Skip to content

Commit 51da8cc

Browse files
renestraubdpgeorge
authored andcommitted
stm32/eth: Add Ethernet support for H5 MCUs.
This commit implements Ethernet support for STM32H5. Changes are: - Add Cortex-M33 MPU code. Ethernet driver requires MPU to define cache strategy for DMA buffers (descriptors and frames). - Add support for STM32H5 Ethernet controller. The controller is mostly compatible with the STM32H7. However the descriptor layout is different. - Adapt clocking and reset for STM32H5. Tested on NUCLEO-H563ZI and STM32H573I-DK, using ping and iperf3. TCP rates of 80-90 Mbits/sec were achievable. Signed-off-by: Rene Straub <[email protected]> Signed-off-by: Damien George <[email protected]>
1 parent 8b12923 commit 51da8cc

File tree

2 files changed

+136
-32
lines changed

2 files changed

+136
-32
lines changed

ports/stm32/eth.c

+85-31
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,19 @@
6262
#define PHY_SCSR_SPEED_100FULL (6 << PHY_SCSR_SPEED_Pos)
6363

6464
// ETH DMA RX and TX descriptor definitions
65-
#if defined(STM32H7)
65+
#if defined(STM32H5)
66+
#define RX_DESCR_3_OWN_Pos (31)
67+
#define RX_DESCR_3_IOC_Pos (30)
68+
#define RX_DESCR_3_BUF1V_Pos (24)
69+
#define RX_DESCR_3_PL_Msk (0x7fff)
70+
71+
#define TX_DESCR_3_OWN_Pos (31)
72+
#define TX_DESCR_3_FD_Pos (29)
73+
#define TX_DESCR_3_LD_Pos (28)
74+
#define TX_DESCR_3_CIC_Pos (16)
75+
#define TX_DESCR_2_B1L_Pos (0)
76+
#define TX_DESCR_2_B1L_Msk (0x3fff << TX_DESCR_2_B1L_Pos)
77+
#elif defined(STM32H7)
6678
#define RX_DESCR_3_OWN_Pos (31)
6779
#define RX_DESCR_3_IOC_Pos (30)
6880
#define RX_DESCR_3_BUF1V_Pos (24)
@@ -135,7 +147,7 @@ STATIC void eth_mac_deinit(eth_t *self);
135147
STATIC void eth_process_frame(eth_t *self, size_t len, const uint8_t *buf);
136148

137149
STATIC void eth_phy_write(uint32_t reg, uint32_t val) {
138-
#if defined(STM32H7)
150+
#if defined(STM32H5) || defined(STM32H7)
139151
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
140152
}
141153
uint32_t ar = ETH->MACMDIOAR;
@@ -161,7 +173,7 @@ STATIC void eth_phy_write(uint32_t reg, uint32_t val) {
161173
}
162174

163175
STATIC uint32_t eth_phy_read(uint32_t reg) {
164-
#if defined(STM32H7)
176+
#if defined(STM32H5) || defined(STM32H7)
165177
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
166178
}
167179
uint32_t ar = ETH->MACMDIOAR;
@@ -202,7 +214,11 @@ void eth_init(eth_t *self, int mac_idx) {
202214
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_TXD1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_RMII_TXD1);
203215

