1616#endif
1717
1818#if defined(STM32H5 )
19- #if TZEN_ENABLED
20- #define ETH_BASE 0x50028000UL /* Secure alias */
21- #else
22- #define ETH_BASE 0x40028000UL /* Non-secure alias */
23- #endif
19+ /* Always use the NS alias of ETH on H5. Both wolfIP build modes run in
20+ * the Non-Secure world: TZEN=0 has no security distinction, and TZEN=1
21+ * runs as a NS application launched by wolfBoot (plain LDR/STR carry
22+ * HNONSEC=1 and would fault on a 0x5xxxxxxx access). */
23+ #define ETH_BASE 0x40028000UL
2424#define STM32_ETH_NEEDS_MDIO_DELAY 0
2525#elif defined(STM32H7 )
2626#define ETH_BASE 0x40028000UL
@@ -207,14 +207,16 @@ struct eth_desc {
207207#if defined(STM32H7 ) || defined(STM32N6 )
208208#define ETH_SECTION __attribute__((section(".eth_buffers")))
209209#elif defined(STM32H5 )
210- #if TZEN_ENABLED
211- #define ETH_SECTION __attribute__((section(".eth_buffers")))
212- #else
210+ /* H5 places ETH descriptors and buffers in the regular .bss region.
211+ * Both TZEN=0 (TrustZone disabled) and TZEN=1 (NS app under wolfBoot)
212+ * link RAM into a single NS-accessible region; no separate ETHMEM
213+ * alias is needed since the CPU and ETH DMA both run in NS world and
214+ * share the same NS view of physical SRAM. */
213215#define ETH_SECTION
214216#endif
215- #endif
216217
217- /* DMA buffer address — use secure alias (0x34), matching RISAF SEC=1. */
218+ /* DMA descriptor / buffer addresses are taken as-is. NS pointers map
219+ * directly to NS DMA accesses on H5; H7 / N6 use identity mapping. */
218220#define ETH_DMA_ADDR (ptr ) ((uint32_t)(ptr))
219221
220222static struct eth_desc rx_ring [RX_DESC_COUNT ] __attribute__((aligned (32 ))) ETH_SECTION ;
@@ -235,6 +237,9 @@ static int32_t phy_addr = -1;
235237
236238static uint32_t rx_poll_count = 0 ;
237239static uint32_t rx_pkt_count = 0 ;
240+ #ifdef DEBUG_H5_ETH
241+ static uint32_t tx_send_count = 0 ;
242+ #endif
238243
239244static uint16_t eth_mdio_read (uint32_t phy , uint32_t reg );
240245static void eth_mdio_write (uint32_t phy , uint32_t reg , uint16_t value );
@@ -256,7 +261,7 @@ static int eth_hw_reset(void)
256261 * (HAL uses 1 second). Do NOT manually clear SWR — it corrupts DMA. */
257262 timeout = 50000000U ; /* ~80ms at 600MHz */
258263#else
259- timeout = 1000000U ;
264+ timeout = 5000000U ;
260265#endif
261266
262267 ETH_DMAMR |= ETH_DMAMR_SWR ;
@@ -664,9 +669,10 @@ static void eth_phy_init(void)
664669 }
665670 }
666671
667- /* Reset PHY. */
672+ /* Reset PHY. PHY reset typically completes in <1 ms; allow ~1 s
673+ * worst case at the H5's 32 MHz HSI / CR=4 MDC speed. */
668674 eth_mdio_write ((uint32_t )phy_addr , PHY_REG_BCR , PHY_BCR_RESET );
669- timeout = 100000U ;
675+ timeout = 5000U ;
670676 do {
671677 ctrl = eth_mdio_read ((uint32_t )phy_addr , PHY_REG_BCR );
672678 } while ((ctrl & PHY_BCR_RESET ) != 0U && -- timeout != 0U );
@@ -677,15 +683,19 @@ static void eth_phy_init(void)
677683 ctrl |= PHY_BCR_AUTONEG_ENABLE | PHY_BCR_RESTART_AUTONEG ;
678684 eth_mdio_write ((uint32_t )phy_addr , PHY_REG_BCR , ctrl );
679685
680- /* Wait for auto-negotiation complete. */
681- timeout = 100000U ;
686+ /* Wait for auto-negotiation complete. With a cable plugged in
687+ * aneg takes ~3 s; without a cable it never completes. Cap the
688+ * wait so boot proceeds (with link DOWN) in ~5 s instead of ~40 s. */
689+ timeout = 20000U ;
682690 do {
683691 bsr = eth_mdio_read ((uint32_t )phy_addr , PHY_REG_BSR );
684692 bsr |= eth_mdio_read ((uint32_t )phy_addr , PHY_REG_BSR );
685693 } while ((bsr & PHY_BSR_AUTONEG_COMPLETE ) == 0U && -- timeout != 0U );
686694
687- /* Wait for link up. */
688- timeout = 100000U ;
695+ /* Wait for link up. Link comes up promptly once aneg finishes;
696+ * a short timeout is enough -- if there is no cable the previous
697+ * loop has already burned its budget. */
698+ timeout = 5000U ;
689699 do {
690700 bsr = eth_mdio_read ((uint32_t )phy_addr , PHY_REG_BSR );
691701 bsr |= eth_mdio_read ((uint32_t )phy_addr , PHY_REG_BSR );
@@ -779,6 +789,9 @@ static int eth_send(struct wolfIP_ll_dev *dev, void *frame, uint32_t len)
779789 next_idx = (tx_idx + 1U ) % TX_DESC_COUNT ;
780790 ETH_DMACTXDTPR = ETH_DMA_ADDR (& tx_ring [next_idx ]);
781791 tx_idx = next_idx ;
792+ #ifdef DEBUG_H5_ETH
793+ tx_send_count ++ ;
794+ #endif
782795
783796 return (int )len ;
784797}
@@ -827,6 +840,47 @@ uint32_t stm32_eth_get_dmacsr(void)
827840 return val ;
828841}
829842
843+ #ifdef DEBUG_H5_ETH
844+ /* H5 MAC frame counters (MMC) - read-only, free-running.
845+ * ETH base 0x40028000, MMC offsets:
846+ * 0x0114 MMC Tx Single Collision Good Frames -> not us
847+ * 0x014C TX FRAMES OK BY CNT (TXSNGLCOLG_GBPF.. actual)
848+ * Simpler: use generic MAC_TX_PACKET_COUNT_GOOD = 0x40028068
849+ * and MAC_RX_PACKET_COUNT_GOOD = 0x4002809C
850+ * But H5 uses MMC: TX 0x0768 RX 0x0794 (good_packet counters).
851+ * Reference: RM0481 Rev2 Sec 60.8.4.
852+ */
853+ #define ETH_MMC_TX_PACKET_GOOD ETH_REG(0x0768U)
854+ #define ETH_MMC_RX_PACKET_GOOD ETH_REG(0x0794U)
855+ #define ETH_MMC_RX_CRC_ERR ETH_REG(0x0794U + 0x10U) /* 0x07A4 */
856+
857+ uint32_t stm32_eth_get_tx_count (void )
858+ {
859+ return tx_send_count ;
860+ }
861+
862+ uint32_t stm32_eth_get_tx_des3 (uint32_t i )
863+ {
864+ if (i >= TX_DESC_COUNT ) return 0xFFFFFFFFU ;
865+ return tx_ring [i ].des3 ;
866+ }
867+
868+ uint32_t stm32_eth_get_mac_rx_frames (void )
869+ {
870+ return ETH_MMC_RX_PACKET_GOOD ;
871+ }
872+
873+ uint32_t stm32_eth_get_mac_tx_frames (void )
874+ {
875+ return ETH_MMC_TX_PACKET_GOOD ;
876+ }
877+
878+ uint32_t stm32_eth_get_mac_rx_errors (void )
879+ {
880+ return ETH_MMC_RX_CRC_ERR ;
881+ }
882+ #endif
883+
830884int stm32_eth_init (struct wolfIP_ll_dev * ll , const uint8_t * mac )
831885{
832886 uint8_t local_mac [6 ];
0 commit comments