kopia lustrzana https://github.com/micropython/micropython
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 <rene@see5.ch> Signed-off-by: Damien George <damien@micropython.org>pull/12226/head
rodzic
8b12923da2
commit
51da8cc28b
|
@ -62,7 +62,19 @@
|
||||||
#define PHY_SCSR_SPEED_100FULL (6 << PHY_SCSR_SPEED_Pos)
|
#define PHY_SCSR_SPEED_100FULL (6 << PHY_SCSR_SPEED_Pos)
|
||||||
|
|
||||||
// ETH DMA RX and TX descriptor definitions
|
// ETH DMA RX and TX descriptor definitions
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5)
|
||||||
|
#define RX_DESCR_3_OWN_Pos (31)
|
||||||
|
#define RX_DESCR_3_IOC_Pos (30)
|
||||||
|
#define RX_DESCR_3_BUF1V_Pos (24)
|
||||||
|
#define RX_DESCR_3_PL_Msk (0x7fff)
|
||||||
|
|
||||||
|
#define TX_DESCR_3_OWN_Pos (31)
|
||||||
|
#define TX_DESCR_3_FD_Pos (29)
|
||||||
|
#define TX_DESCR_3_LD_Pos (28)
|
||||||
|
#define TX_DESCR_3_CIC_Pos (16)
|
||||||
|
#define TX_DESCR_2_B1L_Pos (0)
|
||||||
|
#define TX_DESCR_2_B1L_Msk (0x3fff << TX_DESCR_2_B1L_Pos)
|
||||||
|
#elif defined(STM32H7)
|
||||||
#define RX_DESCR_3_OWN_Pos (31)
|
#define RX_DESCR_3_OWN_Pos (31)
|
||||||
#define RX_DESCR_3_IOC_Pos (30)
|
#define RX_DESCR_3_IOC_Pos (30)
|
||||||
#define RX_DESCR_3_BUF1V_Pos (24)
|
#define RX_DESCR_3_BUF1V_Pos (24)
|
||||||
|
@ -135,7 +147,7 @@ STATIC void eth_mac_deinit(eth_t *self);
|
||||||
STATIC void eth_process_frame(eth_t *self, size_t len, const uint8_t *buf);
|
STATIC void eth_process_frame(eth_t *self, size_t len, const uint8_t *buf);
|
||||||
|
|
||||||
STATIC void eth_phy_write(uint32_t reg, uint32_t val) {
|
STATIC void eth_phy_write(uint32_t reg, uint32_t val) {
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
|
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
|
||||||
}
|
}
|
||||||
uint32_t ar = ETH->MACMDIOAR;
|
uint32_t ar = ETH->MACMDIOAR;
|
||||||
|
@ -161,7 +173,7 @@ STATIC void eth_phy_write(uint32_t reg, uint32_t val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC uint32_t eth_phy_read(uint32_t reg) {
|
STATIC uint32_t eth_phy_read(uint32_t reg) {
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
|
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
|
||||||
}
|
}
|
||||||
uint32_t ar = ETH->MACMDIOAR;
|
uint32_t ar = ETH->MACMDIOAR;
|
||||||
|
@ -202,7 +214,11 @@ void eth_init(eth_t *self, int mac_idx) {
|
||||||
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);
|
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);
|
||||||
|
|
||||||
// Enable peripheral clock
|
// Enable peripheral clock
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5)
|
||||||
|
__HAL_RCC_ETH_CLK_ENABLE();
|
||||||
|
__HAL_RCC_ETHTX_CLK_ENABLE();
|
||||||
|
__HAL_RCC_ETHRX_CLK_ENABLE();
|
||||||
|
#elif defined(STM32H7)
|
||||||
__HAL_RCC_ETH1MAC_CLK_ENABLE();
|
__HAL_RCC_ETH1MAC_CLK_ENABLE();
|
||||||
__HAL_RCC_ETH1TX_CLK_ENABLE();
|
__HAL_RCC_ETH1TX_CLK_ENABLE();
|
||||||
__HAL_RCC_ETH1RX_CLK_ENABLE();
|
__HAL_RCC_ETH1RX_CLK_ENABLE();
|
||||||
|
@ -218,11 +234,20 @@ void eth_set_trace(eth_t *self, uint32_t value) {
|
||||||
STATIC int eth_mac_init(eth_t *self) {
|
STATIC int eth_mac_init(eth_t *self) {
|
||||||
// Configure MPU
|
// Configure MPU
|
||||||
uint32_t irq_state = mpu_config_start();
|
uint32_t irq_state = mpu_config_start();
|
||||||
|
#if defined(STM32H5)
|
||||||
|
mpu_config_region(MPU_REGION_ETH, (uint32_t)ð_dma, MPU_CONFIG_ETH(16 * 1024));
|
||||||
|
#else
|
||||||
mpu_config_region(MPU_REGION_ETH, (uint32_t)ð_dma, MPU_CONFIG_ETH(MPU_REGION_SIZE_16KB));
|
mpu_config_region(MPU_REGION_ETH, (uint32_t)ð_dma, MPU_CONFIG_ETH(MPU_REGION_SIZE_16KB));
|
||||||
|
#endif
|
||||||
mpu_config_end(irq_state);
|
mpu_config_end(irq_state);
|
||||||
|
|
||||||
// Enable peripheral clock
|
// Enable peripheral clock
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5)
|
||||||
|
__HAL_RCC_ETH_CLK_ENABLE();
|
||||||
|
__HAL_RCC_ETHTX_CLK_ENABLE();
|
||||||
|
__HAL_RCC_ETHRX_CLK_ENABLE();
|
||||||
|
__HAL_RCC_ETH_FORCE_RESET();
|
||||||
|
#elif defined(STM32H7)
|
||||||
__HAL_RCC_ETH1MAC_CLK_ENABLE();
|
__HAL_RCC_ETH1MAC_CLK_ENABLE();
|
||||||
__HAL_RCC_ETH1TX_CLK_ENABLE();
|
__HAL_RCC_ETH1TX_CLK_ENABLE();
|
||||||
__HAL_RCC_ETH1RX_CLK_ENABLE();
|
__HAL_RCC_ETH1RX_CLK_ENABLE();
|
||||||
|
@ -233,14 +258,23 @@ STATIC int eth_mac_init(eth_t *self) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Select RMII interface
|
// Select RMII interface
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5)
|
||||||
|
__HAL_RCC_SBS_CLK_ENABLE();
|
||||||
|
SBS->PMCR = (SBS->PMCR & ~SBS_PMCR_ETH_SEL_PHY_Msk) | SBS_PMCR_ETH_SEL_PHY_2;
|
||||||
|
#elif defined(STM32H7)
|
||||||
SYSCFG->PMCR = (SYSCFG->PMCR & ~SYSCFG_PMCR_EPIS_SEL_Msk) | SYSCFG_PMCR_EPIS_SEL_2;
|
SYSCFG->PMCR = (SYSCFG->PMCR & ~SYSCFG_PMCR_EPIS_SEL_Msk) | SYSCFG_PMCR_EPIS_SEL_2;
|
||||||
#else
|
#else
|
||||||
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||||||
SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
|
SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5)
|
||||||
|
__HAL_RCC_ETH_RELEASE_RESET();
|
||||||
|
|
||||||
|
__HAL_RCC_ETH_CLK_SLEEP_ENABLE();
|
||||||
|
__HAL_RCC_ETHTX_CLK_SLEEP_ENABLE();
|
||||||
|
__HAL_RCC_ETHRX_CLK_SLEEP_ENABLE();
|
||||||
|
#elif defined(STM32H7)
|
||||||
__HAL_RCC_ETH1MAC_RELEASE_RESET();
|
__HAL_RCC_ETH1MAC_RELEASE_RESET();
|
||||||
|
|
||||||
__HAL_RCC_ETH1MAC_CLK_SLEEP_ENABLE();
|
__HAL_RCC_ETH1MAC_CLK_SLEEP_ENABLE();
|
||||||
|
@ -255,7 +289,7 @@ STATIC int eth_mac_init(eth_t *self) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Do a soft reset of the MAC core
|
// Do a soft reset of the MAC core
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
#define ETH_SOFT_RESET(eth) do { eth->DMAMR = ETH_DMAMR_SWR; } while (0)
|
#define ETH_SOFT_RESET(eth) do { eth->DMAMR = ETH_DMAMR_SWR; } while (0)
|
||||||
#define ETH_IS_RESET(eth) (eth->DMAMR & ETH_DMAMR_SWR)
|
#define ETH_IS_RESET(eth) (eth->DMAMR & ETH_DMAMR_SWR)
|
||||||
#else
|
#else
|
||||||
|
@ -277,7 +311,23 @@ STATIC int eth_mac_init(eth_t *self) {
|
||||||
// Set MII clock range
|
// Set MII clock range
|
||||||
uint32_t hclk = HAL_RCC_GetHCLKFreq();
|
uint32_t hclk = HAL_RCC_GetHCLKFreq();
|
||||||
uint32_t cr_div;
|
uint32_t cr_div;
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5)
|
||||||
|
cr_div = ETH->MACMDIOAR & ~ETH_MACMDIOAR_CR;
|
||||||
|
if (hclk < 35000000) {
|
||||||
|
cr_div |= ETH_MACMDIOAR_CR_DIV16;
|
||||||
|
} else if (hclk < 60000000) {
|
||||||
|
cr_div |= ETH_MACMDIOAR_CR_DIV26;
|
||||||
|
} else if (hclk < 100000000) {
|
||||||
|
cr_div |= ETH_MACMDIOAR_CR_DIV42;
|
||||||
|
} else if (hclk < 150000000) {
|
||||||
|
cr_div |= ETH_MACMDIOAR_CR_DIV62;
|
||||||
|
} else if (hclk < 250000000) {
|
||||||
|
cr_div |= ETH_MACMDIOAR_CR_DIV102;
|
||||||
|
} else {
|
||||||
|
cr_div |= ETH_MACMDIOAR_CR_DIV124;
|
||||||
|
}
|
||||||
|
ETH->MACMDIOAR = cr_div;
|
||||||
|
#elif defined(STM32H7)
|
||||||
cr_div = ETH->MACMDIOAR & ~ETH_MACMDIOAR_CR;
|
cr_div = ETH->MACMDIOAR & ~ETH_MACMDIOAR_CR;
|
||||||
if (hclk < 35000000) {
|
if (hclk < 35000000) {
|
||||||
cr_div |= ETH_MACMDIOAR_CR_DIV16;
|
cr_div |= ETH_MACMDIOAR_CR_DIV16;
|
||||||
|
@ -306,7 +356,7 @@ STATIC int eth_mac_init(eth_t *self) {
|
||||||
ETH->MACMIIAR = cr_div;
|
ETH->MACMIIAR = cr_div;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
// don't skip 32bit words since our descriptors are continuous in memory
|
// don't skip 32bit words since our descriptors are continuous in memory
|
||||||
ETH->DMACCR &= ~(ETH_DMACCR_DSL_Msk);
|
ETH->DMACCR &= ~(ETH_DMACCR_DSL_Msk);
|
||||||
#endif
|
#endif
|
||||||
|
@ -351,7 +401,7 @@ STATIC int eth_mac_init(eth_t *self) {
|
||||||
uint16_t phy_scsr = eth_phy_read(PHY_SCSR);
|
uint16_t phy_scsr = eth_phy_read(PHY_SCSR);
|
||||||
|
|
||||||
// Burst mode configuration
|
// Burst mode configuration
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
ETH->DMASBMR = ETH->DMASBMR & ~ETH_DMASBMR_AAL & ~ETH_DMASBMR_FB;
|
ETH->DMASBMR = ETH->DMASBMR & ~ETH_DMASBMR_AAL & ~ETH_DMASBMR_FB;
|
||||||
#else
|
#else
|
||||||
ETH->DMABMR = 0;
|
ETH->DMABMR = 0;
|
||||||
|
@ -359,7 +409,7 @@ STATIC int eth_mac_init(eth_t *self) {
|
||||||
mp_hal_delay_ms(2);
|
mp_hal_delay_ms(2);
|
||||||
|
|
||||||
// Select DMA interrupts
|
// Select DMA interrupts
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
ETH->DMACIER = ETH->DMACIER
|
ETH->DMACIER = ETH->DMACIER
|
||||||
| ETH_DMACIER_NIE // enable normal interrupts
|
| ETH_DMACIER_NIE // enable normal interrupts
|
||||||
| ETH_DMACIER_RIE // enable RX interrupt
|
| ETH_DMACIER_RIE // enable RX interrupt
|
||||||
|
@ -373,7 +423,7 @@ STATIC int eth_mac_init(eth_t *self) {
|
||||||
|
|
||||||
// Configure RX descriptor lists
|
// Configure RX descriptor lists
|
||||||
for (size_t i = 0; i < RX_BUF_NUM; ++i) {
|
for (size_t i = 0; i < RX_BUF_NUM; ++i) {
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
eth_dma.rx_descr[i].rdes3 =
|
eth_dma.rx_descr[i].rdes3 =
|
||||||
1 << RX_DESCR_3_OWN_Pos
|
1 << RX_DESCR_3_OWN_Pos
|
||||||
| (1 << RX_DESCR_3_BUF1V_Pos) // buf1 address valid
|
| (1 << RX_DESCR_3_BUF1V_Pos) // buf1 address valid
|
||||||
|
@ -391,7 +441,7 @@ STATIC int eth_mac_init(eth_t *self) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
ETH->DMACRDLAR = (uint32_t)ð_dma.rx_descr[0];
|
ETH->DMACRDLAR = (uint32_t)ð_dma.rx_descr[0];
|
||||||
#else
|
#else
|
||||||
ETH->DMARDLAR = (uint32_t)ð_dma.rx_descr[0];
|
ETH->DMARDLAR = (uint32_t)ð_dma.rx_descr[0];
|
||||||
|
@ -400,7 +450,7 @@ STATIC int eth_mac_init(eth_t *self) {
|
||||||
|
|
||||||
// Configure TX descriptor lists
|
// Configure TX descriptor lists
|
||||||
for (size_t i = 0; i < TX_BUF_NUM; ++i) {
|
for (size_t i = 0; i < TX_BUF_NUM; ++i) {
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
eth_dma.tx_descr[i].tdes0 = 0;
|
eth_dma.tx_descr[i].tdes0 = 0;
|
||||||
eth_dma.tx_descr[i].tdes1 = 0;
|
eth_dma.tx_descr[i].tdes1 = 0;
|
||||||
eth_dma.tx_descr[i].tdes2 = TX_BUF_SIZE & TX_DESCR_2_B1L_Msk;
|
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) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
// set number of descriptors and buffers
|
// set number of descriptors and buffers
|
||||||
ETH->DMACTDRLR = TX_BUF_NUM - 1;
|
ETH->DMACTDRLR = TX_BUF_NUM - 1;
|
||||||
ETH->DMACRDRLR = RX_BUF_NUM - 1;
|
ETH->DMACRDRLR = RX_BUF_NUM - 1;
|
||||||
|
@ -425,7 +475,7 @@ STATIC int eth_mac_init(eth_t *self) {
|
||||||
eth_dma.tx_descr_idx = 0;
|
eth_dma.tx_descr_idx = 0;
|
||||||
|
|
||||||
// Configure DMA
|
// Configure DMA
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
// read from RX FIFO only after a full frame is written
|
// read from RX FIFO only after a full frame is written
|
||||||
ETH->MTLRQOMR = ETH_MTLRQOMR_RSF;
|
ETH->MTLRQOMR = ETH_MTLRQOMR_RSF;
|
||||||
// transmission starts when a full packet resides in the Tx queue
|
// transmission starts when a full packet resides in the Tx queue
|
||||||
|
@ -439,7 +489,7 @@ STATIC int eth_mac_init(eth_t *self) {
|
||||||
mp_hal_delay_ms(2);
|
mp_hal_delay_ms(2);
|
||||||
|
|
||||||
// Select MAC filtering options
|
// Select MAC filtering options
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
ETH->MACPFR = ETH_MACPFR_RA; // pass all frames up
|
ETH->MACPFR = ETH_MACPFR_RA; // pass all frames up
|
||||||
#else
|
#else
|
||||||
ETH->MACFFR =
|
ETH->MACFFR =
|
||||||
|
@ -472,7 +522,7 @@ STATIC int eth_mac_init(eth_t *self) {
|
||||||
mp_hal_delay_ms(2);
|
mp_hal_delay_ms(2);
|
||||||
|
|
||||||
// Start DMA layer
|
// Start DMA layer
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
ETH->DMACRCR |= ETH_DMACRCR_SR; // start RX
|
ETH->DMACRCR |= ETH_DMACRCR_SR; // start RX
|
||||||
ETH->DMACTCR |= ETH_DMACTCR_ST; // start TX
|
ETH->DMACTCR |= ETH_DMACTCR_ST; // start TX
|
||||||
#else
|
#else
|
||||||
|
@ -493,7 +543,11 @@ STATIC int eth_mac_init(eth_t *self) {
|
||||||
STATIC void eth_mac_deinit(eth_t *self) {
|
STATIC void eth_mac_deinit(eth_t *self) {
|
||||||
(void)self;
|
(void)self;
|
||||||
HAL_NVIC_DisableIRQ(ETH_IRQn);
|
HAL_NVIC_DisableIRQ(ETH_IRQn);
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5)
|
||||||
|
__HAL_RCC_ETH_FORCE_RESET();
|
||||||
|
__HAL_RCC_ETH_RELEASE_RESET();
|
||||||
|
__HAL_RCC_ETH_CLK_DISABLE();
|
||||||
|
#elif defined(STM32H7)
|
||||||
__HAL_RCC_ETH1MAC_FORCE_RESET();
|
__HAL_RCC_ETH1MAC_FORCE_RESET();
|
||||||
__HAL_RCC_ETH1MAC_RELEASE_RESET();
|
__HAL_RCC_ETH1MAC_RELEASE_RESET();
|
||||||
__HAL_RCC_ETH1MAC_CLK_DISABLE();
|
__HAL_RCC_ETH1MAC_CLK_DISABLE();
|
||||||
|
@ -513,7 +567,7 @@ STATIC int eth_tx_buf_get(size_t len, uint8_t **buf) {
|
||||||
eth_dma_tx_descr_t *tx_descr = ð_dma.tx_descr[eth_dma.tx_descr_idx];
|
eth_dma_tx_descr_t *tx_descr = ð_dma.tx_descr[eth_dma.tx_descr_idx];
|
||||||
uint32_t t0 = mp_hal_ticks_ms();
|
uint32_t t0 = mp_hal_ticks_ms();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
if (!(tx_descr->tdes3 & (1 << TX_DESCR_3_OWN_Pos))) {
|
if (!(tx_descr->tdes3 & (1 << TX_DESCR_3_OWN_Pos))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -527,7 +581,7 @@ STATIC int eth_tx_buf_get(size_t len, uint8_t **buf) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
// Update TX descriptor with length and buffer pointer
|
// Update TX descriptor with length and buffer pointer
|
||||||
*buf = ð_dma.tx_buf[eth_dma.tx_descr_idx * TX_BUF_SIZE];
|
*buf = ð_dma.tx_buf[eth_dma.tx_descr_idx * TX_BUF_SIZE];
|
||||||
tx_descr->tdes2 = len & TX_DESCR_2_B1L_Msk;
|
tx_descr->tdes2 = len & TX_DESCR_2_B1L_Msk;
|
||||||
|
@ -549,7 +603,7 @@ STATIC int eth_tx_buf_send(void) {
|
||||||
eth_dma.tx_descr_idx = (eth_dma.tx_descr_idx + 1) % TX_BUF_NUM;
|
eth_dma.tx_descr_idx = (eth_dma.tx_descr_idx + 1) % TX_BUF_NUM;
|
||||||
|
|
||||||
// Schedule to send next outgoing frame
|
// Schedule to send next outgoing frame
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
tx_descr->tdes3 =
|
tx_descr->tdes3 =
|
||||||
1 << TX_DESCR_3_OWN_Pos // owned by DMA
|
1 << TX_DESCR_3_OWN_Pos // owned by DMA
|
||||||
| 1 << TX_DESCR_3_LD_Pos // last segment
|
| 1 << TX_DESCR_3_LD_Pos // last segment
|
||||||
|
@ -568,7 +622,7 @@ STATIC int eth_tx_buf_send(void) {
|
||||||
|
|
||||||
// Notify ETH DMA that there is a new TX descriptor for sending
|
// Notify ETH DMA that there is a new TX descriptor for sending
|
||||||
__DMB();
|
__DMB();
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
if (ETH->DMACSR & ETH_DMACSR_TBU) {
|
if (ETH->DMACSR & ETH_DMACSR_TBU) {
|
||||||
ETH->DMACSR = ETH_DMACSR_TBU;
|
ETH->DMACSR = ETH_DMACSR_TBU;
|
||||||
}
|
}
|
||||||
|
@ -590,7 +644,7 @@ STATIC void eth_dma_rx_free(void) {
|
||||||
eth_dma.rx_descr_idx = (eth_dma.rx_descr_idx + 1) % RX_BUF_NUM;
|
eth_dma.rx_descr_idx = (eth_dma.rx_descr_idx + 1) % RX_BUF_NUM;
|
||||||
|
|
||||||
// Schedule to get next incoming frame
|
// Schedule to get next incoming frame
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
rx_descr->rdes0 = (uint32_t)buf;
|
rx_descr->rdes0 = (uint32_t)buf;
|
||||||
rx_descr->rdes3 = 1 << RX_DESCR_3_OWN_Pos; // owned by DMA
|
rx_descr->rdes3 = 1 << RX_DESCR_3_OWN_Pos; // owned by DMA
|
||||||
rx_descr->rdes3 |= 1 << RX_DESCR_3_BUF1V_Pos; // buf 1 address valid
|
rx_descr->rdes3 |= 1 << RX_DESCR_3_BUF1V_Pos; // buf 1 address valid
|
||||||
|
@ -607,7 +661,7 @@ STATIC void eth_dma_rx_free(void) {
|
||||||
|
|
||||||
// Notify ETH DMA that there is a new RX descriptor available
|
// Notify ETH DMA that there is a new RX descriptor available
|
||||||
__DMB();
|
__DMB();
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
ETH->DMACRDTPR = (uint32_t)&rx_descr[eth_dma.rx_descr_idx];
|
ETH->DMACRDTPR = (uint32_t)&rx_descr[eth_dma.rx_descr_idx];
|
||||||
#else
|
#else
|
||||||
ETH->DMARPDR = 0;
|
ETH->DMARPDR = 0;
|
||||||
|
@ -615,7 +669,7 @@ STATIC void eth_dma_rx_free(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ETH_IRQHandler(void) {
|
void ETH_IRQHandler(void) {
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
uint32_t sr = ETH->DMACSR;
|
uint32_t sr = ETH->DMACSR;
|
||||||
ETH->DMACSR = ETH_DMACSR_NIS;
|
ETH->DMACSR = ETH_DMACSR_NIS;
|
||||||
uint32_t rx_interrupt = sr & ETH_DMACSR_RI;
|
uint32_t rx_interrupt = sr & ETH_DMACSR_RI;
|
||||||
|
@ -625,13 +679,13 @@ void ETH_IRQHandler(void) {
|
||||||
uint32_t rx_interrupt = sr & ETH_DMASR_RS;
|
uint32_t rx_interrupt = sr & ETH_DMASR_RS;
|
||||||
#endif
|
#endif
|
||||||
if (rx_interrupt) {
|
if (rx_interrupt) {
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
ETH->DMACSR = ETH_DMACSR_RI;
|
ETH->DMACSR = ETH_DMACSR_RI;
|
||||||
#else
|
#else
|
||||||
ETH->DMASR = ETH_DMASR_RS;
|
ETH->DMASR = ETH_DMASR_RS;
|
||||||
#endif
|
#endif
|
||||||
for (;;) {
|
for (;;) {
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
eth_dma_rx_descr_t *rx_descr_l = ð_dma.rx_descr[eth_dma.rx_descr_idx];
|
eth_dma_rx_descr_t *rx_descr_l = ð_dma.rx_descr[eth_dma.rx_descr_idx];
|
||||||
if (rx_descr_l->rdes3 & (1 << RX_DESCR_3_OWN_Pos)) {
|
if (rx_descr_l->rdes3 & (1 << RX_DESCR_3_OWN_Pos)) {
|
||||||
// No more RX descriptors ready to read
|
// No more RX descriptors ready to read
|
||||||
|
@ -646,13 +700,13 @@ void ETH_IRQHandler(void) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Get RX buffer containing new frame
|
// Get RX buffer containing new frame
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
size_t len = (rx_descr_l->rdes3 & RX_DESCR_3_PL_Msk);
|
size_t len = (rx_descr_l->rdes3 & RX_DESCR_3_PL_Msk);
|
||||||
#else
|
#else
|
||||||
size_t len = (rx_descr->rdes0 & RX_DESCR_0_FL_Msk) >> RX_DESCR_0_FL_Pos;
|
size_t len = (rx_descr->rdes0 & RX_DESCR_0_FL_Msk) >> RX_DESCR_0_FL_Pos;
|
||||||
#endif
|
#endif
|
||||||
len -= 4; // discard CRC at end
|
len -= 4; // discard CRC at end
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
uint8_t *buf = ð_dma.rx_buf[eth_dma.rx_descr_idx * RX_BUF_SIZE];
|
uint8_t *buf = ð_dma.rx_buf[eth_dma.rx_descr_idx * RX_BUF_SIZE];
|
||||||
#else
|
#else
|
||||||
uint8_t *buf = (uint8_t *)rx_descr->rdes2;
|
uint8_t *buf = (uint8_t *)rx_descr->rdes2;
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#ifndef MICROPY_INCLUDED_STM32_MPU_H
|
#ifndef MICROPY_INCLUDED_STM32_MPU_H
|
||||||
#define MICROPY_INCLUDED_STM32_MPU_H
|
#define MICROPY_INCLUDED_STM32_MPU_H
|
||||||
|
|
||||||
#if defined(STM32F7) || defined(STM32H7) || defined(MICROPY_HW_ETH_MDC)
|
#if (defined(STM32F4) && defined(MICROPY_HW_ETH_MDC)) || defined(STM32F7) || defined(STM32H7)
|
||||||
|
|
||||||
#define MPU_REGION_ETH (MPU_REGION_NUMBER0)
|
#define MPU_REGION_ETH (MPU_REGION_NUMBER0)
|
||||||
#define MPU_REGION_QSPI1 (MPU_REGION_NUMBER1)
|
#define MPU_REGION_QSPI1 (MPU_REGION_NUMBER1)
|
||||||
|
@ -97,9 +97,16 @@ static inline void mpu_config_end(uint32_t irq_state) {
|
||||||
|
|
||||||
#elif defined(STM32H5)
|
#elif defined(STM32H5)
|
||||||
|
|
||||||
|
#define MPU_REGION_SIG (MPU_REGION_NUMBER0)
|
||||||
|
#define MPU_REGION_ETH (MPU_REGION_NUMBER1)
|
||||||
|
|
||||||
#define ST_DEVICE_SIGNATURE_BASE (0x08fff800)
|
#define ST_DEVICE_SIGNATURE_BASE (0x08fff800)
|
||||||
#define ST_DEVICE_SIGNATURE_LIMIT (0x08ffffff)
|
#define ST_DEVICE_SIGNATURE_LIMIT (0x08ffffff)
|
||||||
|
|
||||||
|
// STM32H5 Cortex-M33 MPU works differently from older cores.
|
||||||
|
// Macro only takes region size in bytes, Attributes are coded in mpu_config_region().
|
||||||
|
#define MPU_CONFIG_ETH(size) (size)
|
||||||
|
|
||||||
static inline void mpu_init(void) {
|
static inline void mpu_init(void) {
|
||||||
// Configure attribute 0, inner-outer non-cacheable (=0x44).
|
// Configure attribute 0, inner-outer non-cacheable (=0x44).
|
||||||
__DMB();
|
__DMB();
|
||||||
|
@ -125,6 +132,49 @@ static inline void mpu_init(void) {
|
||||||
__ISB();
|
__ISB();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint32_t mpu_config_start(void) {
|
||||||
|
return disable_irq();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mpu_config_region(uint32_t region, uint32_t base_addr, uint32_t size) {
|
||||||
|
if (region == MPU_REGION_ETH) {
|
||||||
|
// Configure region 1 to make DMA memory non-cacheable.
|
||||||
|
|
||||||
|
__DMB();
|
||||||
|
// Configure attribute 1, inner-outer non-cacheable (=0x44).
|
||||||
|
MPU->MAIR0 = (MPU->MAIR0 & ~MPU_MAIR0_Attr1_Msk)
|
||||||
|
| 0x44 << MPU_MAIR0_Attr1_Pos;
|
||||||
|
__DMB();
|
||||||
|
|
||||||
|
// RBAR
|
||||||
|
// BASE Bits [31:5] of base address
|
||||||
|
// SH[4:3] 00 = Non-shareable
|
||||||
|
// AP[2:1] 01 = Read/write by any privilege level
|
||||||
|
// XN[0]: 1 = No execution
|
||||||
|
|
||||||
|
// RLAR
|
||||||
|
// LIMIT Limit address. Contains bits[31:5] of the upper inclusive limit of the selected MPU memory region
|
||||||
|
// AT[3:1] 001 = Attribute 1
|
||||||
|
// EN[0] 1 = Enabled
|
||||||
|
MPU->RNR = region;
|
||||||
|
MPU->RBAR = (base_addr & MPU_RBAR_BASE_Msk)
|
||||||
|
| MPU_ACCESS_NOT_SHAREABLE << MPU_RBAR_SH_Pos
|
||||||
|
| MPU_REGION_ALL_RW << MPU_RBAR_AP_Pos
|
||||||
|
| MPU_INSTRUCTION_ACCESS_DISABLE << MPU_RBAR_XN_Pos;
|
||||||
|
MPU->RLAR = ((base_addr + size - 1) & MPU_RLAR_LIMIT_Msk)
|
||||||
|
| MPU_ATTRIBUTES_NUMBER1 << MPU_RLAR_AttrIndx_Pos
|
||||||
|
| MPU_REGION_ENABLE << MPU_RLAR_EN_Pos;
|
||||||
|
}
|
||||||
|
__DMB();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mpu_config_end(uint32_t irq_state) {
|
||||||
|
__ISB();
|
||||||
|
__DSB();
|
||||||
|
__DMB();
|
||||||
|
enable_irq(irq_state);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static inline void mpu_init(void) {
|
static inline void mpu_init(void) {
|
||||||
|
|
Ładowanie…
Reference in New Issue