@@ -129,6 +129,9 @@ eth_t eth_instance;
129
129
130
130
static void eth_mac_deinit (eth_t * self );
131
131
static void eth_process_frame (eth_t * self , size_t len , const uint8_t * buf );
132
+ static void eth_netif_init_early (eth_t * self );
133
+ static void eth_phy_link_status_poll (eth_t * self );
134
+ static void eth_phy_configure_autoneg (eth_t * self );
132
135
133
136
void eth_phy_write (uint32_t phy_addr , uint32_t reg , uint32_t val ) {
134
137
#if defined(STM32H5 ) || defined(STM32H7 )
@@ -223,6 +226,10 @@ int eth_init(eth_t *self, int mac_idx, uint32_t phy_addr, int phy_type) {
223
226
#else
224
227
__HAL_RCC_ETH_CLK_ENABLE ();
225
228
#endif
229
+
230
+ // Initialize netif structure early so static IP can be configured before active(True)
231
+ eth_netif_init_early (self );
232
+
226
233
return 0 ;
227
234
}
228
235
@@ -253,6 +260,7 @@ static int eth_mac_init(eth_t *self) {
253
260
#if defined(STM32H5 )
254
261
__HAL_RCC_SBS_CLK_ENABLE ();
255
262
SBS -> PMCR = (SBS -> PMCR & ~SBS_PMCR_ETH_SEL_PHY_Msk ) | SBS_PMCR_ETH_SEL_PHY_2 ;
263
+ HAL_SBS_ETHInterfaceSelect (SBS_ETH_RMII );
256
264
#elif defined(STM32H7 )
257
265
SYSCFG -> PMCR = (SYSCFG -> PMCR & ~SYSCFG_PMCR_EPIS_SEL_Msk ) | SYSCFG_PMCR_EPIS_SEL_2 ;
258
266
#else
@@ -262,22 +270,10 @@ static int eth_mac_init(eth_t *self) {
262
270
263
271
#if defined(STM32H5 )
264
272
__HAL_RCC_ETH_RELEASE_RESET ();
265
-
266
- __HAL_RCC_ETH_CLK_SLEEP_ENABLE ();
267
- __HAL_RCC_ETHTX_CLK_SLEEP_ENABLE ();
268
- __HAL_RCC_ETHRX_CLK_SLEEP_ENABLE ();
269
273
#elif defined(STM32H7 )
270
274
__HAL_RCC_ETH1MAC_RELEASE_RESET ();
271
-
272
- __HAL_RCC_ETH1MAC_CLK_SLEEP_ENABLE ();
273
- __HAL_RCC_ETH1TX_CLK_SLEEP_ENABLE ();
274
- __HAL_RCC_ETH1RX_CLK_SLEEP_ENABLE ();
275
275
#else
276
276
__HAL_RCC_ETHMAC_RELEASE_RESET ();
277
-
278
- __HAL_RCC_ETHMAC_CLK_SLEEP_ENABLE ();
279
- __HAL_RCC_ETHMACTX_CLK_SLEEP_ENABLE ();
280
- __HAL_RCC_ETHMACRX_CLK_SLEEP_ENABLE ();
281
277
#endif
282
278
283
279
// Do a soft reset of the MAC core
@@ -353,57 +349,30 @@ static int eth_mac_init(eth_t *self) {
353
349
ETH -> DMACCR &= ~(ETH_DMACCR_DSL_Msk );
354
350
#endif
355
351
356
- // Reset the PHY
352
+ // Reset the PHY and wait for reset to complete
357
353
eth_phy_write (self -> phy_addr , PHY_BCR , PHY_BCR_SOFT_RESET );
358
354
mp_hal_delay_ms (50 );
359
355
360
- // Wait for the PHY link to be established
361
- int phy_state = 0 ;
356
+ // Wait for PHY reset to complete (but don't wait for link)
362
357
t0 = mp_hal_ticks_ms ();
363
- while (phy_state != 3 ) {
364
- if (mp_hal_ticks_ms () - t0 > PHY_INIT_TIMEOUT_MS ) {
358
+ while (eth_phy_read ( self -> phy_addr , PHY_BCR ) & PHY_BCR_SOFT_RESET ) {
359
+ if (mp_hal_ticks_ms () - t0 > 1000 ) { // 1 second timeout for reset
365
360
eth_mac_deinit (self );
366
361
return - MP_ETIMEDOUT ;
367
362
}
368
- uint16_t bcr = eth_phy_read (self -> phy_addr , PHY_BCR );
369
- uint16_t bsr = eth_phy_read (self -> phy_addr , PHY_BSR );
370
- switch (phy_state ) {
371
- case 0 :
372
- if (!(bcr & PHY_BCR_SOFT_RESET )) {
373
- phy_state = 1 ;
374
- }
375
- break ;
376
- case 1 :
377
- if (bsr & PHY_BSR_LINK_STATUS ) {
378
- // Announce all modes
379
- eth_phy_write (self -> phy_addr , PHY_ANAR ,
380
- PHY_ANAR_SPEED_10HALF |
381
- PHY_ANAR_SPEED_10FULL |
382
- PHY_ANAR_SPEED_100HALF |
383
- PHY_ANAR_SPEED_100FULL |
384
- PHY_ANAR_IEEE802_3 );
385
- // Start autonegotiate.
386
- eth_phy_write (self -> phy_addr , PHY_BCR , PHY_BCR_AUTONEG_EN );
387
- phy_state = 2 ;
388
- }
389
- break ;
390
- case 2 :
391
- if ((bsr & (PHY_BSR_AUTONEG_DONE | PHY_BSR_LINK_STATUS ))
392
- == (PHY_BSR_AUTONEG_DONE | PHY_BSR_LINK_STATUS )) {
393
- phy_state = 3 ;
394
- }
395
- break ;
396
- }
397
363
mp_hal_delay_ms (2 );
398
364
}
399
365
400
- // Get register with link status
401
- uint16_t phy_scsr = self -> phy_get_link_status (self -> phy_addr );
402
-
403
- // Initialize link status tracking
366
+ // Initialize link status tracking (current state, whatever it is)
404
367
uint16_t bsr = eth_phy_read (self -> phy_addr , PHY_BSR );
405
368
self -> last_link_status = (bsr & PHY_BSR_LINK_STATUS ) != 0 ;
406
369
370
+ // Configure autonegotiation if link is already up, otherwise it will be
371
+ // configured when link comes up via the polling function
372
+ if (self -> last_link_status ) {
373
+ eth_phy_configure_autoneg (self );
374
+ }
375
+
407
376
// Enable PHY link change interrupts (for future use if PHY interrupt pin available)
408
377
eth_phy_enable_link_interrupts (self -> phy_addr );
409
378
@@ -512,13 +481,9 @@ static int eth_mac_init(eth_t *self) {
512
481
ETH -> MACA0LR = mac [3 ] << 24 | mac [2 ] << 16 | mac [1 ] << 8 | mac [0 ];
513
482
mp_hal_delay_ms (2 );
514
483
515
- // Set main MAC control register
516
- ETH -> MACCR =
517
- phy_scsr == PHY_SPEED_10FULL ? ETH_MACCR_DM
518
- : phy_scsr == PHY_SPEED_100HALF ? ETH_MACCR_FES
519
- : phy_scsr == PHY_SPEED_100FULL ? (ETH_MACCR_FES | ETH_MACCR_DM )
520
- : 0
521
- ;
484
+ // Set main MAC control register with default configuration
485
+ // The PHY speed/duplex will be auto-detected and updated via autonegotiation
486
+ ETH -> MACCR = ETH_MACCR_FES | ETH_MACCR_DM ; // Default: 100Mbps, Full Duplex
522
487
mp_hal_delay_ms (2 );
523
488
524
489
// Start MAC layer
@@ -730,29 +695,7 @@ void ETH_IRQHandler(void) {
730
695
static uint32_t link_check_counter = 0 ;
731
696
if (++ link_check_counter >= 100 ) { // Check every ~100 RX interrupts
732
697
link_check_counter = 0 ;
733
-
734
- // Read current PHY link status
735
- uint16_t bsr = eth_phy_read (eth_instance .phy_addr , PHY_BSR );
736
- bool current_link_status = (bsr & PHY_BSR_LINK_STATUS ) != 0 ;
737
-
738
- // Check if link status changed
739
- if (current_link_status != eth_instance .last_link_status ) {
740
- eth_instance .last_link_status = current_link_status ;
741
-
742
- // Update LWIP netif link status to reflect physical cable connection
743
- struct netif * netif = & eth_instance .netif ;
744
- if (current_link_status ) {
745
- // Cable is physically connected
746
- netif_set_link_up (netif );
747
- // Restart DHCP if interface is up and DHCP is enabled
748
- if (netif_is_up (netif ) && netif_dhcp_data (netif )) {
749
- dhcp_renew (netif );
750
- }
751
- } else {
752
- // Cable is physically disconnected
753
- netif_set_link_down (netif );
754
- }
755
- }
698
+ eth_phy_link_status_poll (& eth_instance );
756
699
}
757
700
}
758
701
@@ -815,39 +758,127 @@ static err_t eth_netif_init(struct netif *netif) {
815
758
return ERR_OK ;
816
759
}
817
760
818
- static void eth_lwip_init (eth_t * self ) {
761
+ static void eth_netif_init_early (eth_t * self ) {
762
+ // Initialize netif structure but don't add to network stack yet
763
+ struct netif * n = & self -> netif ;
764
+ n -> name [0 ] = 'e' ;
765
+ n -> name [1 ] = '0' ;
766
+ n -> state = self ;
767
+
768
+ // Set default IP configuration (0.0.0.0 = use DHCP)
819
769
ip_addr_t ipconfig [4 ];
820
- IP4_ADDR (& ipconfig [0 ], 0 , 0 , 0 , 0 );
821
- IP4_ADDR (& ipconfig [2 ], 192 , 168 , 0 , 1 );
822
- IP4_ADDR (& ipconfig [1 ], 255 , 255 , 255 , 0 );
823
- IP4_ADDR (& ipconfig [3 ], 8 , 8 , 8 , 8 );
770
+ IP_ADDR4 (& ipconfig [0 ], 0 , 0 , 0 , 0 ); // IP: 0.0.0.0 (DHCP)
771
+ IP_ADDR4 (& ipconfig [1 ], 255 , 255 , 255 , 0 ); // Netmask
772
+ IP_ADDR4 (& ipconfig [2 ], 192 , 168 , 0 , 1 ); // Gateway
773
+ IP_ADDR4 (& ipconfig [3 ], 8 , 8 , 8 , 8 ); // DNS
774
+
775
+ netif_set_addr (n , ip_2_ip4 (& ipconfig [0 ]), ip_2_ip4 (& ipconfig [1 ]), ip_2_ip4 (& ipconfig [2 ]));
776
+
777
+ // Initialize DHCP structure
778
+ dhcp_set_struct (n , & self -> dhcp_struct );
779
+ }
824
780
781
+ static void eth_lwip_init (eth_t * self ) {
825
782
MICROPY_PY_LWIP_ENTER
826
783
827
784
struct netif * n = & self -> netif ;
828
- n -> name [0 ] = 'e' ;
829
- n -> name [1 ] = '0' ;
830
- netif_add (n , & ipconfig [0 ], & ipconfig [1 ], & ipconfig [2 ], self , eth_netif_init , ethernet_input );
831
- netif_set_hostname (n , mod_network_hostname_data );
832
- netif_set_default (n );
833
- netif_set_up (n );
834
785
835
- dns_setserver (0 , & ipconfig [3 ]);
836
- dhcp_set_struct (n , & self -> dhcp_struct );
837
- dhcp_start (n );
786
+ // Add netif to network stack (only if not already added)
787
+ if (netif_find (n -> name ) == NULL ) {
788
+ ip_addr_t dns_addr ;
789
+ IP_ADDR4 (& dns_addr , 8 , 8 , 8 , 8 );
838
790
839
- netif_set_link_up (n );
791
+ netif_add (n , netif_ip4_addr (n ), netif_ip4_netmask (n ), netif_ip4_gw (n ), self , eth_netif_init , ethernet_input );
792
+ netif_set_hostname (n , mod_network_hostname_data );
793
+ netif_set_default (n );
794
+ netif_set_up (n );
795
+
796
+ dns_setserver (0 , & dns_addr );
797
+
798
+ #if LWIP_IPV6
799
+ netif_create_ip6_linklocal_address (n , 1 );
800
+ #endif
801
+ }
840
802
841
803
MICROPY_PY_LWIP_EXIT
842
804
}
843
805
806
+ static void eth_start_dhcp_if_needed (eth_t * self ) {
807
+ MICROPY_PY_LWIP_ENTER
808
+ struct netif * netif = & self -> netif ;
809
+
810
+ // Check if a static IP address has been configured
811
+ if (ip4_addr_isany_val (* netif_ip4_addr (netif ))) {
812
+ // No static IP configured, start DHCP
813
+ dhcp_start (netif );
814
+ }
815
+ // If static IP is already configured, don't start DHCP
816
+
817
+ MICROPY_PY_LWIP_EXIT
818
+ }
819
+
820
+ static void eth_phy_configure_autoneg (eth_t * self ) {
821
+ // Configure PHY for autonegotiation (non-blocking)
822
+ // This sets up the PHY but doesn't wait for link establishment
823
+
824
+ // Announce all supported modes
825
+ eth_phy_write (self -> phy_addr , PHY_ANAR ,
826
+ PHY_ANAR_SPEED_10HALF |
827
+ PHY_ANAR_SPEED_10FULL |
828
+ PHY_ANAR_SPEED_100HALF |
829
+ PHY_ANAR_SPEED_100FULL |
830
+ PHY_ANAR_IEEE802_3 );
831
+
832
+ // Start autonegotiation
833
+ eth_phy_write (self -> phy_addr , PHY_BCR , PHY_BCR_AUTONEG_EN );
834
+ }
835
+
836
+ static void eth_phy_link_status_poll (eth_t * self ) {
837
+ // Poll PHY link status and handle state changes
838
+ uint16_t bsr = eth_phy_read (self -> phy_addr , PHY_BSR );
839
+ bool current_link_status = (bsr & PHY_BSR_LINK_STATUS ) != 0 ;
840
+
841
+ // Check if link status changed
842
+ if (current_link_status != self -> last_link_status ) {
843
+ self -> last_link_status = current_link_status ;
844
+
845
+ // Update LWIP netif link status to reflect physical cable connection
846
+ struct netif * netif = & self -> netif ;
847
+ if (current_link_status ) {
848
+ // Cable is physically connected
849
+ netif_set_link_up (netif );
850
+
851
+ // If this is a new connection, configure autonegotiation
852
+ uint16_t bcr = eth_phy_read (self -> phy_addr , PHY_BCR );
853
+ if (!(bcr & PHY_BCR_AUTONEG_EN )) {
854
+ eth_phy_configure_autoneg (self );
855
+ }
856
+
857
+ // Restart DHCP if interface is up and DHCP is enabled
858
+ if (netif_is_up (netif ) && netif_dhcp_data (netif )) {
859
+ dhcp_renew (netif );
860
+ }
861
+ } else {
862
+ // Cable is physically disconnected
863
+ netif_set_link_down (netif );
864
+ }
865
+ }
866
+ }
867
+
844
868
static void eth_lwip_deinit (eth_t * self ) {
845
869
MICROPY_PY_LWIP_ENTER
846
- for (struct netif * netif = netif_list ; netif != NULL ; netif = netif -> next ) {
847
- if (netif == & self -> netif ) {
848
- netif_remove (netif );
849
- netif -> ip_addr .addr = 0 ;
850
- netif -> flags = 0 ;
870
+ struct netif * netif = & self -> netif ;
871
+
872
+ // Stop DHCP if running
873
+ if (netif_dhcp_data (netif )) {
874
+ dhcp_stop (netif );
875
+ }
876
+
877
+ // Remove from network stack but keep netif structure for reuse
878
+ for (struct netif * n = netif_list ; n != NULL ; n = n -> next ) {
879
+ if (n == netif ) {
880
+ netif_remove (n );
881
+ break ;
851
882
}
852
883
}
853
884
MICROPY_PY_LWIP_EXIT
@@ -895,16 +926,23 @@ bool eth_is_enabled(eth_t *self) {
895
926
}
896
927
897
928
int eth_start (eth_t * self ) {
898
- eth_lwip_deinit (self );
899
-
900
929
// Make sure Eth is Not in low power mode.
901
930
eth_low_power_mode (self , false);
902
931
903
932
int ret = eth_mac_init (self );
904
933
if (ret < 0 ) {
905
934
return ret ;
906
935
}
936
+
937
+ // Initialize LWIP netif (only once, safe to call multiple times)
907
938
eth_lwip_init (self );
939
+
940
+ // Start DHCP if no static IP has been configured
941
+ eth_start_dhcp_if_needed (self );
942
+
943
+ // Do an initial link status poll
944
+ eth_phy_link_status_poll (self );
945
+
908
946
self -> enabled = true;
909
947
return 0 ;
910
948
}
0 commit comments