diff options
| author | Damien George <damien@micropython.org> | 2024-06-18 17:46:21 +1000 |
|---|---|---|
| committer | Damien George <damien@micropython.org> | 2025-07-08 16:24:27 +1000 |
| commit | eb3ea9ee13093d81053f5d07b8c96e4fc0e1383d (patch) | |
| tree | 07f7bb3e3f9c6fb1f4204c531d3c18a29c3cb189 /ports/stm32/dma.c | |
| parent | 24fd5f72682922664c0bcf70d6e3631a6d5b8d2b (diff) | |
stm32: Add support for STM32N6xx MCUs.
This commit adds preliminary support for ST's new STM32N6xx MCUs.
Supported features of this MCU so far are:
- basic clock tree initialisation, running at 800MHz
- fully working USB
- XSPI in memory-mapped mode
- machine.Pin
- machine.UART
- RTC and deepsleep support
- SD card
- filesystem
- ROMFS
- WiFi and BLE via cyw43-driver (SDIO backend)
Note that the N6 does not have internal flash, and has some tricky boot
sequence, so using a custom bootloader (mboot) is almost a necessity.
Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'ports/stm32/dma.c')
| -rw-r--r-- | ports/stm32/dma.c | 83 |
1 files changed, 75 insertions, 8 deletions
diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index 53c53868c..c25277074 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -81,7 +81,7 @@ typedef union { struct _dma_descr_t { #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) DMA_Stream_TypeDef *instance; - #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) DMA_Channel_TypeDef *instance; #else #error "Unsupported Processor" @@ -93,7 +93,7 @@ struct _dma_descr_t { // Default parameters to dma_init() shared by spi and i2c; Channel and Direction // vary depending on the peripheral instance so they get passed separately -#if defined(STM32H5) +#if defined(STM32H5) || defined(STM32N6) static const DMA_InitTypeDef dma_init_struct_spi_i2c = { .Request = 0, // set by dma_init_handle .BlkHWRequest = DMA_BREQ_SINGLE_BURST, @@ -157,7 +157,7 @@ static const DMA_InitTypeDef dma_init_struct_i2s = { }; #endif -#if ENABLE_SDIO && !defined(STM32H5) && !defined(STM32H7) +#if ENABLE_SDIO && !defined(STM32H5) && !defined(STM32H7) && !defined(STM32N6) // Parameters to dma_init() for SDIO tx and rx. static const DMA_InitTypeDef dma_init_struct_sdio = { #if defined(STM32F4) || defined(STM32F7) @@ -830,6 +830,46 @@ static const uint8_t dma_irqn[NSTREAM] = { DMA2_Stream7_IRQn, }; +#elif defined(STM32N6) + +#define NCONTROLLERS (1) +#define NSTREAMS_PER_CONTROLLER (16) +#define NSTREAM (NCONTROLLERS * NSTREAMS_PER_CONTROLLER) + +#define DMA_SUB_INSTANCE_AS_UINT8(dma_channel) (dma_channel) + +#define DMA1_ENABLE_MASK (0xffff) // Bits in dma_enable_mask corresponding to GPDMA1 + +const dma_descr_t dma_SPI_1_RX = { GPDMA1_Channel0, GPDMA1_REQUEST_SPI1_RX, dma_id_0, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_1_TX = { GPDMA1_Channel1, GPDMA1_REQUEST_SPI1_TX, dma_id_1, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_2_RX = { GPDMA1_Channel2, GPDMA1_REQUEST_SPI2_RX, dma_id_2, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_2_TX = { GPDMA1_Channel3, GPDMA1_REQUEST_SPI2_TX, dma_id_3, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_3_RX = { GPDMA1_Channel4, GPDMA1_REQUEST_SPI3_RX, dma_id_4, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_3_TX = { GPDMA1_Channel5, GPDMA1_REQUEST_SPI3_TX, dma_id_5, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_4_RX = { GPDMA1_Channel6, GPDMA1_REQUEST_SPI4_RX, dma_id_6, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_4_TX = { GPDMA1_Channel7, GPDMA1_REQUEST_SPI4_TX, dma_id_7, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_5_RX = { GPDMA1_Channel8, GPDMA1_REQUEST_SPI5_RX, dma_id_8, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_5_TX = { GPDMA1_Channel9, GPDMA1_REQUEST_SPI5_TX, dma_id_9, &dma_init_struct_spi_i2c }; + +static const uint8_t dma_irqn[NSTREAM] = { + GPDMA1_Channel0_IRQn, + GPDMA1_Channel1_IRQn, + GPDMA1_Channel2_IRQn, + GPDMA1_Channel3_IRQn, + GPDMA1_Channel4_IRQn, + GPDMA1_Channel5_IRQn, + GPDMA1_Channel6_IRQn, + GPDMA1_Channel7_IRQn, + GPDMA1_Channel8_IRQn, + GPDMA1_Channel9_IRQn, + GPDMA1_Channel10_IRQn, + GPDMA1_Channel11_IRQn, + GPDMA1_Channel12_IRQn, + GPDMA1_Channel13_IRQn, + GPDMA1_Channel14_IRQn, + GPDMA1_Channel15_IRQn, +}; + #endif static DMA_HandleTypeDef *dma_handle[NSTREAM] = {NULL}; @@ -853,6 +893,10 @@ volatile dma_idle_count_t dma_idle; #define __HAL_RCC_DMA2_CLK_ENABLE __HAL_RCC_GPDMA2_CLK_ENABLE #define __HAL_RCC_DMA1_CLK_DISABLE __HAL_RCC_GPDMA1_CLK_DISABLE #define __HAL_RCC_DMA2_CLK_DISABLE __HAL_RCC_GPDMA2_CLK_DISABLE +#elif defined(STM32N6) +#define DMA1_IS_CLK_ENABLED() (__HAL_RCC_GPDMA1_IS_CLK_ENABLED()) +#define __HAL_RCC_DMA1_CLK_ENABLE __HAL_RCC_GPDMA1_CLK_ENABLE +#define __HAL_RCC_DMA1_CLK_DISABLE __HAL_RCC_GPDMA1_CLK_DISABLE #else #define DMA1_IS_CLK_ENABLED() ((RCC->AHB1ENR & RCC_AHB1ENR_DMA1EN) != 0) #define DMA2_IS_CLK_ENABLED() ((RCC->AHB1ENR & RCC_AHB1ENR_DMA2EN) != 0) @@ -1185,10 +1229,11 @@ void DMA2_Channel8_IRQHandler(void) { } #endif -#elif defined(STM32H5) +#elif defined(STM32H5) || defined(STM32N6) #define DEFINE_IRQ_HANDLER(periph, channel, id) \ void GPDMA##periph##_Channel##channel##_IRQHandler(void) { \ + MP_STATIC_ASSERT(GPDMA##periph##_Channel##channel##_IRQn > 0); \ IRQ_ENTER(GPDMA##periph##_Channel##channel##_IRQn); \ if (dma_handle[id] != NULL) { \ HAL_DMA_IRQHandler(dma_handle[id]); \ @@ -1204,6 +1249,7 @@ DEFINE_IRQ_HANDLER(1, 4, dma_id_4) DEFINE_IRQ_HANDLER(1, 5, dma_id_5) DEFINE_IRQ_HANDLER(1, 6, dma_id_6) DEFINE_IRQ_HANDLER(1, 7, dma_id_7) +#if defined(STM32H5) DEFINE_IRQ_HANDLER(2, 0, dma_id_8) DEFINE_IRQ_HANDLER(2, 1, dma_id_9) DEFINE_IRQ_HANDLER(2, 2, dma_id_10) @@ -1212,6 +1258,16 @@ DEFINE_IRQ_HANDLER(2, 4, dma_id_12) DEFINE_IRQ_HANDLER(2, 5, dma_id_13) DEFINE_IRQ_HANDLER(2, 6, dma_id_14) DEFINE_IRQ_HANDLER(2, 7, dma_id_15) +#else +DEFINE_IRQ_HANDLER(1, 8, dma_id_8) +DEFINE_IRQ_HANDLER(1, 9, dma_id_9) +DEFINE_IRQ_HANDLER(1, 10, dma_id_10) +DEFINE_IRQ_HANDLER(1, 11, dma_id_11) +DEFINE_IRQ_HANDLER(1, 12, dma_id_12) +DEFINE_IRQ_HANDLER(1, 13, dma_id_13) +DEFINE_IRQ_HANDLER(1, 14, dma_id_14) +DEFINE_IRQ_HANDLER(1, 15, dma_id_15) +#endif #elif defined(STM32L0) @@ -1424,7 +1480,7 @@ void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint3 dma->Instance = dma_descr->instance; dma->Init = *dma_descr->init; dma->Init.Direction = dir; - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) dma->Init.Request = dma_descr->sub_instance; #else #if !defined(STM32F0) && !defined(STM32L1) @@ -1432,7 +1488,7 @@ void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint3 #endif #endif - #if defined(STM32H5) + #if defined(STM32H5) || defined(STM32N6) // Configure src/dest settings based on the DMA direction. if (dir == DMA_MEMORY_TO_PERIPH) { dma->Init.SrcInc = DMA_SINC_INCREMENTED; @@ -1463,13 +1519,24 @@ void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir dma_enable_clock(dma_id); - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) // Always reset and configure the H7 and G0/G4/H7/L0/L4/WB/WL DMA peripheral // (dma->State is set to HAL_DMA_STATE_RESET by memset above) // TODO: understand how L0/L4 DMA works so this is not needed HAL_DMA_DeInit(dma); dma->Parent = data; // HAL_DMA_DeInit may clear Parent, so set it again HAL_DMA_Init(dma); + + #if defined(STM32N6) + // Configure security attributes. + HAL_DMA_ConfigChannelAttributes(dma, DMA_CHANNEL_PRIV | DMA_CHANNEL_SEC | DMA_CHANNEL_SRC_SEC | DMA_CHANNEL_DEST_SEC); + // Configure data handling. + DMA_DataHandlingConfTypeDef config; + config.DataExchange = DMA_EXCHANGE_NONE; + config.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED; + HAL_DMAEx_ConfigDataHandling(dma, &config); + #endif + NVIC_SetPriority(IRQn_NONNEG(dma_irqn[dma_id]), IRQ_PRI_DMA); #else // if this stream was previously configured for this channel/request and direction then we @@ -1740,7 +1807,7 @@ void dma_nohal_start(const dma_descr_t *descr, uint32_t src_addr, uint32_t dst_a dma->CCR |= DMA_CCR_EN; } -#elif defined(STM32G0) || defined(STM32WB) || defined(STM32WL) +#elif defined(STM32G0) || defined(STM32N6) || defined(STM32WB) || defined(STM32WL) // These functions are currently not implemented or needed for this MCU. |