204216
// Enable peripheral clock
205-
#if defined(STM32H7)
217+
#if defined(STM32H5)
218+
__HAL_RCC_ETH_CLK_ENABLE();
219+
__HAL_RCC_ETHTX_CLK_ENABLE();
220+
__HAL_RCC_ETHRX_CLK_ENABLE();
221+
#elif defined(STM32H7)
206222
__HAL_RCC_ETH1MAC_CLK_ENABLE();
207223
__HAL_RCC_ETH1TX_CLK_ENABLE();
208224
__HAL_RCC_ETH1RX_CLK_ENABLE();
@@ -218,11 +234,20 @@ void eth_set_trace(eth_t *self, uint32_t value) {
218234
STATIC int eth_mac_init(eth_t *self) {
219235
// Configure MPU
220236
uint32_t irq_state = mpu_config_start();
237+
#if defined(STM32H5)
238+
mpu_config_region(MPU_REGION_ETH, (uint32_t)&eth_dma, MPU_CONFIG_ETH(16 * 1024));
239+
#else
221240
mpu_config_region(MPU_REGION_ETH, (uint32_t)&eth_dma, MPU_CONFIG_ETH(MPU_REGION_SIZE_16KB));
241+
#endif
222242
mpu_config_end(irq_state);
223243

224244
// Enable peripheral clock
225-
#if defined(STM32H7)
245+
#if defined(STM32H5)
246+
__HAL_RCC_ETH_CLK_ENABLE();
247+
__HAL_RCC_ETHTX_CLK_ENABLE();
248+
__HAL_RCC_ETHRX_CLK_ENABLE();
249+
__HAL_RCC_ETH_FORCE_RESET();
250+
#elif defined(STM32H7)
226251
__HAL_RCC_ETH1MAC_CLK_ENABLE();
227252
__HAL_RCC_ETH1TX_CLK_ENABLE();
228253
__HAL_RCC_ETH1RX_CLK_ENABLE();
@@ -233,14 +258,23 @@ STATIC int eth_mac_init(eth_t *self) {
233258
#endif
234259

235260
// Select RMII interface
236-
#if defined(STM32H7)
261+
#if defined(STM32H5)
262+
__HAL_RCC_SBS_CLK_ENABLE();
263+
SBS->PMCR = (SBS->PMCR & ~SBS_PMCR_ETH_SEL_PHY_Msk) | SBS_PMCR_ETH_SEL_PHY_2;
264+
#elif defined(STM32H7)
237265
SYSCFG->PMCR = (SYSCFG->PMCR & ~SYSCFG_PMCR_EPIS_SEL_Msk) | SYSCFG_PMCR_EPIS_SEL_2;
238266
#else
239267
__HAL_RCC_SYSCFG_CLK_ENABLE();
240268
SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
241269
#endif
242270

243-
#if defined(STM32H7)
271+
#if defined(STM32H5)
272+
__HAL_RCC_ETH_RELEASE_RESET();
273+
274+
__HAL_RCC_ETH_CLK_SLEEP_ENABLE();
275+
__HAL_RCC_ETHTX_CLK_SLEEP_ENABLE();
276+
__HAL_RCC_ETHRX_CLK_SLEEP_ENABLE();
277+
#elif defined(STM32H7)
244278
__HAL_RCC_ETH1MAC_RELEASE_RESET();
245279

246280
__HAL_RCC_ETH1MAC_CLK_SLEEP_ENABLE();
@@ -255,7 +289,7 @@ STATIC int eth_mac_init(eth_t *self) {
255289
#endif
256290

257291
// Do a soft reset of the MAC core
258-
#if defined(STM32H7)
292+
#if defined(STM32H5) || defined(STM32H7)
259293
#define ETH_SOFT_RESET(eth) do { eth->DMAMR = ETH_DMAMR_SWR; } while (0)
260294
#define ETH_IS_RESET(eth) (eth->DMAMR & ETH_DMAMR_SWR)
261295
#else
@@ -277,7 +311,23 @@ STATIC int eth_mac_init(eth_t *self) {
277311
// Set MII clock range
278312
uint32_t hclk = HAL_RCC_GetHCLKFreq();
279313
uint32_t cr_div;
280-
#if defined(STM32H7)
314+
#if defined(STM32H5)
315+
cr_div = ETH->MACMDIOAR & ~ETH_MACMDIOAR_CR;
316+
if (hclk < 35000000) {
317+
cr_div |= ETH_MACMDIOAR_CR_DIV16;
318+
} else if (hclk < 60000000) {
319+
cr_div |= ETH_MACMDIOAR_CR_DIV26;
320+
} else if (hclk < 100000000) {
321+
cr_div |= ETH_MACMDIOAR_CR_DIV42;
322+
} else if (hclk < 150000000) {
323+
cr_div |= ETH_MACMDIOAR_CR_DIV62;
324+
} else if (hclk < 250000000) {
325+
cr_div |= ETH_MACMDIOAR_CR_DIV102;
326+
} else {
327+
cr_div |= ETH_MACMDIOAR_CR_DIV124;
328+
}
329+
ETH->MACMDIOAR = cr_div;
330+
#elif defined(STM32H7)
281331
cr_div = ETH->MACMDIOAR & ~ETH_MACMDIOAR_CR;
282332
if (hclk < 35000000) {
283333
cr_div |= ETH_MACMDIOAR_CR_DIV16;
@@ -306,7 +356,7 @@ STATIC int eth_mac_init(eth_t *self) {
306356
ETH->MACMIIAR = cr_div;
307357
#endif
308358

309-
#if defined(STM32H7)
359+
#if defined(STM32H5) || defined(STM32H7)
310360
// don't skip 32bit words since our descriptors are continuous in memory
311361
ETH->DMACCR &= ~(ETH_DMACCR_DSL_Msk);
312362
#endif
@@ -351,15 +401,15 @@ STATIC int eth_mac_init(eth_t *self) {
351401
uint16_t phy_scsr = eth_phy_read(PHY_SCSR);
352402

353403
// Burst mode configuration
354-
#if defined(STM32H7)
404+
#if defined(STM32H5) || defined(STM32H7)
355405
ETH->DMASBMR = ETH->DMASBMR & ~ETH_DMASBMR_AAL & ~ETH_DMASBMR_FB;
356406
#else
357407
ETH->DMABMR = 0;
358408
#endif
359409
mp_hal_delay_ms(2);
360410

361411
// Select DMA interrupts
362-
#if defined(STM32H7)
412+
#if defined(STM32H5) || defined(STM32H7)
363413
ETH->DMACIER = ETH->DMACIER
364414
| ETH_DMACIER_NIE // enable normal interrupts
365415
| ETH_DMACIER_RIE // enable RX interrupt
@@ -373,7 +423,7 @@ STATIC int eth_mac_init(eth_t *self) {
373423

374424
// Configure RX descriptor lists
375425
for (size_t i = 0; i < RX_BUF_NUM; ++i) {
376-
#if defined(STM32H7)
426+
#if defined(STM32H5) || defined(STM32H7)
377427
eth_dma.rx_descr[i].rdes3 =
378428
1 << RX_DESCR_3_OWN_Pos
379429
| (1 << RX_DESCR_3_BUF1V_Pos) // buf1 address valid
@@ -391,7 +441,7 @@ STATIC int eth_mac_init(eth_t *self) {
391441
#endif
392442
}
393443

394-
#if defined(STM32H7)
444+
#if defined(STM32H5) || defined(STM32H7)
395445
ETH->DMACRDLAR = (uint32_t)&eth_dma.rx_descr[0];
396446
#else
397447
ETH->DMARDLAR = (uint32_t)&eth_dma.rx_descr[0];
@@ -400,7 +450,7 @@ STATIC int eth_mac_init(eth_t *self) {
400450

401451
// Configure TX descriptor lists
402452
for (size_t i = 0; i < TX_BUF_NUM; ++i) {
403-
#if defined(STM32H7)
453+
#if defined(STM32H5) || defined(STM32H7)
404454
eth_dma.tx_descr[i].tdes0 = 0;
405455
eth_dma.tx_descr[i].tdes1 = 0;
406456
eth_dma.tx_descr[i].tdes2 = TX_BUF_SIZE & TX_DESCR_2_B1L_Msk;
@@ -413,7 +463,7 @@ STATIC int eth_mac_init(eth_t *self) {
413463
#endif
414464
}
415465

416-
#if defined(STM32H7)
466+
#if defined(STM32H5) || defined(STM32H7)
417467
// set number of descriptors and buffers
418468
ETH->DMACTDRLR = TX_BUF_NUM - 1;
419469
ETH->DMACRDRLR = RX_BUF_NUM - 1;
@@ -425,7 +475,7 @@ STATIC int eth_mac_init(eth_t *self) {
425475
eth_dma.tx_descr_idx = 0;
426476

427477
// Configure DMA
428-
#if defined(STM32H7)
478+
#if defined(STM32H5) || defined(STM32H7)
429479
// read from RX FIFO only after a full frame is written
430480
ETH->MTLRQOMR = ETH_MTLRQOMR_RSF;
431481
// transmission starts when a full packet resides in the Tx queue
@@ -439,7 +489,7 @@ STATIC int eth_mac_init(eth_t *self) {
439489
mp_hal_delay_ms(2);
440490

441491
// Select MAC filtering options
442-
#if defined(STM32H7)
492+
#if defined(STM32H5) || defined(STM32H7)
443493
ETH->MACPFR = ETH_MACPFR_RA; // pass all frames up
444494
#else
445495
ETH->MACFFR =
@@ -472,7 +522,7 @@ STATIC int eth_mac_init(eth_t *self) {
472522
mp_hal_delay_ms(2);
473523

474524
// Start DMA layer
475-
#if defined(STM32H7)
525+
#if defined(STM32H5) || defined(STM32H7)
476526
ETH->DMACRCR |= ETH_DMACRCR_SR; // start RX
477527
ETH->DMACTCR |= ETH_DMACTCR_ST; // start TX
478528
#else
@@ -493,7 +543,11 @@ STATIC int eth_mac_init(eth_t *self) {
493543
STATIC void eth_mac_deinit(eth_t *self) {
494544
(void)self;
495545
HAL_NVIC_DisableIRQ(ETH_IRQn);
496-
#if defined(STM32H7)
546+
#if defined(STM32H5)
547+
__HAL_RCC_ETH_FORCE_RESET();
548+
__HAL_RCC_ETH_RELEASE_RESET();
549+
__HAL_RCC_ETH_CLK_DISABLE();
550+
#elif defined(STM32H7)
497551
__HAL_RCC_ETH1MAC_FORCE_RESET();
498552
__HAL_RCC_ETH1MAC_RELEASE_RESET();
499553
__HAL_RCC_ETH1MAC_CLK_DISABLE();
@@ -513,7 +567,7 @@ STATIC int eth_tx_buf_get(size_t len, uint8_t **buf) {
513567
eth_dma_tx_descr_t *tx_descr = &eth_dma.tx_descr[eth_dma.tx_descr_idx];
514568
uint32_t t0 = mp_hal_ticks_ms();
515569
for (;;) {
516-
#if defined(STM32H7)
570+
#if defined(STM32H5) || defined(STM32H7)
517571
if (!(tx_descr->tdes3 & (1 << TX_DESCR_3_OWN_Pos))) {
518572
break;
519573
}
@@ -527,7 +581,7 @@ STATIC int eth_tx_buf_get(size_t len, uint8_t **buf) {
527581
}
528582
}
529583

530-
#if defined(STM32H7)
584+
#if defined(STM32H5) || defined(STM32H7)
531585
// Update TX descriptor with length and buffer pointer
532586
*buf = &eth_dma.tx_buf[eth_dma.tx_descr_idx * TX_BUF_SIZE];
533587
tx_descr->tdes2 = len & TX_DESCR_2_B1L_Msk;
@@ -549,7 +603,7 @@ STATIC int eth_tx_buf_send(void) {
549603
eth_dma.tx_descr_idx = (eth_dma.tx_descr_idx + 1) % TX_BUF_NUM;
550604

551605
// Schedule to send next outgoing frame
552-
#if defined(STM32H7)
606+
#if defined(STM32H5) || defined(STM32H7)
553607
tx_descr->tdes3 =
554608
1 << TX_DESCR_3_OWN_Pos // owned by DMA
555609
| 1 << TX_DESCR_3_LD_Pos // last segment
@@ -568,7 +622,7 @@ STATIC int eth_tx_buf_send(void) {
568622

569623
// Notify ETH DMA that there is a new TX descriptor for sending
570624
__DMB();
571-
#if defined(STM32H7)
625+
#if defined(STM32H5) || defined(STM32H7)
572626
if (ETH->DMACSR & ETH_DMACSR_TBU) {
573627
ETH->DMACSR = ETH_DMACSR_TBU;
574628
}
@@ -590,7 +644,7 @@ STATIC void eth_dma_rx_free(void) {
590644
eth_dma.rx_descr_idx = (eth_dma.rx_descr_idx + 1) % RX_BUF_NUM;
591645

592646
// Schedule to get next incoming frame
593-
#if defined(STM32H7)
647+
#if defined(STM32H5) || defined(STM32H7)
594648
rx_descr->rdes0 = (uint32_t)buf;
595649
rx_descr->rdes3 = 1 << RX_DESCR_3_OWN_Pos; // owned by DMA
596650
rx_descr->rdes3 |= 1 << RX_DESCR_3_BUF1V_Pos; // buf 1 address valid
@@ -607,15 +661,15 @@ STATIC void eth_dma_rx_free(void) {
607661

608662
// Notify ETH DMA that there is a new RX descriptor available
609663
__DMB();
610-
#if defined(STM32H7)
664+
#if defined(STM32H5) || defined(STM32H7)
611665
ETH->DMACRDTPR = (uint32_t)&rx_descr[eth_dma.rx_descr_idx];
612666
#else
613667
ETH->DMARPDR = 0;
614668
#endif
615669
}
616670

617671
void ETH_IRQHandler(void) {
618-
#if defined(STM32H7)
672+
#if defined(STM32H5) || defined(STM32H7)
619673
uint32_t sr = ETH->DMACSR;
620674
ETH->DMACSR = ETH_DMACSR_NIS;
621675
uint32_t rx_interrupt = sr & ETH_DMACSR_RI;
@@ -625,13 +679,13 @@ void ETH_IRQHandler(void) {
625679
uint32_t rx_interrupt = sr & ETH_DMASR_RS;
626680
#endif
627681
if (rx_interrupt) {
628-
#if defined(STM32H7)
682+
#if defined(STM32H5) || defined(STM32H7)
629683
ETH->DMACSR = ETH_DMACSR_RI;
630684
#else
631685
ETH->DMASR = ETH_DMASR_RS;
632686
#endif
633687
for (;;) {
634-
#if defined(STM32H7)
688+
#if defined(STM32H5) || defined(STM32H7)
635689
eth_dma_rx_descr_t *rx_descr_l = &eth_dma.rx_descr[eth_dma.rx_descr_idx];
636690
if (rx_descr_l->rdes3 & (1 << RX_DESCR_3_OWN_Pos)) {
637691
// No more RX descriptors ready to read
@@ -646,13 +700,13 @@ void ETH_IRQHandler(void) {
646700
#endif
647701

648702
// Get RX buffer containing new frame
649-
#if defined(STM32H7)
703+
#if defined(STM32H5) || defined(STM32H7)
650704
size_t len = (rx_descr_l->rdes3 & RX_DESCR_3_PL_Msk);
651705
#else
652706
size_t len = (rx_descr->rdes0 & RX_DESCR_0_FL_Msk) >> RX_DESCR_0_FL_Pos;
653707
#endif
654708
len -= 4; // discard CRC at end
655-
#if defined(STM32H7)
709+
#if defined(STM32H5) || defined(STM32H7)
656710
uint8_t *buf = &eth_dma.rx_buf[eth_dma.rx_descr_idx * RX_BUF_SIZE];
657711
#else
658712
uint8_t *buf = (uint8_t *)rx_descr->rdes2;

0 commit comments

Comments
 (0)