stm32/eth: Add support for Ethernet on N6 MCUs.

This adds working support for 100MBit Ethernet on N6 MCUs.

Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
Damien George
2025-07-26 16:22:36 +10:00
parent 2ad1d29747
commit 5a69d47567
5 changed files with 203 additions and 35 deletions

View File

@@ -20,6 +20,7 @@ PortC,PC9 , , , ,
PortC,PC10, , , , , , , , , , ,SDMMC1_D2 , , , , , ,
PortC,PC11, , , , , , , , , , ,SDMMC1_D3 , , , , , ,
PortC,PC12, , , , , , , , , , ,SDMMC1_CK , , , , , ,
PortD,PD1 , , , , , , , , , , , ,ETH1_MDC , , , , ,
PortD,PD2 , , , , , , , , , , , ,SDMMC2_CK , , , , ,
PortD,PD5 , , , , , , , ,USART2_TX , , , , , , , , ,
PortD,PD6 , , , , ,TIM15_CH2 , , , , , , , , , , , ,
@@ -27,6 +28,7 @@ PortD,PD7 , , , ,
PortD,PD8 , , , , , , , ,USART3_TX , , , , , , , , ,
PortD,PD9 , , , , , , , ,USART3_RX , , , , , , , , ,
PortD,PD11, , , , , ,SPI2_MISO , , , , , , , , , , ,
PortD,PD12, , , , , , , , , , , ,ETH1_MDIO , , , , ,
PortD,PD13, , ,TIM4_CH2 , , , , , , , , , , , , , ,
PortE,PE5 , , , , , , , ,USART1_TX , , , , , , , , ,
PortE,PE6 , , , , , , , ,USART1_RX , , , , , , , , ,
@@ -38,12 +40,21 @@ PortE,PE13, , , ,
PortE,PE14, , , , ,I2C4_SDA , , , , , , , , , , , ,
PortE,PE15, , , , , ,SPI5_SCK , , , , , , , , , , ,
PortF,PF3 , , , , , , , ,USART2_RTS , , , , , , , , ,ADC1_INP16
PortF,PF4 , , , , , , , , , , , ,ETH1_MDIO , , , , ,
PortF,PF6 , , , , , , , ,USART2_RX , , , , , , , , ,
PortF,PF7 , , , , , , , , , , , ,ETH1_RMII_REF_CLK , , , , ,
PortF,PF10, , , , , , , , , , , ,ETH1_RMII_CRS_DV , , , , ,
PortF,PF11, , , , , , , , , , , ,ETH1_RMII_TX_EN , , , , ,
PortF,PF12, , , , , , , , , , , ,ETH1_RMII_TXD0 , , , , ,
PortF,PF13, , , , , , , , , , , ,ETH1_RMII_TXD1 , , , , ,
PortF,PF14, , , , , , , , , , , ,ETH1_RMII_RXD0 , , , , ,
PortF,PF15, , , , , , , , , , , ,ETH1_RMII_RXD1 , , , , ,
PortG,PG0 , , ,TIM12_CH1 , , , , , , , , , , , , , ,
PortG,PG1 , , , , , ,SPI5_MISO , , , , , , , , , , ,
PortG,PG2 , , , , , ,SPI5_MOSI , , , , , , , , , , ,
PortG,PG5 , , , , , , , ,USART2_CTS , , , , , , , , ,
PortG,PG8 , , , , , , , , , , , ,SDMMC2_D1 , , , , ,
PortG,PG11, , , , , , , , , , , ,ETH1_MDC , , , , ,
PortG,PG12, ,TIM17_CH1 , , , , , , , , , , , , , , ,
PortG,PG13, , ,TIM4_CH1 , , , , ,USART3_RTS , , , , , , , , ,
PortG,PG15, , , , , , , , , , , , , , , , ,ADC12_INP7/ADC12_INN3
1 Port Pin AF0 AF1 AF2 AF3 AF4 AF5 AF6 AF7 AF8 AF9 AF10 AF11 AF12 AF13 AF14 AF15 ADC
20 PortC PC10 SDMMC1_D2
21 PortC PC11 SDMMC1_D3
22 PortC PC12 SDMMC1_CK
23 PortD PD1 ETH1_MDC
24 PortD PD2 SDMMC2_CK
25 PortD PD5 USART2_TX
26 PortD PD6 TIM15_CH2
28 PortD PD8 USART3_TX
29 PortD PD9 USART3_RX
30 PortD PD11 SPI2_MISO
31 PortD PD12 ETH1_MDIO
32 PortD PD13 TIM4_CH2
33 PortE PE5 USART1_TX
34 PortE PE6 USART1_RX
40 PortE PE14 I2C4_SDA
41 PortE PE15 SPI5_SCK
42 PortF PF3 USART2_RTS ADC1_INP16
43 PortF PF4 ETH1_MDIO
44 PortF PF6 USART2_RX
45 PortF PF7 ETH1_RMII_REF_CLK
46 PortF PF10 ETH1_RMII_CRS_DV
47 PortF PF11 ETH1_RMII_TX_EN
48 PortF PF12 ETH1_RMII_TXD0
49 PortF PF13 ETH1_RMII_TXD1
50 PortF PF14 ETH1_RMII_RXD0
51 PortF PF15 ETH1_RMII_RXD1
52 PortG PG0 TIM12_CH1
53 PortG PG1 SPI5_MISO
54 PortG PG2 SPI5_MOSI
55 PortG PG5 USART2_CTS
56 PortG PG8 SDMMC2_D1
57 PortG PG11 ETH1_MDC
58 PortG PG12 TIM17_CH1
59 PortG PG13 TIM4_CH1 USART3_RTS
60 PortG PG15 ADC12_INP7/ADC12_INN3

