Skip to content

Commit e924518

Browse files
committed
stm32/eth: Add N6 ethernet driver support.
Add STM32N6 support to the ethernet driver with RMII/RGMII interface configuration, proper clock setup, and DMA descriptor handling for the N6's ethernet peripheral. Changes include: - N6 clock source configuration for REFTX/REFRX/PTP - MAC1USTCR tick counter setup - DMA channel 0 interrupt and descriptor configuration - TX/RX buffer size adjusted to 1528 (multiple of 8 for N6) - Low power mode clock enable/disable for N6 Signed-off-by: Andrew Leech <[email protected]>
1 parent 95a887e commit e924518

File tree

1 file changed

+55
-19
lines changed

1 file changed

+55
-19
lines changed

ports/stm32/eth.c

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,9 @@
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);
156157
static int eth_phy_init(eth_t *self);
157158

158159
void 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

186187
uint32_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) {
296297
static 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

Comments
 (0)