108108#define PHY_INIT_TIMEOUT_MS (10000)
109109#define PHY_AUTONEG_TIMEOUT_MS (5000)
110110
111- #define RX_BUF_SIZE (1524) // includes 4-byte CRC at end
112- #define TX_BUF_SIZE (1524)
111+ // These buffer sizes need to be a multiple of 8 (for STM32N6 at least).
112+ #define RX_BUF_SIZE (1528) // includes 4-byte CRC at end
113+ #define TX_BUF_SIZE (1528)
113114
114115#define RX_BUF_NUM (5)
115116#define TX_BUF_NUM (5)
@@ -156,7 +157,7 @@ static void eth_lwip_init(eth_t *self);
156157static int eth_phy_init (eth_t * self );
157158
158159void eth_phy_write (uint32_t phy_addr , uint32_t reg , uint32_t val ) {
159- #if defined(STM32H5 ) || defined(STM32H7 )
160+ #if defined(STM32H5 ) || defined(STM32H7 ) || defined( STM32N6 )
160161 while (ETH -> MACMDIOAR & ETH_MACMDIOAR_MB ) {
161162 }
162163 uint32_t ar = ETH -> MACMDIOAR ;
@@ -184,7 +185,7 @@ void eth_phy_write(uint32_t phy_addr, uint32_t reg, uint32_t val) {
184185}
185186
186187uint32_t eth_phy_read (uint32_t phy_addr , uint32_t reg ) {
187- #if defined(STM32H5 ) || defined(STM32H7 )
188+ #if defined(STM32H5 ) || defined(STM32H7 ) || defined( STM32N6 )
188189 while (ETH -> MACMDIOAR & ETH_MACMDIOAR_MB ) {
189190 }
190191 uint32_t ar = ETH -> MACMDIOAR ;
@@ -296,7 +297,7 @@ void eth_set_trace(eth_t *self, uint32_t value) {
296297static int eth_mac_init (eth_t * self ) {
297298 // Configure MPU
298299 uint32_t irq_state = mpu_config_start ();
299- #if defined(STM32H5 )
300+ #if defined(STM32H5 ) || defined( STM32N6 )
300301 mpu_config_region (MPU_REGION_ETH , (uint32_t )& eth_dma , MPU_CONFIG_ETH (16 * 1024 ));
301302 #else
302303 mpu_config_region (MPU_REGION_ETH , (uint32_t )& eth_dma , MPU_CONFIG_ETH (MPU_REGION_SIZE_16KB ));
@@ -316,8 +317,10 @@ static int eth_mac_init(eth_t *self) {
316317
317318 // Configure clock sources for N6
318319 #if defined(STM32N6 )
319- LL_RCC_SetETH1TXClockSource (LL_RCC_ETH1TX_CLKSOURCE_HSE );
320- LL_RCC_SetETH1RXClockSource (LL_RCC_ETH1RX_CLKSOURCE_HSE );
320+ LL_RCC_SetETHREFTXClockSource (LL_RCC_ETH1REFTX_CLKSOURCE_EXT ); // max 25MHz
321+ LL_RCC_SetETHREFRXClockSource (LL_RCC_ETH1REFRX_CLKSOURCE_EXT ); // max 125MHz
322+ LL_RCC_SetETHClockSource (LL_RCC_ETH1_CLKSOURCE_IC12 ); // max 125MHz
323+ LL_RCC_SetETH1PTPDivider (LL_RCC_ETH1PTP_DIV_1 );
321324 LL_RCC_SetETHPTPClockSource (LL_RCC_ETH1PTP_CLKSOURCE_HCLK ); // max 200MHz
322325 #endif
323326
@@ -389,7 +392,7 @@ static int eth_mac_init(eth_t *self) {
389392 // Set MII clock range
390393 uint32_t hclk = HAL_RCC_GetHCLKFreq ();
391394 uint32_t cr_div ;
392- #if defined(STM32H5 )
395+ #if defined(STM32H5 ) || defined( STM32N6 )
393396 cr_div = ETH -> MACMDIOAR & ~ETH_MACMDIOAR_CR ;
394397 if (hclk < 35000000 ) {
395398 cr_div |= ETH_MACMDIOAR_CR_DIV16 ;
@@ -434,6 +437,11 @@ static int eth_mac_init(eth_t *self) {
434437 ETH -> MACMIIAR = cr_div ;
435438 #endif
436439
440+ #if defined(STM32H5 ) || defined(STM32H7 ) || defined(STM32N6 )
441+ // Set 1us tick counter for MAC operation
442+ WRITE_REG (ETH -> MAC1USTCR , HAL_RCC_GetHCLKFreq () / 1000000U - 1U );
443+ #endif
444+
437445 #if defined(STM32H5 ) || defined(STM32H7 )
438446 // don't skip 32bit words since our descriptors are continuous in memory
439447 ETH -> DMACCR &= ~(ETH_DMACCR_DSL_Msk );
@@ -442,7 +450,7 @@ static int eth_mac_init(eth_t *self) {
442450 #endif
443451
444452 // Burst mode configuration
445- #if defined(STM32H5 ) || defined(STM32H7 )
453+ #if defined(STM32H5 ) || defined(STM32H7 ) || defined( STM32N6 )
446454 ETH -> DMASBMR = ETH -> DMASBMR & ~ETH_DMASBMR_AAL & ~ETH_DMASBMR_FB ;
447455 #else
448456 ETH -> DMABMR = 0 ;
@@ -455,6 +463,8 @@ static int eth_mac_init(eth_t *self) {
455463 | ETH_DMACIER_NIE // enable normal interrupts
456464 | ETH_DMACIER_RIE // enable RX interrupt
457465 ;
466+ #elif defined(STM32N6 )
467+ ETH -> DMA_CH [0 ].DMACIER = ETH_DMACxIER_NIE | ETH_DMACxIER_RIE ;
458468 #else
459469 ETH -> DMAIER =
460470 ETH_DMAIER_NISE // enable normal interrupts
@@ -464,7 +474,7 @@ static int eth_mac_init(eth_t *self) {
464474
465475 // Configure RX descriptor lists
466476 for (size_t i = 0 ; i < RX_BUF_NUM ; ++ i ) {
467- #if defined(STM32H5 ) || defined(STM32H7 )
477+ #if defined(STM32H5 ) || defined(STM32H7 ) || defined( STM32N6 )
468478 eth_dma .rx_descr [i ].rdes3 =
469479 1 << RX_DESCR_3_OWN_Pos
470480 | (1 << RX_DESCR_3_BUF1V_Pos ) // buf1 address valid
@@ -484,14 +494,18 @@ static int eth_mac_init(eth_t *self) {
484494
485495 #if defined(STM32H5 ) || defined(STM32H7 )
486496 ETH -> DMACRDLAR = (uint32_t )& eth_dma .rx_descr [0 ];
497+ #elif defined(STM32N6 )
498+ ETH -> DMA_CH [0 ].DMACRXRLR = RX_BUF_NUM - 1 ;
499+ ETH -> DMA_CH [0 ].DMACRXDLAR = (uint32_t )& eth_dma .rx_descr [0 ];
500+ ETH -> DMA_CH [0 ].DMACRXDTPR = (uint32_t )& eth_dma .rx_descr [RX_BUF_NUM - 1 ];
487501 #else
488502 ETH -> DMARDLAR = (uint32_t )& eth_dma .rx_descr [0 ];
489503 #endif
490504 eth_dma .rx_descr_idx = 0 ;
491505
492506 // Configure TX descriptor lists
493507 for (size_t i = 0 ; i < TX_BUF_NUM ; ++ i ) {
494- #if defined(STM32H5 ) || defined(STM32H7 )
508+ #if defined(STM32H5 ) || defined(STM32H7 ) || defined( STM32N6 )
495509 eth_dma .tx_descr [i ].tdes0 = 0 ;
496510 eth_dma .tx_descr [i ].tdes1 = 0 ;
497511 eth_dma .tx_descr [i ].tdes2 = TX_BUF_SIZE & TX_DESCR_2_B1L_Msk ;
@@ -510,6 +524,10 @@ static int eth_mac_init(eth_t *self) {
510524 ETH -> DMACRDRLR = RX_BUF_NUM - 1 ;
511525
512526 ETH -> DMACTDLAR = (uint32_t )& eth_dma .tx_descr [0 ];
527+ #elif defined(STM32N6 )
528+ ETH -> DMA_CH [0 ].DMACTXRLR = TX_BUF_NUM - 1 ;
529+ ETH -> DMA_CH [0 ].DMACTXDLAR = (uint32_t )& eth_dma .tx_descr [0 ];
530+ ETH -> DMA_CH [0 ].DMACTXDTPR = (uint32_t )& eth_dma .tx_descr [0 ];
513531 #else
514532 ETH -> DMATDLAR = (uint32_t )& eth_dma .tx_descr [0 ];
515533 #endif
@@ -521,6 +539,9 @@ static int eth_mac_init(eth_t *self) {
521539 ETH -> MTLRQOMR = ETH_MTLRQOMR_RSF ;
522540 // transmission starts when a full packet resides in the Tx queue
523541 ETH -> MTLTQOMR = ETH_MTLTQOMR_TSF ;
542+ #elif defined(STM32N6 )
543+ ETH -> MTL_QUEUE [0 ].MTLRXQOMR = ETH_MTLRXQxOMR_RSF ;
544+ ETH -> MTL_QUEUE [0 ].MTLTXQOMR = ETH_MTLTXQxOMR_TSF ;
524545 #else
525546 ETH -> DMAOMR =
526547 ETH_DMAOMR_RSF // read from RX FIFO after a full frame is written
@@ -530,7 +551,7 @@ static int eth_mac_init(eth_t *self) {
530551 mp_hal_delay_ms (2 );
531552
532553 // Select MAC filtering options
533- #if defined(STM32H5 ) || defined(STM32H7 )
554+ #if defined(STM32H5 ) || defined(STM32H7 ) || defined( STM32N6 )
534555 ETH -> MACPFR = ETH_MACPFR_RA ; // pass all frames up
535556 #else
536557 ETH -> MACFFR =
@@ -586,13 +607,17 @@ static int eth_mac_init(eth_t *self) {
586607 ETH -> DMACRCR |= ETH_DMACRCR_SR ; // start RX
587608 ETH -> DMACTCR |= ETH_DMACTCR_ST ; // start TX
588609 #elif defined(STM32N6 )
589- ETH -> MTL_QUEUE [0 ].MTLTXQOMR |= ETH_MTLTXQxOMR_FTQ ; // flush TX FIFO
590- ETH -> MTL_QUEUE [1 ].MTLTXQOMR |= ETH_MTLTXQxOMR_FTQ ; // flush TX FIFO
610+ // Flush TX FIFOs before starting
611+ ETH -> MTL_QUEUE [0 ].MTLTXQOMR |= ETH_MTLTXQxOMR_FTQ ;
612+ ETH -> MTL_QUEUE [1 ].MTLTXQOMR |= ETH_MTLTXQxOMR_FTQ ;
613+ // Configure RX buffer size and start RX
591614 ETH -> DMA_CH [0 ].DMACRXCR = RX_BUF_SIZE << ETH_DMACxRXCR_RBSZ_Pos ;
592- ETH -> DMA_CH [0 ].DMACRXCR |= ETH_DMACxRXCR_SR ; // start RX
615+ ETH -> DMA_CH [0 ].DMACRXCR |= ETH_DMACxRXCR_SR ;
616+ // Configure TX and start TX
593617 ETH -> DMA_CH [0 ].DMACTXCR = 4 << ETH_DMACxTXCR_TXPBL_Pos ;
594- ETH -> DMA_CH [0 ].DMACTXCR |= ETH_DMACxTXCR_ST ; // start TX
595- ETH -> DMA_CH [0 ].DMACSR |= ETH_DMACxSR_TPS | ETH_DMACxSR_RPS ; // clear TX/RX process stopped flags
618+ ETH -> DMA_CH [0 ].DMACTXCR |= ETH_DMACxTXCR_ST ;
619+ // Clear TX/RX process stopped flags
620+ ETH -> DMA_CH [0 ].DMACSR |= ETH_DMACxSR_TPS | ETH_DMACxSR_RPS ;
596621 #else
597622 ETH -> DMAOMR |=
598623 ETH_DMAOMR_ST // start TX
@@ -694,11 +719,16 @@ static int eth_tx_buf_send(void) {
694719
695720 // Notify ETH DMA that there is a new TX descriptor for sending
696721 __DMB ();
697- #if defined(STM32H5 ) || defined(STM32H7 ) || defined( STM32N6 )
722+ #if defined(STM32H5 ) || defined(STM32H7 )
698723 if (ETH -> DMACSR & ETH_DMACSR_TBU ) {
699724 ETH -> DMACSR = ETH_DMACSR_TBU ;
700725 }
701726 ETH -> DMACTDTPR = (uint32_t )& eth_dma .tx_descr [eth_dma .tx_descr_idx ];
727+ #elif defined(STM32N6 )
728+ if (ETH -> DMA_CH [0 ].DMACSR & ETH_DMACxSR_TBU ) {
729+ ETH -> DMA_CH [0 ].DMACSR = ETH_DMACxSR_TBU ;
730+ }
731+ ETH -> DMA_CH [0 ].DMACTXDTPR = (uint32_t )& eth_dma .tx_descr [eth_dma .tx_descr_idx ];
702732 #else
703733 if (ETH -> DMASR & ETH_DMASR_TBUS ) {
704734 ETH -> DMASR = ETH_DMASR_TBUS ;
@@ -716,7 +746,7 @@ static void eth_dma_rx_free(void) {
716746 eth_dma .rx_descr_idx = (eth_dma .rx_descr_idx + 1 ) % RX_BUF_NUM ;
717747
718748 // Schedule to get next incoming frame
719- #if defined(STM32H5 ) || defined(STM32H7 )
749+ #if defined(STM32H5 ) || defined(STM32H7 ) || defined( STM32N6 )
720750 rx_descr -> rdes0 = (uint32_t )buf ;
721751 rx_descr -> rdes3 = 1 << RX_DESCR_3_OWN_Pos ; // owned by DMA
722752 rx_descr -> rdes3 |= 1 << RX_DESCR_3_BUF1V_Pos ; // buf 1 address valid
@@ -735,6 +765,8 @@ static void eth_dma_rx_free(void) {
735765 __DMB ();
736766 #if defined(STM32H5 ) || defined(STM32H7 )
737767 ETH -> DMACRDTPR = (uint32_t )& rx_descr [eth_dma .rx_descr_idx ];
768+ #elif defined(STM32N6 )
769+ ETH -> DMA_CH [0 ].DMACRXDTPR = (uint32_t )& eth_dma .rx_descr [eth_dma .rx_descr_idx ];
738770 #else
739771 ETH -> DMARPDR = 0 ;
740772 #endif
@@ -1174,6 +1206,8 @@ void eth_low_power_mode(eth_t *self, bool enable) {
11741206 // Enable eth clock
11751207 #if defined(STM32H7 )
11761208 __HAL_RCC_ETH1MAC_CLK_ENABLE ();
1209+ #elif defined(STM32N6 )
1210+ __HAL_RCC_ETH1_CLK_ENABLE ();
11771211 #else
11781212 __HAL_RCC_ETH_CLK_ENABLE ();
11791213 #endif
@@ -1185,6 +1219,8 @@ void eth_low_power_mode(eth_t *self, bool enable) {
11851219 // Disable eth clock.
11861220 #if defined(STM32H7 )
11871221 __HAL_RCC_ETH1MAC_CLK_DISABLE ();
1222+ #elif defined(STM32N6 )
1223+ __HAL_RCC_ETH1_CLK_DISABLE ();
11881224 #else
11891225 __HAL_RCC_ETH_CLK_DISABLE ();
11901226 #endif
0 commit comments