View File

@@ -160,7 +160,6 @@
#include "stm32n6xx_hal_dcmipp.h"
#include "stm32n6xx_hal_dma2d.h"
#include "stm32n6xx_hal_dts.h"
#include "stm32n6xx_hal_eth.h"
#include "stm32n6xx_hal_exti.h"
#include "stm32n6xx_hal_fdcan.h"
#include "stm32n6xx_hal_gfxmmu.h"

View File

@@ -41,8 +41,19 @@
#include "lwip/dhcp.h"
#include "netif/ethernet.h"
// Register and IRQ compatibility for STM32N6.
#if defined(STM32N6)
#define ETH ETH1
#define ETH_MACMDIOAR_MB (ETH_MACMDIOAR_GB)
#define ETH_MACMDIOAR_MOC_Msk (ETH_MACMDIOAR_GOC_Msk)
#define ETH_MACMDIOAR_MOC_WR (ETH_MACMDIOAR_GOC_0)
#define ETH_MACMDIOAR_MOC_RD (ETH_MACMDIOAR_GOC_1 | ETH_MACMDIOAR_GOC_0)
#define ETH_IRQn ETH1_IRQn
#define ETH_IRQHandler ETH1_IRQHandler
#endif
// ETH DMA RX and TX descriptor definitions
#if defined(STM32H5)
#if defined(STM32H5) || defined(STM32N6)
#define RX_DESCR_3_OWN_Pos (31)
#define RX_DESCR_3_IOC_Pos (30)
#define RX_DESCR_3_BUF1V_Pos (24)
@@ -85,6 +96,13 @@
#define TX_DESCR_1_TBS1_Pos (0)
#endif
// Static alternate function macro.
#if defined(STM32N6)
#define STATIC_AF_ETH(signal) STATIC_AF_ETH1_##signal
#else
#define STATIC_AF_ETH(signal) STATIC_AF_ETH_##signal
#endif
// Configuration values
#define PHY_INIT_TIMEOUT_MS (10000)
@@ -95,6 +113,12 @@
#define RX_BUF_NUM (5)
#define TX_BUF_NUM (5)
#if defined(STM32N6)
// The N6 has two DMA channels, so use one for RX and one for TX.
#define RX_DMA_CH (0)
#define TX_DMA_CH (1)
#endif
typedef struct _eth_dma_rx_descr_t {
volatile uint32_t rdes0, rdes1, rdes2, rdes3;
} eth_dma_rx_descr_t;
@@ -129,7 +153,7 @@ static void eth_mac_deinit(eth_t *self);
static void eth_process_frame(eth_t *self, size_t len, const uint8_t *buf);
void eth_phy_write(uint32_t phy_addr, uint32_t reg, uint32_t val) {
#if defined(STM32H5) || defined(STM32H7)
#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6)
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
}
uint32_t ar = ETH->MACMDIOAR;
@@ -157,7 +181,7 @@ void eth_phy_write(uint32_t phy_addr, uint32_t reg, uint32_t val) {
}
uint32_t eth_phy_read(uint32_t phy_addr, uint32_t reg) {
#if defined(STM32H5) || defined(STM32H7)
#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6)
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
}
uint32_t ar = ETH->MACMDIOAR;
@@ -197,15 +221,15 @@ int eth_init(eth_t *self, int mac_idx, uint32_t phy_addr, int phy_type) {
}
// Configure GPIO
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_MDC, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_MDC);
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_MDIO, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_MDIO);
mp_hal_pin_config_alt_static_speed(MICROPY_HW_ETH_RMII_REF_CLK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_MEDIUM, STATIC_AF_ETH_RMII_REF_CLK);
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_CRS_DV, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_RMII_CRS_DV);
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_RXD0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_RMII_RXD0);
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_RXD1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_RMII_RXD1);
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_TX_EN, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_RMII_TX_EN);
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_TXD0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_RMII_TXD0);
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_MDC, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH(MDC));
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_MDIO, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH(MDIO));
mp_hal_pin_config_alt_static_speed(MICROPY_HW_ETH_RMII_REF_CLK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_MEDIUM, STATIC_AF_ETH(RMII_REF_CLK));
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_CRS_DV, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH(RMII_CRS_DV));
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_RXD0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH(RMII_RXD0));
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_RXD1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH(RMII_RXD1));
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_TX_EN, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH(RMII_TX_EN));
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_TXD0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH(RMII_TXD0));
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
#if defined(STM32H5)
@@ -216,6 +240,11 @@ int eth_init(eth_t *self, int mac_idx, uint32_t phy_addr, int phy_type) {
__HAL_RCC_ETH1MAC_CLK_ENABLE();
__HAL_RCC_ETH1TX_CLK_ENABLE();
__HAL_RCC_ETH1RX_CLK_ENABLE();
#elif defined(STM32N6)
__HAL_RCC_ETH1_CLK_ENABLE();
__HAL_RCC_ETH1MAC_CLK_ENABLE();
__HAL_RCC_ETH1TX_CLK_ENABLE();
__HAL_RCC_ETH1RX_CLK_ENABLE();
#else
__HAL_RCC_ETH_CLK_ENABLE();
#endif
@@ -229,7 +258,7 @@ void eth_set_trace(eth_t *self, uint32_t value) {
static int eth_mac_init(eth_t *self) {
// Configure MPU
uint32_t irq_state = mpu_config_start();
#if defined(STM32H5)
#if defined(STM32H5) || defined(STM32N6)
mpu_config_region(MPU_REGION_ETH, (uint32_t)&eth_dma, MPU_CONFIG_ETH(16 * 1024));
#else
mpu_config_region(MPU_REGION_ETH, (uint32_t)&eth_dma, MPU_CONFIG_ETH(MPU_REGION_SIZE_16KB));
@@ -241,16 +270,29 @@ static int eth_mac_init(eth_t *self) {
__HAL_RCC_ETH_FORCE_RESET();
#elif defined(STM32H7)
__HAL_RCC_ETH1MAC_FORCE_RESET();
#elif defined(STM32N6)
__HAL_RCC_ETH1_FORCE_RESET();
#else
__HAL_RCC_ETHMAC_FORCE_RESET();
#endif
// Select clock sources.
#if defined(STM32N6)
LL_RCC_SetETHREFTXClockSource(LL_RCC_ETH1REFTX_CLKSOURCE_EXT); // max 25MHz
LL_RCC_SetETHREFRXClockSource(LL_RCC_ETH1REFRX_CLKSOURCE_EXT); // max 125MHz
LL_RCC_SetETHClockSource(LL_RCC_ETH1_CLKSOURCE_IC12); // max 125MHz
LL_RCC_SetETH1PTPDivider(LL_RCC_ETH1PTP_DIV_1);
LL_RCC_SetETHPTPClockSource(LL_RCC_ETH1PTP_CLKSOURCE_HCLK); // max 200MHz
#endif
// Select RMII interface
#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;
#elif defined(STM32N6)
LL_RCC_SetETHPHYInterface(LL_RCC_ETH1PHY_IF_RMII);
#else
__HAL_RCC_SYSCFG_CLK_ENABLE();
SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
@@ -265,6 +307,13 @@ static int eth_mac_init(eth_t *self) {
#elif defined(STM32H7)
__HAL_RCC_ETH1MAC_RELEASE_RESET();
__HAL_RCC_ETH1MAC_CLK_SLEEP_ENABLE();
__HAL_RCC_ETH1TX_CLK_SLEEP_ENABLE();
__HAL_RCC_ETH1RX_CLK_SLEEP_ENABLE();
#elif defined(STM32N6)
__HAL_RCC_ETH1_RELEASE_RESET();
__HAL_RCC_ETH1_CLK_SLEEP_ENABLE();
__HAL_RCC_ETH1MAC_CLK_SLEEP_ENABLE();
__HAL_RCC_ETH1TX_CLK_SLEEP_ENABLE();
__HAL_RCC_ETH1RX_CLK_SLEEP_ENABLE();
@@ -277,7 +326,7 @@ static int eth_mac_init(eth_t *self) {
#endif
// Do a soft reset of the MAC core
#if defined(STM32H5) || defined(STM32H7)
#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6)
#define ETH_SOFT_RESET(eth) do { eth->DMAMR = ETH_DMAMR_SWR; } while (0)
#define ETH_IS_RESET(eth) (eth->DMAMR & ETH_DMAMR_SWR)
#else
@@ -299,7 +348,7 @@ static int eth_mac_init(eth_t *self) {
// Set MII clock range
uint32_t hclk = HAL_RCC_GetHCLKFreq();
uint32_t cr_div;
#if defined(STM32H5)
#if defined(STM32H5) || defined(STM32N6)
cr_div = ETH->MACMDIOAR & ~ETH_MACMDIOAR_CR;
if (hclk < 35000000) {
cr_div |= ETH_MACMDIOAR_CR_DIV16;
@@ -311,8 +360,17 @@ static int eth_mac_init(eth_t *self) {
cr_div |= ETH_MACMDIOAR_CR_DIV62;
} else if (hclk < 250000000) {
cr_div |= ETH_MACMDIOAR_CR_DIV102;
#if defined(STM32H5)
} else {
cr_div |= ETH_MACMDIOAR_CR_DIV124;
#else
} else if (hclk < 300000000) {
cr_div |= ETH_MACMDIOAR_CR_DIV124;
} else if (hclk < 500000000) {
cr_div |= ETH_MACMDIOAR_CR_DIV204;
} else {
cr_div |= ETH_MACMDIOAR_CR_DIV324;
#endif
}
ETH->MACMDIOAR = cr_div;
#elif defined(STM32H7)
@@ -344,9 +402,17 @@ static int eth_mac_init(eth_t *self) {
ETH->MACMIIAR = cr_div;
#endif
#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6)
// Configure the MAC 1-us tick counter register.
WRITE_REG(ETH->MAC1USTCR, HAL_RCC_GetHCLKFreq() / 1000000U - 1U);
#endif
#if defined(STM32H5) || defined(STM32H7)
// don't skip 32bit words since our descriptors are continuous in memory
ETH->DMACCR &= ~(ETH_DMACCR_DSL_Msk);
#elif defined(STM32N6)
ETH->DMA_CH[RX_DMA_CH].DMACCR &= ~(ETH_DMACxCR_DSL_Msk);
ETH->DMA_CH[TX_DMA_CH].DMACCR &= ~(ETH_DMACxCR_DSL_Msk);
#endif
// Reset the PHY
@@ -397,7 +463,7 @@ static int eth_mac_init(eth_t *self) {
uint16_t phy_scsr = self->phy_get_link_status(self->phy_addr);
// Burst mode configuration
#if defined(STM32H5) || defined(STM32H7)
#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6)
ETH->DMASBMR = ETH->DMASBMR & ~ETH_DMASBMR_AAL & ~ETH_DMASBMR_FB;
#else
ETH->DMABMR = 0;
@@ -410,6 +476,11 @@ static int eth_mac_init(eth_t *self) {
| ETH_DMACIER_NIE // enable normal interrupts
| ETH_DMACIER_RIE // enable RX interrupt
;
#elif defined(STM32N6)
ETH->DMA_CH[RX_DMA_CH].DMACIER =
ETH_DMACxIER_NIE // enable normal interrupts
| ETH_DMACxIER_RIE // enable RX interrupt
;
#else
ETH->DMAIER =
ETH_DMAIER_NISE // enable normal interrupts
@@ -419,7 +490,7 @@ static int eth_mac_init(eth_t *self) {
// Configure RX descriptor lists
for (size_t i = 0; i < RX_BUF_NUM; ++i) {
#if defined(STM32H5) || defined(STM32H7)
#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6)
eth_dma.rx_descr[i].rdes3 =
1 << RX_DESCR_3_OWN_Pos
| (1 << RX_DESCR_3_BUF1V_Pos) // buf1 address valid
@@ -439,6 +510,11 @@ static int eth_mac_init(eth_t *self) {
#if defined(STM32H5) || defined(STM32H7)
ETH->DMACRDLAR = (uint32_t)&eth_dma.rx_descr[0];
#elif defined(STM32N6)
// Set number of RX descriptors and buffer pointers.
ETH->DMA_CH[RX_DMA_CH].DMACRXRLR = RX_BUF_NUM - 1;
ETH->DMA_CH[RX_DMA_CH].DMACRXDLAR = (uint32_t)&eth_dma.rx_descr[0];
ETH->DMA_CH[RX_DMA_CH].DMACRXDTPR = (uint32_t)&eth_dma.rx_descr[RX_BUF_NUM - 1];
#else
ETH->DMARDLAR = (uint32_t)&eth_dma.rx_descr[0];
#endif
@@ -446,7 +522,7 @@ static int eth_mac_init(eth_t *self) {
// Configure TX descriptor lists
for (size_t i = 0; i < TX_BUF_NUM; ++i) {
#if defined(STM32H5) || defined(STM32H7)
#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6)
eth_dma.tx_descr[i].tdes0 = 0;
eth_dma.tx_descr[i].tdes1 = 0;
eth_dma.tx_descr[i].tdes2 = TX_BUF_SIZE & TX_DESCR_2_B1L_Msk;
@@ -465,6 +541,11 @@ static int eth_mac_init(eth_t *self) {
ETH->DMACRDRLR = RX_BUF_NUM - 1;
ETH->DMACTDLAR = (uint32_t)&eth_dma.tx_descr[0];
#elif defined(STM32N6)
// Set number of TX descriptors and buffer pointers.
ETH->DMA_CH[TX_DMA_CH].DMACTXRLR = TX_BUF_NUM - 1;
ETH->DMA_CH[TX_DMA_CH].DMACTXDLAR = (uint32_t)&eth_dma.tx_descr[0];
ETH->DMA_CH[TX_DMA_CH].DMACTXDTPR = (uint32_t)&eth_dma.tx_descr[0];
#else
ETH->DMATDLAR = (uint32_t)&eth_dma.tx_descr[0];
#endif
@@ -476,6 +557,11 @@ static int eth_mac_init(eth_t *self) {
ETH->MTLRQOMR = ETH_MTLRQOMR_RSF;
// transmission starts when a full packet resides in the Tx queue
ETH->MTLTQOMR = ETH_MTLTQOMR_TSF;
#elif defined(STM32N6)
// read from RX FIFO only after a full frame is written
ETH->MTL_QUEUE[0].MTLRXQOMR = ETH_MTLRXQxOMR_RSF;
// transmission starts when a full packet resides in the Tx queue
ETH->MTL_QUEUE[0].MTLTXQOMR = ETH_MTLTXQxOMR_TSF;
#else
ETH->DMAOMR =
ETH_DMAOMR_RSF // read from RX FIFO after a full frame is written
@@ -485,7 +571,7 @@ static int eth_mac_init(eth_t *self) {
mp_hal_delay_ms(2);
// Select MAC filtering options
#if defined(STM32H5) || defined(STM32H7)
#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6)
ETH->MACPFR = ETH_MACPFR_RA; // pass all frames up
#else
ETH->MACFFR =
@@ -501,15 +587,47 @@ static int eth_mac_init(eth_t *self) {
ETH->MACA0LR = mac[3] << 24 | mac[2] << 16 | mac[1] << 8 | mac[0];
mp_hal_delay_ms(2);
// Work out the line speed configuration for MACCR.
uint32_t maccr = 0;
if (phy_scsr & PHY_SPEED_100HALF) {
maccr |= ETH_MACCR_FES;
}
if (phy_scsr & PHY_DUPLEX) {
maccr |= ETH_MACCR_DM;
}
#if defined(STM32N6)
maccr |=
ETH_MACCR_IPG_96BIT
| ETH_MACCR_SARC_REPADDR0
| ETH_MACCR_IPC
| ETH_MACCR_PS
| ETH_MACCR_BL_10
| ETH_MACCR_PRELEN_7;
ETH->MACCR = maccr;
ETH->MACECR = 0x618U;
ETH->MACWTR = ETH_MACWTR_WTO_2KB;
ETH->MACQ0TXFCR = ETH_MACQ0TXFCR_PLT_MINUS4;
ETH->MACRXFCR = 0;
ETH->MACRXQC0R = ETH_MACRXQC0R_RXQ0EN_GT | ETH_MACRXQC0R_RXQ1EN_NOT;
ETH->MTLOMR = ETH_MTLOMR_SCHALG_SP | ETH_MTLOMR_RAA_SP;
ETH->MTLRXQDMAMR = ETH_MTLRXQDMAMR_Q0MDMACH_DMACH0 | ETH_MTLRXQDMAMR_Q1MDMACH_DMACH1;
ETH->MTL_QUEUE[0].MTLTXQOMR = ETH_MTLTXQxOMR_TXQEN_EN | ETH_MTLTXQxOMR_TSF | 7 << ETH_MTLTXQxOMR_TQS_Pos;
ETH->MTL_QUEUE[1].MTLTXQOMR = ETH_MTLTXQxOMR_TXQEN_EN | ETH_MTLTXQxOMR_TSF | 7 << ETH_MTLTXQxOMR_TQS_Pos;
ETH->MTL_QUEUE[0].MTLRXQOMR = ETH_MTLRXQxOMR_RSF | 15 << ETH_MTLRXQxOMR_RQS_Pos;
ETH->MTL_QUEUE[1].MTLRXQOMR = ETH_MTLRXQxOMR_RSF | 15 << ETH_MTLRXQxOMR_RQS_Pos;
#else
// Set main MAC control register
ETH->MACCR =
phy_scsr == PHY_SPEED_10FULL ? ETH_MACCR_DM
: phy_scsr == PHY_SPEED_100HALF ? ETH_MACCR_FES
: phy_scsr == PHY_SPEED_100FULL ? (ETH_MACCR_FES | ETH_MACCR_DM)
: 0
;
ETH->MACCR = maccr;
mp_hal_delay_ms(2);
#endif
// Start MAC layer
ETH->MACCR |=
ETH_MACCR_TE // enable TX
@@ -521,6 +639,15 @@ static int eth_mac_init(eth_t *self) {
#if defined(STM32H5) || defined(STM32H7)
ETH->DMACRCR |= ETH_DMACRCR_SR; // start RX
ETH->DMACTCR |= ETH_DMACTCR_ST; // start TX
#elif defined(STM32N6)
ETH->MTL_QUEUE[0].MTLTXQOMR |= ETH_MTLTXQxOMR_FTQ; // flush TX FIFO
ETH->MTL_QUEUE[1].MTLTXQOMR |= ETH_MTLTXQxOMR_FTQ; // flush TX FIFO
ETH->DMA_CH[RX_DMA_CH].DMACRXCR = RX_BUF_SIZE << ETH_DMACxRXCR_RBSZ_Pos;
ETH->DMA_CH[RX_DMA_CH].DMACRXCR |= ETH_DMACxRXCR_SR; // start RX
ETH->DMA_CH[TX_DMA_CH].DMACTXCR = 4 << ETH_DMACxTXCR_TXPBL_Pos;
ETH->DMA_CH[TX_DMA_CH].DMACTXCR |= ETH_DMACxTXCR_ST; // start TX
ETH->DMA_CH[RX_DMA_CH].DMACSR |= ETH_DMACxSR_TPS | ETH_DMACxSR_RPS; // clear TX/RX process stopped flags
ETH->DMA_CH[TX_DMA_CH].DMACSR |= ETH_DMACxSR_TPS | ETH_DMACxSR_RPS; // clear TX/RX process stopped flags
#else
ETH->DMAOMR |=
ETH_DMAOMR_ST // start TX
@@ -547,6 +674,10 @@ static void eth_mac_deinit(eth_t *self) {
__HAL_RCC_ETH1MAC_FORCE_RESET();
__HAL_RCC_ETH1MAC_RELEASE_RESET();
__HAL_RCC_ETH1MAC_CLK_DISABLE();
#elif defined(STM32N6)
__HAL_RCC_ETH1_FORCE_RESET();
__HAL_RCC_ETH1_RELEASE_RESET();
__HAL_RCC_ETH1_CLK_DISABLE();
#else
__HAL_RCC_ETHMAC_FORCE_RESET();
__HAL_RCC_ETHMAC_RELEASE_RESET();
@@ -563,7 +694,7 @@ static int eth_tx_buf_get(size_t len, uint8_t **buf) {
eth_dma_tx_descr_t *tx_descr = &eth_dma.tx_descr[eth_dma.tx_descr_idx];
uint32_t t0 = mp_hal_ticks_ms();
for (;;) {
#if defined(STM32H5) || defined(STM32H7)
#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6)
if (!(tx_descr->tdes3 & (1 << TX_DESCR_3_OWN_Pos))) {
break;
}
@@ -577,7 +708,7 @@ static int eth_tx_buf_get(size_t len, uint8_t **buf) {
}
}
#if defined(STM32H5) || defined(STM32H7)
#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6)
// Update TX descriptor with length and buffer pointer
*buf = &eth_dma.tx_buf[eth_dma.tx_descr_idx * TX_BUF_SIZE];
tx_descr->tdes2 = len & TX_DESCR_2_B1L_Msk;
@@ -599,7 +730,7 @@ static int eth_tx_buf_send(void) {
eth_dma.tx_descr_idx = (eth_dma.tx_descr_idx + 1) % TX_BUF_NUM;
// Schedule to send next outgoing frame
#if defined(STM32H5) || defined(STM32H7)
#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6)
tx_descr->tdes3 =
1 << TX_DESCR_3_OWN_Pos // owned by DMA
| 1 << TX_DESCR_3_LD_Pos // last segment
@@ -623,6 +754,11 @@ static int eth_tx_buf_send(void) {
ETH->DMACSR = ETH_DMACSR_TBU;
}
ETH->DMACTDTPR = (uint32_t)&eth_dma.tx_descr[eth_dma.tx_descr_idx];
#elif defined(STM32N6)
if (ETH->DMA_CH[TX_DMA_CH].DMACSR & ETH_DMACxSR_TBU) {
ETH->DMA_CH[TX_DMA_CH].DMACSR = ETH_DMACxSR_TBU;
}
ETH->DMA_CH[TX_DMA_CH].DMACTXDTPR = (uint32_t)&eth_dma.tx_descr[eth_dma.tx_descr_idx];
#else
if (ETH->DMASR & ETH_DMASR_TBUS) {
ETH->DMASR = ETH_DMASR_TBUS;
@@ -640,7 +776,7 @@ static void eth_dma_rx_free(void) {
eth_dma.rx_descr_idx = (eth_dma.rx_descr_idx + 1) % RX_BUF_NUM;
// Schedule to get next incoming frame
#if defined(STM32H5) || defined(STM32H7)
#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6)
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_BUF1V_Pos; // buf 1 address valid
@@ -659,16 +795,24 @@ static void eth_dma_rx_free(void) {
__DMB();
#if defined(STM32H5) || defined(STM32H7)
ETH->DMACRDTPR = (uint32_t)&rx_descr[eth_dma.rx_descr_idx];
#elif defined(STM32N6)
ETH->DMA_CH[RX_DMA_CH].DMACRXDTPR = (uint32_t)&rx_descr[eth_dma.rx_descr_idx];
#else
ETH->DMARPDR = 0;
#endif
}
void ETH_IRQHandler(void) {
MP_STATIC_ASSERT(ETH_IRQn > 0);
#if defined(STM32H5) || defined(STM32H7)
uint32_t sr = ETH->DMACSR;
ETH->DMACSR = ETH_DMACSR_NIS;
uint32_t rx_interrupt = sr & ETH_DMACSR_RI;
#elif defined(STM32N6)
uint32_t sr = ETH->DMA_CH[RX_DMA_CH].DMACSR;
ETH->DMA_CH[RX_DMA_CH].DMACSR = ETH_DMACxSR_NIS;
uint32_t rx_interrupt = sr & ETH_DMACxSR_RI;
#else
uint32_t sr = ETH->DMASR;
ETH->DMASR = ETH_DMASR_NIS;
@@ -677,11 +821,13 @@ void ETH_IRQHandler(void) {
if (rx_interrupt) {
#if defined(STM32H5) || defined(STM32H7)
ETH->DMACSR = ETH_DMACSR_RI;
#elif defined(STM32N6)
ETH->DMA_CH[RX_DMA_CH].DMACSR = ETH_DMACxSR_RI;
#else
ETH->DMASR = ETH_DMASR_RS;
#endif
for (;;) {
#if defined(STM32H5) || defined(STM32H7)
#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6)
eth_dma_rx_descr_t *rx_descr_l = &eth_dma.rx_descr[eth_dma.rx_descr_idx];
if (rx_descr_l->rdes3 & (1 << RX_DESCR_3_OWN_Pos)) {
// No more RX descriptors ready to read
@@ -696,13 +842,13 @@ void ETH_IRQHandler(void) {
#endif
// Get RX buffer containing new frame
#if defined(STM32H5) || defined(STM32H7)
#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6)
size_t len = (rx_descr_l->rdes3 & RX_DESCR_3_PL_Msk);
#else
size_t len = (rx_descr->rdes0 & RX_DESCR_0_FL_Msk) >> RX_DESCR_0_FL_Pos;
#endif
len -= 4; // discard CRC at end
#if defined(STM32H5) || defined(STM32H7)
#if defined(STM32H5) || defined(STM32H7) || defined(STM32N6)
uint8_t *buf = &eth_dma.rx_buf[eth_dma.rx_descr_idx * RX_BUF_SIZE];
#else
uint8_t *buf = (uint8_t *)rx_descr->rdes2;
@@ -875,6 +1021,8 @@ void eth_low_power_mode(eth_t *self, bool enable) {
// Enable eth clock
#if defined(STM32H7)
__HAL_RCC_ETH1MAC_CLK_ENABLE();
#elif defined(STM32N6)
__HAL_RCC_ETH1_CLK_ENABLE();
#else
__HAL_RCC_ETH_CLK_ENABLE();
#endif
@@ -886,6 +1034,8 @@ void eth_low_power_mode(eth_t *self, bool enable) {
// Disable eth clock.
#if defined(STM32H7)
__HAL_RCC_ETH1MAC_CLK_DISABLE();
#elif defined(STM32N6)
__HAL_RCC_ETH1_CLK_DISABLE();
#else
__HAL_RCC_ETH_CLK_DISABLE();
#endif

View File

@@ -318,11 +318,14 @@ static void risaf_init(void) {
rimc_master.MasterCID = RIF_CID_1;
rimc_master.SecPriv = RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV;
HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_ADC12, RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_SDMMC1, &rimc_master);
HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_SDMMC1, RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_SDMMC2, &rimc_master);
HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_ETH1, &rimc_master);
HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_ADC12, RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_SDMMC1, RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_SDMMC2, RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_ETH1, RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
}
#endif

View File

@@ -482,6 +482,11 @@ void SystemClock_Config(void) {
LL_RCC_IC11_SetDivider(1);
LL_RCC_IC11_Enable();
// Configure IC12 at 100MHz for ETH1CLKSEL.
LL_RCC_IC12_SetSource(LL_RCC_ICCLKSOURCE_PLL1);
LL_RCC_IC12_SetDivider(8);
LL_RCC_IC12_Enable();
// Configure IC14 at 100MHz for slower peripherals.
LL_RCC_IC14_SetSource(LL_RCC_ICCLKSOURCE_PLL1);
LL_RCC_IC14_SetDivider(8);