@@ -132,9 +132,9 @@ eth_t eth_instance;
132132
133133static void eth_mac_deinit (eth_t * self );
134134static void eth_process_frame (eth_t * self , size_t len , const uint8_t * buf );
135- static void eth_netif_init_early (eth_t * self );
136- static void eth_phy_link_status_poll (eth_t * self );
135+ static void eth_lwip_init (eth_t * self );
137136static void eth_phy_configure_autoneg (eth_t * self );
137+ static int eth_phy_init (eth_t * self );
138138
139139void eth_phy_write (uint32_t phy_addr , uint32_t reg , uint32_t val ) {
140140 #if defined(STM32H5 ) || defined(STM32H7 )
@@ -230,8 +230,8 @@ int eth_init(eth_t *self, int mac_idx, uint32_t phy_addr, int phy_type) {
230230 __HAL_RCC_ETH_CLK_ENABLE ();
231231 #endif
232232
233- // Initialize netif structure early so static IP can be configured before active(True)
234- eth_netif_init_early (self );
233+ // Initialize netif and register with LWIP
234+ eth_lwip_init (self );
235235
236236 return 0 ;
237237}
@@ -270,25 +270,26 @@ static int eth_mac_init(eth_t *self) {
270270 __HAL_RCC_SYSCFG_CLK_ENABLE ();
271271 SYSCFG -> PMC |= SYSCFG_PMC_MII_RMII_SEL ;
272272 #endif
273- // #if defined(STM32H5)
274- // __HAL_RCC_ETH_RELEASE_RESET();
275-
276- // __HAL_RCC_ETH_CLK_SLEEP_DISABLE();
277- // __HAL_RCC_ETHTX_CLK_SLEEP_DISABLE();
278- // __HAL_RCC_ETHRX_CLK_SLEEP_DISABLE();
279- // #elif defined(STM32H7)
280- // __HAL_RCC_ETH1MAC_RELEASE_RESET();
281-
282- // __HAL_RCC_ETH1MAC_CLK_SLEEP_DISABLE();
283- // __HAL_RCC_ETH1TX_CLK_SLEEP_DISABLE();
284- // __HAL_RCC_ETH1RX_CLK_SLEEP_DISABLE();
285- // #else
286- // __HAL_RCC_ETHMAC_RELEASE_RESET();
287-
288- // __HAL_RCC_ETHMAC_CLK_SLEEP_DISABLE();
289- // __HAL_RCC_ETHMACTX_CLK_SLEEP_DISABLE();
290- // __HAL_RCC_ETHMACRX_CLK_SLEEP_DISABLE();
291- // #endif
273+
274+ #if defined(STM32H5 )
275+ __HAL_RCC_ETH_RELEASE_RESET ();
276+
277+ __HAL_RCC_ETH_CLK_SLEEP_DISABLE ();
278+ __HAL_RCC_ETHTX_CLK_SLEEP_DISABLE ();
279+ __HAL_RCC_ETHRX_CLK_SLEEP_DISABLE ();
280+ #elif defined(STM32H7 )
281+ __HAL_RCC_ETH1MAC_RELEASE_RESET ();
282+
283+ __HAL_RCC_ETH1MAC_CLK_SLEEP_DISABLE ();
284+ __HAL_RCC_ETH1TX_CLK_SLEEP_DISABLE ();
285+ __HAL_RCC_ETH1RX_CLK_SLEEP_DISABLE ();
286+ #else
287+ __HAL_RCC_ETHMAC_RELEASE_RESET ();
288+
289+ __HAL_RCC_ETHMAC_CLK_SLEEP_DISABLE ();
290+ __HAL_RCC_ETHMACTX_CLK_SLEEP_DISABLE ();
291+ __HAL_RCC_ETHMACRX_CLK_SLEEP_DISABLE ();
292+ #endif
292293
293294 // Do a soft reset of the MAC core
294295 #if defined(STM32H5 ) || defined(STM32H7 )
@@ -378,33 +379,6 @@ static int eth_mac_init(eth_t *self) {
378379 ETH -> DMACCR &= ~(ETH_DMACCR_DSL_Msk );
379380 #endif
380381
381- // Reset the PHY and wait for reset to complete
382- eth_phy_write (self -> phy_addr , PHY_BCR , PHY_BCR_SOFT_RESET );
383- mp_hal_delay_ms (50 );
384-
385- // Wait for PHY reset to complete (but don't wait for link)
386- t0 = mp_hal_ticks_ms ();
387- while (eth_phy_read (self -> phy_addr , PHY_BCR ) & PHY_BCR_SOFT_RESET ) {
388- if (mp_hal_ticks_ms () - t0 > 1000 ) { // 1 second timeout for reset
389- eth_mac_deinit (self );
390- return - MP_ETIMEDOUT ;
391- }
392- mp_hal_delay_ms (2 );
393- }
394-
395- // Initialize link status tracking (current state, whatever it is)
396- uint16_t bsr = eth_phy_read (self -> phy_addr , PHY_BSR );
397- self -> last_link_status = (bsr & PHY_BSR_LINK_STATUS ) != 0 ;
398-
399- // Configure autonegotiation if link is already up, otherwise it will be
400- // configured when link comes up via the polling function
401- if (self -> last_link_status ) {
402- eth_phy_configure_autoneg (self );
403- }
404-
405- // Enable PHY link change interrupts (for future use if PHY interrupt pin available)
406- eth_phy_enable_link_interrupts (self -> phy_addr );
407-
408382 // Burst mode configuration
409383 #if defined(STM32H5 ) || defined(STM32H7 )
410384 ETH -> DMASBMR = ETH -> DMASBMR & ~ETH_DMASBMR_AAL & ~ETH_DMASBMR_FB ;
@@ -718,14 +692,6 @@ void ETH_IRQHandler(void) {
718692 eth_dma_rx_free ();
719693 }
720694 }
721-
722- // Check for PHY link status changes (polled approach)
723- // This runs on every RX interrupt, providing reasonable responsiveness
724- static uint32_t link_check_counter = 0 ;
725- if (++ link_check_counter >= 100 ) { // Check every ~100 RX interrupts
726- link_check_counter = 0 ;
727- eth_phy_link_status_poll (& eth_instance );
728- }
729695}
730696
731697/*******************************************************************************/
@@ -791,7 +757,8 @@ static err_t eth_netif_init(struct netif *netif) {
791757 return ERR_OK ;
792758}
793759
794- static void eth_netif_init_early (eth_t * self ) {
760+ static void eth_lwip_init (eth_t * self ) {
761+ MICROPY_PY_LWIP_ENTER
795762 // Initialize netif structure but don't add to network stack yet
796763 struct netif * n = & self -> netif ;
797764 n -> name [0 ] = 'e' ;
@@ -805,48 +772,19 @@ static void eth_netif_init_early(eth_t *self) {
805772 IP_ADDR4 (& ipconfig [2 ], 192 , 168 , 0 , 1 ); // Gateway
806773 IP_ADDR4 (& ipconfig [3 ], 8 , 8 , 8 , 8 ); // DNS
807774
808- netif_set_addr (n , ip_2_ip4 (& ipconfig [0 ]), ip_2_ip4 (& ipconfig [1 ]), ip_2_ip4 (& ipconfig [2 ]));
775+ netif_add (n , ip_2_ip4 (& ipconfig [0 ]), ip_2_ip4 (& ipconfig [1 ]), ip_2_ip4 (& ipconfig [2 ]), self , eth_netif_init , ethernet_input );
776+ netif_set_hostname (n , mod_network_hostname_data );
777+
778+ ip_addr_t dns_addr ;
779+ IP_ADDR4 (& dns_addr , 8 , 8 , 8 , 8 );
780+ dns_setserver (0 , & dns_addr );
809781
810782 // Initialize DHCP structure
811783 dhcp_set_struct (n , & self -> dhcp_struct );
812- }
813-
814- static void eth_lwip_init (eth_t * self ) {
815- MICROPY_PY_LWIP_ENTER
816-
817- struct netif * n = & self -> netif ;
818-
819- // Add netif to network stack (only if not already added)
820- if (netif_find (n -> name ) == NULL ) {
821- ip_addr_t dns_addr ;
822- IP_ADDR4 (& dns_addr , 8 , 8 , 8 , 8 );
823-
824- netif_add (n , netif_ip4_addr (n ), netif_ip4_netmask (n ), netif_ip4_gw (n ), self , eth_netif_init , ethernet_input );
825- netif_set_hostname (n , mod_network_hostname_data );
826- netif_set_default (n );
827- netif_set_up (n );
828-
829- dns_setserver (0 , & dns_addr );
830-
831- #if LWIP_IPV6
832- netif_create_ip6_linklocal_address (n , 1 );
833- #endif
834- }
835-
836- MICROPY_PY_LWIP_EXIT
837- }
838-
839- static void eth_start_dhcp_if_needed (eth_t * self ) {
840- MICROPY_PY_LWIP_ENTER
841- struct netif * netif = & self -> netif ;
842-
843- // Check if a static IP address has been configured
844- if (ip4_addr_isany_val (* netif_ip4_addr (netif ))) {
845- // No static IP configured, start DHCP
846- dhcp_start (netif );
847- }
848- // If static IP is already configured, don't start DHCP
849784
785+ #if LWIP_IPV6
786+ netif_create_ip6_linklocal_address (n , 1 );
787+ #endif
850788 MICROPY_PY_LWIP_EXIT
851789}
852790
@@ -866,7 +804,11 @@ static void eth_phy_configure_autoneg(eth_t *self) {
866804 eth_phy_write (self -> phy_addr , PHY_BCR , PHY_BCR_AUTONEG_EN );
867805}
868806
869- static void eth_phy_link_status_poll (eth_t * self ) {
807+ void eth_phy_link_status_poll () {
808+ eth_t * self = & eth_instance ;
809+ if (!self -> enabled ) {
810+ return ;
811+ }
870812 // Poll PHY link status and handle state changes
871813 uint16_t bsr = eth_phy_read (self -> phy_addr , PHY_BSR );
872814 bool current_link_status = (bsr & PHY_BSR_LINK_STATUS ) != 0 ;
@@ -877,6 +819,7 @@ static void eth_phy_link_status_poll(eth_t *self) {
877819
878820 // Update LWIP netif link status to reflect physical cable connection
879821 struct netif * netif = & self -> netif ;
822+ MICROPY_PY_LWIP_ENTER
880823 if (current_link_status ) {
881824 // Cable is physically connected
882825 netif_set_link_up (netif );
@@ -895,28 +838,10 @@ static void eth_phy_link_status_poll(eth_t *self) {
895838 // Cable is physically disconnected
896839 netif_set_link_down (netif );
897840 }
841+ MICROPY_PY_LWIP_EXIT
898842 }
899843}
900844
901- static void eth_lwip_deinit (eth_t * self ) {
902- MICROPY_PY_LWIP_ENTER
903- struct netif * netif = & self -> netif ;
904-
905- // Stop DHCP if running
906- if (netif_dhcp_data (netif )) {
907- dhcp_stop (netif );
908- }
909-
910- // Remove from network stack but keep netif structure for reuse
911- for (struct netif * n = netif_list ; n != NULL ; n = n -> next ) {
912- if (n == netif ) {
913- netif_remove (n );
914- break ;
915- }
916- }
917- MICROPY_PY_LWIP_EXIT
918- }
919-
920845static void eth_process_frame (eth_t * self , size_t len , const uint8_t * buf ) {
921846 eth_trace (self , len , buf , NETUTILS_TRACE_NEWLINE );
922847
@@ -937,17 +862,21 @@ struct netif *eth_netif(eth_t *self) {
937862}
938863
939864int eth_link_status (eth_t * self ) {
865+ // Do a quick poll to ensure link status is current
866+ eth_phy_link_status_poll ();
867+
940868 struct netif * netif = & self -> netif ;
941869 if ((netif -> flags & (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP ))
942870 == (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP )) {
943871 if (!ip4_addr_isany_val (* netif_ip4_addr (netif ))) {
944- return 3 ; // link up
872+ return 3 ; // link up with IP
945873 } else {
946- return 2 ; // link no-ip;
874+ return 2 ; // link up, no IP
947875 }
948876 } else {
949- if (eth_phy_read (self -> phy_addr , PHY_BSR ) & PHY_BSR_LINK_STATUS ) {
950- return 1 ; // link up
877+ // Use tracked link status instead of direct PHY read
878+ if (self -> last_link_status ) {
879+ return 1 ; // physical link up but interface down
951880 } else {
952881 return 0 ; // link down
953882 }
@@ -967,21 +896,51 @@ int eth_start(eth_t *self) {
967896 return ret ;
968897 }
969898
970- // Initialize LWIP netif (only once, safe to call multiple times)
971- eth_lwip_init (self );
899+ // Initialize PHY (reset and configure)
900+ ret = eth_phy_init (self );
901+ if (ret < 0 ) {
902+ eth_mac_deinit (self );
903+ return ret ;
904+ }
905+
906+ // Give PHY time to settle after initialization
907+ // mp_hal_delay_ms(100);
908+
909+ MICROPY_PY_LWIP_ENTER
910+ struct netif * n = & self -> netif ;
911+
912+ // Enable the interface in LWIP
913+ netif_set_default (n );
914+ netif_set_up (n );
972915
973916 // Start DHCP if no static IP has been configured
974- eth_start_dhcp_if_needed (self );
917+ if (ip4_addr_isany_val (* netif_ip4_addr (n ))) {
918+ // No static IP configured, start DHCP
919+ dhcp_start (n );
920+ }
975921
976- // Do an initial link status poll
977- eth_phy_link_status_poll (self );
922+ MICROPY_PY_LWIP_EXIT
923+
924+ // Do an initial link status poll after PHY has had time to initialize
925+ eth_phy_link_status_poll ();
978926
979927 self -> enabled = true;
980928 return 0 ;
981929}
982930
983931int eth_stop (eth_t * self ) {
984- eth_lwip_deinit (self );
932+ // Stop DHCP if running
933+ if (netif_dhcp_data (& self -> netif )) {
934+ dhcp_stop (& self -> netif );
935+ }
936+ netif_set_down (& self -> netif );
937+
938+ // Shutdown PHY
939+ eth_low_power_mode (self , true);
940+
941+ // Clear link status tracking
942+ self -> last_link_status = false;
943+
985944 eth_mac_deinit (self );
986945 self -> enabled = false;
987946 return 0 ;
@@ -1012,4 +971,30 @@ void eth_low_power_mode(eth_t *self, bool enable) {
1012971 eth_phy_write (self -> phy_addr , PHY_BCR , bcr & (~PHY_BCR_POWER_DOWN ));
1013972 }
1014973}
974+
975+ static int eth_phy_init (eth_t * self ) {
976+ // Reset the PHY and wait for reset to complete
977+ eth_phy_write (self -> phy_addr , PHY_BCR , PHY_BCR_SOFT_RESET );
978+ mp_hal_delay_ms (10 );
979+
980+ // Wait for PHY reset to complete (but don't wait for link)
981+ uint32_t t0 = mp_hal_ticks_ms ();
982+ while (eth_phy_read (self -> phy_addr , PHY_BCR ) & PHY_BCR_SOFT_RESET ) {
983+ if (mp_hal_ticks_ms () - t0 > 1000 ) { // 1 second timeout for reset
984+ return - MP_ETIMEDOUT ;
985+ }
986+ mp_hal_delay_ms (2 );
987+ }
988+
989+ // Initialize link status tracking (current state, whatever it is)
990+ self -> last_link_status = false;
991+ eth_phy_link_status_poll ();
992+
993+ // Enable PHY link change interrupts (for future use if PHY interrupt pin available)
994+
995+ eth_phy_enable_link_interrupts (self -> phy_addr );
996+
997+ return 0 ;
998+ }
999+
10151000#endif // defined(MICROPY_HW_ETH_MDC)
0 commit comments