diff --git a/arch/arm/src/stm32l4/Kconfig b/arch/arm/src/stm32l4/Kconfig index 758086eefbd..31c0b45124a 100644 --- a/arch/arm/src/stm32l4/Kconfig +++ b/arch/arm/src/stm32l4/Kconfig @@ -574,6 +574,7 @@ config STM32L4_STM32L4XR select STM32L4_HAVE_DCMI select STM32L4_HAVE_DFSDM1 select STM32L4_HAVE_HSI48 + select STM32L4_HAVE_DMAMUX # Chip subfamilies: @@ -945,6 +946,10 @@ config STM32L4_HAVE_DMA2D bool default n +config STM32L4_HAVE_DMAMUX + bool + default n + config STM32L4_HAVE_FSMC bool default n @@ -1069,9 +1074,15 @@ config STM32L4_DFSDM bool default n +config STM32L4_DMAMUX + bool + default n + depends on STM32L4_HAVE_DMAMUX + config STM32L4_DMA bool default n + select STM32L4_DMAMUX if STM32L4_HAVE_DMAMUX config STM32L4_I2C bool @@ -1101,17 +1112,25 @@ config STM32L4_SDMMC comment "AHB1 Peripherals" +config STM32L4_DMAMUX1 + bool "DMAMUX1" + default n + depends on STM32L4_HAVE_DMAMUX + select STM32L4_DMAMUX + config STM32L4_DMA1 bool "DMA1" default n select STM32L4_DMA select ARCH_DMA + select STM32L4_DMAMUX1 if STM32L4_HAVE_DMAMUX config STM32L4_DMA2 bool "DMA2" default n select STM32L4_DMA select ARCH_DMA + select STM32L4_DMAMUX1 if STM32L4_HAVE_DMAMUX config STM32L4_CRC bool "CRC" @@ -1247,13 +1266,13 @@ choice config STM32L4_QSPI_DMA_CHAN_1_5 bool "DMA1 Channel 5" - depends on STM32L4_DMA1 + depends on STM32L4_DMA1 && !STM32L4_DMAMUX ---help--- Use DMA1 channel 5 for QSPI. config STM32L4_QSPI_DMA_CHAN_2_7 bool "DMA2 Channel 7" - depends on STM32L4_DMA2 + depends on STM32L4_DMA2 && !STM32L4_DMAMUX ---help--- Use DMA2 channel 7 for QSPI. @@ -3786,7 +3805,7 @@ config USART1_RS485_DIR_POLARITY config USART1_RXDMA bool "USART1 Rx DMA" default n - depends on STM32L4_USART1 && ( STM32L4_DMA1 || STM32L4_DMA2 ) + depends on STM32L4_USART1 && (STM32L4_DMA1 || STM32L4_DMA2 || STM32L4_DMAMUX) ---help--- In high data rate usage, Rx DMA may eliminate Rx overrun errors @@ -3831,7 +3850,7 @@ config USART2_RS485_DIR_POLARITY config USART2_RXDMA bool "USART2 Rx DMA" default n - depends on STM32L4_USART2 && STM32L4_DMA1 + depends on STM32L4_USART2 && (STM32L4_DMA1 || STM32L4_DMAMUX) ---help--- In high data rate usage, Rx DMA may eliminate Rx overrun errors @@ -3876,7 +3895,7 @@ config USART3_RS485_DIR_POLARITY config USART3_RXDMA bool "USART3 Rx DMA" default n - depends on STM32L4_USART3 && STM32L4_DMA1 + depends on STM32L4_USART3 && (STM32L4_DMA1 || STM32L4_DMAMUX) ---help--- In high data rate usage, Rx DMA may eliminate Rx overrun errors @@ -3921,7 +3940,7 @@ config UART4_RS485_DIR_POLARITY config UART4_RXDMA bool "UART4 Rx DMA" default n - depends on STM32L4_UART4 && STM32L4_DMA2 + depends on STM32L4_UART4 && (STM32L4_DMA2 || STM32L4_DMAMUX) ---help--- In high data rate usage, Rx DMA may eliminate Rx overrun errors @@ -3966,7 +3985,7 @@ config UART5_RS485_DIR_POLARITY config UART5_RXDMA bool "UART5 Rx DMA" default n - depends on STM32L4_UART5 && STM32L4_DMA2 + depends on STM32L4_UART5 && (STM32L4_DMA2 || STM32L4_DMAMUX) ---help--- In high data rate usage, Rx DMA may eliminate Rx overrun errors diff --git a/arch/arm/src/stm32l4/hardware/stm32l4x3xx_dma.h b/arch/arm/src/stm32l4/hardware/stm32l4x3xx_dma.h index bcefef8ca8a..8a7d531525a 100644 --- a/arch/arm/src/stm32l4/hardware/stm32l4x3xx_dma.h +++ b/arch/arm/src/stm32l4/hardware/stm32l4x3xx_dma.h @@ -43,11 +43,6 @@ #define DMA1 0 #define DMA2 1 -#define DMA3 2 -#define DMA4 3 -#define DMA5 4 -#define DMA6 5 -#define DMA7 6 /* Register Offsets *****************************************************************/ diff --git a/arch/arm/src/stm32l4/hardware/stm32l4x5xx_dma.h b/arch/arm/src/stm32l4/hardware/stm32l4x5xx_dma.h index 2c3fa4fd7c1..6ff86f4ed6c 100644 --- a/arch/arm/src/stm32l4/hardware/stm32l4x5xx_dma.h +++ b/arch/arm/src/stm32l4/hardware/stm32l4x5xx_dma.h @@ -43,11 +43,6 @@ #define DMA1 0 #define DMA2 1 -#define DMA3 2 -#define DMA4 3 -#define DMA5 4 -#define DMA6 5 -#define DMA7 6 /* Register Offsets *****************************************************************/ diff --git a/arch/arm/src/stm32l4/hardware/stm32l4x6xx_dma.h b/arch/arm/src/stm32l4/hardware/stm32l4x6xx_dma.h index 3ff7e3cbeec..c16ebbdf7be 100644 --- a/arch/arm/src/stm32l4/hardware/stm32l4x6xx_dma.h +++ b/arch/arm/src/stm32l4/hardware/stm32l4x6xx_dma.h @@ -43,11 +43,6 @@ #define DMA1 0 #define DMA2 1 -#define DMA3 2 -#define DMA4 3 -#define DMA5 4 -#define DMA6 5 -#define DMA7 6 /* Register Offsets *****************************************************************/ diff --git a/arch/arm/src/stm32l4/hardware/stm32l4xrxx_dma.h b/arch/arm/src/stm32l4/hardware/stm32l4xrxx_dma.h index 2c82fd4eb3d..e0141593587 100644 --- a/arch/arm/src/stm32l4/hardware/stm32l4xrxx_dma.h +++ b/arch/arm/src/stm32l4/hardware/stm32l4xrxx_dma.h @@ -36,6 +36,13 @@ #ifndef __ARCH_ARM_SRC_STM32L4_HARDWARE_STM32L4XRXX_DMA_H #define __ARCH_ARM_SRC_STM32L4_HARDWARE_STM32L4XRXX_DMA_H +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include "chip.h" + /************************************************************************************ * Pre-processor Definitions ************************************************************************************/ @@ -44,11 +51,6 @@ #define DMA1 0 #define DMA2 1 -#define DMA3 2 -#define DMA4 3 -#define DMA5 4 -#define DMA6 5 -#define DMA7 6 /* Register Offsets *****************************************************************/ @@ -106,8 +108,6 @@ #define STM32L4_DMA_CMAR6_OFFSET 0x0078 /* DMA channel 6 memory address register */ #define STM32L4_DMA_CMAR7_OFFSET 0x008c /* DMA channel 7 memory address register */ -#define STM32L4_DMA_CSELR_OFFSET 0x00a8 /* DMA channel selection register */ - /* Register Addresses ***************************************************************/ #define STM32L4_DMA1_ISRC (STM32L4_DMA1_BASE+STM32L4_DMA_ISR_OFFSET) @@ -281,227 +281,6 @@ #define DMA_CNDTR_NDT_SHIFT (0) /* Bits 15-0: Number of data to Transfer */ #define DMA_CNDTR_NDT_MASK (0xffff << DMA_CNDTR_NDT_SHIFT) -/* DMA Channel mapping. Each DMA channel has a mapping to one of several - * possible sources/sinks of data. The requests from peripherals assigned to a - * channel are multiplexed together before entering the DMA block. This means - * that only one request on a given channel can be enabled at once. - * - * Alternative DMA channel selections are provided with a numeric suffix like _1, - * _2, etc. Drivers, however, will use the pin selection without the numeric suffix. - * Additional definitions are required in the board.h file. - */ - -#define STM32L4_DMA1_CHAN1 (0) -#define STM32L4_DMA1_CHAN2 (1) -#define STM32L4_DMA1_CHAN3 (2) -#define STM32L4_DMA1_CHAN4 (3) -#define STM32L4_DMA1_CHAN5 (4) -#define STM32L4_DMA1_CHAN6 (5) -#define STM32L4_DMA1_CHAN7 (6) - -#define STM32L4_DMA2_CHAN1 (7) -#define STM32L4_DMA2_CHAN2 (8) -#define STM32L4_DMA2_CHAN3 (9) -#define STM32L4_DMA2_CHAN4 (10) -#define STM32L4_DMA2_CHAN5 (11) -#define STM32L4_DMA2_CHAN6 (12) -#define STM32L4_DMA2_CHAN7 (13) - -/* DMA Channel settings include a channel and an alternative function. - * Channel is in bits 0..7 - * Request number is in bits 8..15 - * - * TODO: THIS IS WRONG! NEED TO USE DMAMUX_1! - */ - -#define DMACHAN_SETTING(chan, req) ((((req) & 0xff) << 8) | ((chan) & 0xff)) -#define DMACHAN_SETTING_CHANNEL_MASK 0x00FF -#define DMACHAN_SETTING_CHANNEL_SHIFT (0) -#define DMACHAN_SETTING_FUNCTION_MASK 0xFF00 -#define DMACHAN_SETTING_FUNCTION_SHIFT (8) - -/* ADC */ - -#define DMACHAN_ADC1_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN1, 0) -#define DMACHAN_ADC1_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN3, 0) - -#define DMACHAN_ADC2_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN1, 0) -#define DMACHAN_ADC2_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN4, 0) - -#define DMACHAN_ADC3_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN1, 0) -#define DMACHAN_ADC3_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN5, 0) - -/* AES */ - -#define DMACHAN_AES_IN_1 DMACHAN_SETTING(STM32L4_DMA2_CHAN1, 6) -#define DMACHAN_AES_IN_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN5, 6) -#define DMACHAN_AES_OUT_1 DMACHAN_SETTING(STM32L4_DMA2_CHAN2, 6) -#define DMACHAN_AES_OUT_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN3, 6) - -/* DAC */ - -#define DMACHAN_DAC1_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN3, 6) -#define DMACHAN_DAC1_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN4, 3) - -#define DMACHAN_DAC2_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN4, 5) -#define DMACHAN_DAC2_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN5, 3) - -/* DCMI */ - -#define DMACHAN_DCMI_1 DMACHAN_SETTING(STM32L4_DMA2_CHAN5, 4) -#define DMACHAN_DCMI_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN6, 0) - -/* DFSDM */ - -#define DMACHAN_DFSDM0 DMACHAN_SETTING(STM32L4_DMA1_CHAN4, 0) -#define DMACHAN_DFSDM1 DMACHAN_SETTING(STM32L4_DMA1_CHAN5, 0) -#define DMACHAN_DFSDM2 DMACHAN_SETTING(STM32L4_DMA1_CHAN6, 0) -#define DMACHAN_DFSDM3 DMACHAN_SETTING(STM32L4_DMA1_CHAN7, 0) - -/* HASH */ - -#define DMACHAN_HASH_IN DMACHAN_SETTING(STM32L4_DMA2_CHAN7, 6) - -/* I2C */ - -#define DMACHAN_I2C1_RX_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN7, 3) -#define DMACHAN_I2C1_RX_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN6, 5) -#define DMACHAN_I2C1_TX_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN6, 3) -#define DMACHAN_I2C1_TX_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN7, 5) - -#define DMACHAN_I2C2_RX DMACHAN_SETTING(STM32L4_DMA1_CHAN5, 3) -#define DMACHAN_I2C2_TX DMACHAN_SETTING(STM32L4_DMA1_CHAN4, 3) - -#define DMACHAN_I2C3_RX DMACHAN_SETTING(STM32L4_DMA1_CHAN3, 2) -#define DMACHAN_I2C3_TX DMACHAN_SETTING(STM32L4_DMA1_CHAN2, 3) - -#define DMACHAN_I2C4_RX DMACHAN_SETTING(STM32L4_DMA2_CHAN1, 0) -#define DMACHAN_I2C4_TX DMACHAN_SETTING(STM32L4_DMA2_CHAN2, 0) - -/* QUADSPI */ - -#define DMACHAN_QUADSPI_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN5, 5) -#define DMACHAN_QUADSPI_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN7, 3) - -/* SAI */ - -#define DMACHAN_SAI1_A_1 DMACHAN_SETTING(STM32L4_DMA2_CHAN1, 1) -#define DMACHAN_SAI1_A_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN6, 1) -#define DMACHAN_SAI1_B_1 DMACHAN_SETTING(STM32L4_DMA2_CHAN2, 1) -#define DMACHAN_SAI1_B_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN7, 1) - -#define DMACHAN_SAI2_A_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN6, 1) -#define DMACHAN_SAI2_A_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN3, 1) -#define DMACHAN_SAI2_B_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN7, 1) -#define DMACHAN_SAI2_B_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN4, 1) - -/* SDMMC */ - -#define DMACHAN_SDMMC_1 DMACHAN_SETTING(STM32L4_DMA2_CHAN4, 7) -#define DMACHAN_SDMMC_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN5, 7) - -/* SPI */ - -#define DMACHAN_SPI1_RX_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN2, 1) -#define DMACHAN_SPI1_RX_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN3, 4) -#define DMACHAN_SPI1_TX_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN3, 1) -#define DMACHAN_SPI1_TX_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN4, 4) - -#define DMACHAN_SPI2_RX DMACHAN_SETTING(STM32L4_DMA1_CHAN4, 1) -#define DMACHAN_SPI2_TX DMACHAN_SETTING(STM32L4_DMA1_CHAN5, 1) - -#define DMACHAN_SPI3_RX DMACHAN_SETTING(STM32L4_DMA2_CHAN1, 3) -#define DMACHAN_SPI3_TX DMACHAN_SETTING(STM32L4_DMA2_CHAN2, 3) - -/* SWPMI */ - -#define DMACHAN_SWPMI_RX DMACHAN_SETTING(STM32L4_DMA2_CHAN1, 4) -#define DMACHAN_SWPMI_TX DMACHAN_SETTING(STM32L4_DMA2_CHAN2, 4) - -/* TIM */ - -#define DMACHAN_TIM1_CH1 DMACHAN_SETTING(STM32L4_DMA1_CHAN2, 7) -#define DMACHAN_TIM1_CH2 DMACHAN_SETTING(STM32L4_DMA1_CHAN3, 7) -#define DMACHAN_TIM1_CH3 DMACHAN_SETTING(STM32L4_DMA1_CHAN7, 7) -#define DMACHAN_TIM1_CH4 DMACHAN_SETTING(STM32L4_DMA1_CHAN4, 7) -#define DMACHAN_TIM1_COM DMACHAN_SETTING(STM32L4_DMA1_CHAN4, 7) -#define DMACHAN_TIM1_TRIG DMACHAN_SETTING(STM32L4_DMA1_CHAN4, 7) -#define DMACHAN_TIM1_UP DMACHAN_SETTING(STM32L4_DMA1_CHAN6, 7) - -#define DMACHAN_TIM2_CH1 DMACHAN_SETTING(STM32L4_DMA1_CHAN5, 4) -#define DMACHAN_TIM2_CH2 DMACHAN_SETTING(STM32L4_DMA1_CHAN7, 4) -#define DMACHAN_TIM2_CH3 DMACHAN_SETTING(STM32L4_DMA1_CHAN1, 4) -#define DMACHAN_TIM2_CH4 DMACHAN_SETTING(STM32L4_DMA1_CHAN7, 4) -#define DMACHAN_TIM2_UP DMACHAN_SETTING(STM32L4_DMA1_CHAN2, 4) - -#define DMACHAN_TIM3_CH1 DMACHAN_SETTING(STM32L4_DMA1_CHAN6, 5) -#define DMACHAN_TIM3_CH3 DMACHAN_SETTING(STM32L4_DMA1_CHAN2, 5) -#define DMACHAN_TIM3_CH4 DMACHAN_SETTING(STM32L4_DMA1_CHAN3, 5) -#define DMACHAN_TIM3_TRIG DMACHAN_SETTING(STM32L4_DMA1_CHAN6, 5) -#define DMACHAN_TIM3_UP DMACHAN_SETTING(STM32L4_DMA1_CHAN3, 5) - -#define DMACHAN_TIM4_CH1 DMACHAN_SETTING(STM32L4_DMA1_CHAN1, 6) -#define DMACHAN_TIM4_CH2 DMACHAN_SETTING(STM32L4_DMA1_CHAN4, 6) -#define DMACHAN_TIM4_CH3 DMACHAN_SETTING(STM32L4_DMA1_CHAN5, 6) -#define DMACHAN_TIM4_UP DMACHAN_SETTING(STM32L4_DMA1_CHAN7, 6) - -#define DMACHAN_TIM5_CH1 DMACHAN_SETTING(STM32L4_DMA2_CHAN5, 5) -#define DMACHAN_TIM5_CH2 DMACHAN_SETTING(STM32L4_DMA2_CHAN4, 5) -#define DMACHAN_TIM5_CH3 DMACHAN_SETTING(STM32L4_DMA2_CHAN2, 5) -#define DMACHAN_TIM5_CH4 DMACHAN_SETTING(STM32L4_DMA2_CHAN1, 5) -#define DMACHAN_TIM5_COM DMACHAN_SETTING(STM32L4_DMA2_CHAN1, 5) -#define DMACHAN_TIM5_TRIG DMACHAN_SETTING(STM32L4_DMA2_CHAN1, 5) -#define DMACHAN_TIM5_UP DMACHAN_SETTING(STM32L4_DMA2_CHAN2, 5) - -#define DMACHAN_TIM6_UP_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN3, 6) -#define DMACHAN_TIM6_UP_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN4, 3) - -#define DMACHAN_TIM7_UP_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN4, 5) -#define DMACHAN_TIM7_UP_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN5, 3) - -#define DMACHAN_TIM8_CH1 DMACHAN_SETTING(STM32L4_DMA2_CHAN6, 7) -#define DMACHAN_TIM8_CH2 DMACHAN_SETTING(STM32L4_DMA2_CHAN7, 7) -#define DMACHAN_TIM8_CH3 DMACHAN_SETTING(STM32L4_DMA2_CHAN1, 7) -#define DMACHAN_TIM8_CH4 DMACHAN_SETTING(STM32L4_DMA2_CHAN2, 7) -#define DMACHAN_TIM8_COM DMACHAN_SETTING(STM32L4_DMA2_CHAN2, 7) -#define DMACHAN_TIM8_TRIG DMACHAN_SETTING(STM32L4_DMA2_CHAN2, 7) -#define DMACHAN_TIM8_UP DMACHAN_SETTING(STM32L4_DMA2_CHAN1, 7) - -#define DMACHAN_TIM15_CH1 DMACHAN_SETTING(STM32L4_DMA1_CHAN5, 7) -#define DMACHAN_TIM15_COM DMACHAN_SETTING(STM32L4_DMA1_CHAN5, 7) -#define DMACHAN_TIM15_TRIG DMACHAN_SETTING(STM32L4_DMA1_CHAN5, 7) -#define DMACHAN_TIM15_UP DMACHAN_SETTING(STM32L4_DMA1_CHAN5, 7) - -#define DMACHAN_TIM16_CH1_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN3, 4) -#define DMACHAN_TIM16_CH1_2 DMACHAN_SETTING(STM32L4_DMA1_CHAN6, 4) -#define DMACHAN_TIM16_UP_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN3, 4) -#define DMACHAN_TIM16_UP_2 DMACHAN_SETTING(STM32L4_DMA1_CHAN6, 4) - -#define DMACHAN_TIM17_CH1_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN1, 5) -#define DMACHAN_TIM17_CH1_2 DMACHAN_SETTING(STM32L4_DMA1_CHAN7, 5) -#define DMACHAN_TIM17_UP_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN1, 5) -#define DMACHAN_TIM17_UP_2 DMACHAN_SETTING(STM32L4_DMA1_CHAN7, 5) - -/* UART */ - -#define DMACHAN_USART1_RX_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN5, 2) -#define DMACHAN_USART1_RX_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN7, 2) -#define DMACHAN_USART1_TX_1 DMACHAN_SETTING(STM32L4_DMA1_CHAN4, 2) -#define DMACHAN_USART1_TX_2 DMACHAN_SETTING(STM32L4_DMA2_CHAN6, 2) - -#define DMACHAN_USART2_RX DMACHAN_SETTING(STM32L4_DMA1_CHAN6, 2) -#define DMACHAN_USART2_TX DMACHAN_SETTING(STM32L4_DMA1_CHAN7, 2) - -#define DMACHAN_USART3_RX DMACHAN_SETTING(STM32L4_DMA1_CHAN3, 2) -#define DMACHAN_USART3_TX DMACHAN_SETTING(STM32L4_DMA1_CHAN2, 2) - -#define DMACHAN_UART5_RX DMACHAN_SETTING(STM32L4_DMA2_CHAN2, 2) -#define DMACHAN_UART5_TX DMACHAN_SETTING(STM32L4_DMA2_CHAN1, 2) - -#define DMACHAN_UART4_RX DMACHAN_SETTING(STM32L4_DMA2_CHAN5, 2) -#define DMACHAN_UART4_TX DMACHAN_SETTING(STM32L4_DMA2_CHAN3, 2) - -#define DMACHAN_LPUART_RX DMACHAN_SETTING(STM32L4_DMA2_CHAN7, 4) -#define DMACHAN_LPUART_TX DMACHAN_SETTING(STM32L4_DMA2_CHAN6, 4) +/* NOTE: DMA channel mapping is done through DMAMUX1. */ #endif /* __ARCH_ARM_SRC_STM32L4_HARDWARE_STM32L4XRXX_DMA_H */ diff --git a/arch/arm/src/stm32l4/hardware/stm32l4xrxx_dmamux.h b/arch/arm/src/stm32l4/hardware/stm32l4xrxx_dmamux.h new file mode 100644 index 00000000000..1f331eaba63 --- /dev/null +++ b/arch/arm/src/stm32l4/hardware/stm32l4xrxx_dmamux.h @@ -0,0 +1,460 @@ +/************************************************************************************ + * arch/arm/src/stm32l4/hardware/stm32l4xrxx_dmamux.h + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Jussi Kivilinna + * + * Based on STM32H7 DMAMUX: + * Author: Mateusz Szafoni + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32L4_HARDWARE_STM32L4XRXX_DMAMUX_H +#define __ARCH_ARM_SRC_STM32L4_HARDWARE_STM32L4XRXX_DMAMUX_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include "chip.h" +#include "stm32l4xrxx_dma.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#define DMAMUX1 0 + +/* Register Offsets *****************************************************************/ + +#define STM32L4_DMAMUX_CXCR_OFFSET(x) (0x0000+0x0004*(x)) /* DMAMUX1 request line multiplexer channel x configuration register */ +#define STM32L4_DMAMUX_C0CR_OFFSET STM32L4_DMAMUX_CXCR_OFFSET(0) +#define STM32L4_DMAMUX_C1CR_OFFSET STM32L4_DMAMUX_CXCR_OFFSET(1) +#define STM32L4_DMAMUX_C2CR_OFFSET STM32L4_DMAMUX_CXCR_OFFSET(2) +#define STM32L4_DMAMUX_C3CR_OFFSET STM32L4_DMAMUX_CXCR_OFFSET(3) +#define STM32L4_DMAMUX_C4CR_OFFSET STM32L4_DMAMUX_CXCR_OFFSET(4) +#define STM32L4_DMAMUX_C5CR_OFFSET STM32L4_DMAMUX_CXCR_OFFSET(5) +#define STM32L4_DMAMUX_C6CR_OFFSET STM32L4_DMAMUX_CXCR_OFFSET(6) +#define STM32L4_DMAMUX_C7CR_OFFSET STM32L4_DMAMUX_CXCR_OFFSET(7) +#define STM32L4_DMAMUX_C8CR_OFFSET STM32L4_DMAMUX_CXCR_OFFSET(8) +#define STM32L4_DMAMUX_C9CR_OFFSET STM32L4_DMAMUX_CXCR_OFFSET(9) +#define STM32L4_DMAMUX_C10CR_OFFSET STM32L4_DMAMUX_CXCR_OFFSET(10) +#define STM32L4_DMAMUX_C11CR_OFFSET STM32L4_DMAMUX_CXCR_OFFSET(11) +#define STM32L4_DMAMUX_C12CR_OFFSET STM32L4_DMAMUX_CXCR_OFFSET(12) +#define STM32L4_DMAMUX_C13CR_OFFSET STM32L4_DMAMUX_CXCR_OFFSET(13) + /* 0x034-0x07C: Reserved */ +#define STM32L4_DMAMUX_CSR_OFFSET 0x0080 /* DMAMUX1 request line multiplexer interrupt channel status register */ +#define STM32L4_DMAMUX_CFR_OFFSET 0x0084 /* DMAMUX1 request line multiplexer interrupt clear flag register */ + /* 0x088-0x0FC: Reserved */ +#define STM32L4_DMAMUX_RGXCR_OFFSET(x) (0x0100+0x004*(x)) /* DMAMUX1 request generator channel x configuration register */ +#define STM32L4_DMAMUX_RG0CR_OFFSET STM32L4_DMAMUX_RGXCR_OFFSET(0) +#define STM32L4_DMAMUX_RG1CR_OFFSET STM32L4_DMAMUX_RGXCR_OFFSET(1) +#define STM32L4_DMAMUX_RG2CR_OFFSET STM32L4_DMAMUX_RGXCR_OFFSET(2) +#define STM32L4_DMAMUX_RG3CR_OFFSET STM32L4_DMAMUX_RGXCR_OFFSET(3) +#define STM32L4_DMAMUX_RGSR_OFFSET 0x0140 /* DMAMUX1 request generator interrupt status register */ +#define STM32L4_DMAMUX_RGCFR_OFFSET 0x0144 /* DMAMUX1 request generator interrupt clear flag register */ + /* 0x148-0x3FC: Reserved */ + +/* Register Addresses ***************************************************************/ + +#define STM32L4_DMAMUX1_CXCR(x) (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_CXCR_OFFSET(x)) +#define STM32L4_DMAMUX1_C0CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_C0CR_OFFSET) +#define STM32L4_DMAMUX1_C1CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_C1CR_OFFSET) +#define STM32L4_DMAMUX1_C2CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_C2CR_OFFSET) +#define STM32L4_DMAMUX1_C3CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_C3CR_OFFSET) +#define STM32L4_DMAMUX1_C4CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_C4CR_OFFSET) +#define STM32L4_DMAMUX1_C5CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_C5CR_OFFSET) +#define STM32L4_DMAMUX1_C6CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_C6CR_OFFSET) +#define STM32L4_DMAMUX1_C7CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_C7CR_OFFSET) +#define STM32L4_DMAMUX1_C8CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_C8CR_OFFSET) +#define STM32L4_DMAMUX1_C9CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_C9CR_OFFSET) +#define STM32L4_DMAMUX1_C10CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_C10CR_OFFSET) +#define STM32L4_DMAMUX1_C11CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_C11CR_OFFSET) +#define STM32L4_DMAMUX1_C12CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_C12CR_OFFSET) +#define STM32L4_DMAMUX1_C13CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_C12CR_OFFSET) + +#define STM32L4_DMAMUX1_CSR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_CSR_OFFSET) +#define STM32L4_DMAMUX1_CFR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_CFR_OFFSET) + +#define STM32L4_DMAMUX1_RGXCR(x) (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_RGXCR_OFFSET(x)) +#define STM32L4_DMAMUX1_RG0CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_RG0CR_OFFSET) +#define STM32L4_DMAMUX1_RG1CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_RG1CR_OFFSET) +#define STM32L4_DMAMUX1_RG2CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_RG2CR_OFFSET) +#define STM32L4_DMAMUX1_RG3CR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_RG3CR_OFFSET) + +#define STM32L4_DMAMUX1_RGSR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_RGSR_OFFSET) +#define STM32L4_DMAMUX1_RGCFR (STM32L4_DMAMUX1_BASE+STM32L4_DMAMUX_RGCFR_OFFSET) + +/* Register Bitfield Definitions ****************************************************/ + +/* DMAMUX1 request line multiplexer channel x configuration register */ + +#define DMAMUX_CCR_DMAREQID_SHIFT (0) /* Bits 0-6: DMA request identification */ +#define DMAMUX_CCR_DMAREQID_MASK (0x7f << DMAMUX_CCR_DMAREQID_SHIFT) +#define DMAMUX_CCR_SOIE (8) /* Bit 8: Synchronization overrun interrupt enable */ +#define DMAMUX_CCR_EGE (9) /* Bit 9: Event generation enable */ +#define DMAMUX_CCR_SE (16) /* Bit 16: Synchronization enable */ +#define DMAMUX_CCR_SPOL_SHIFT (17) /* Bits 17-18: Synchronization polarity */ +#define DMAMUX_CCR_SPOL_MASK (3 << DMAMUX_CCR_SPOL_SHIFT) +#define DMAMUX_CCR_NBREQ_SHIFT (19) /* Bits 19-23: Number of DMA request - 1 to forward */ +#define DMAMUX_CCR_NBREQ_MASK (0x1f << DMAMUX_CCR_NBREQ_SHIFT) +#define DMAMUX_CCR_SYNCID_SHIFT (24) /* Bits 24-28: Synchronization identification */ +#define DMAMUX_CCR_SYNCID_MASK (0x1f << DMAMUX_CCR_SYNCID_SHIFT) + +/* DMAMUX1 request line multiplexer interrupt channel status register */ + +#define DMAMUX_CSR_SOF(x) (1 << (x)) /* Synchronization overrun event flag */ + +/* DMAMUX1 request line multiplexer interrupt clear flag register */ + +#define DMAMUX_CFR_CSOF(x) (1 << (x)) /* Clear synchronization overrun event flag */ + +/* DMAMUX1 request generator channel x configuration register */ + +#define DMAMUX_RGCR_SIGID_SHIFT (0) /* Bits 0-4: Signal identifiaction */ +#define DMAMUX_RGCR_SIGID_MASK (0x1f << DMAMUX_RGCR_SIGID_SHIFT) +#define DMAMUX_RGCR_OIE (8) /* Bit 8: Trigger overrun interrupt enable */ +#define DMAMUX_RGCR_GE (16) /* Bit 16: DMA request generator channel X enable*/ +#define DMAMUX_RGCR_GPOL_SHIFT (17) /* Bits 17-18: DMA request generator trigger polarity */ +#define DMAMUX_RGCR_GPOL_MASK (7 << DMAMUX_RGCR_GPOL_SHIFT) +#define DMAMUX_RGCR_GNBREQ_SHIFT (17) /* Bits 19-23: Number of DMA requests to be generated -1 */ +#define DMAMUX_RGCR_GNBREQL_MASK (7 << DMAMUX_RGCR_GNBREQ_SHIFT) + +/* DMAMUX1 request generator interrupt status register */ + +#define DMAMUX_RGSR_OF(x) (1 << (x)) /* Trigger overrun event flag */ + +/* DMAMUX1 request generator interrupt clear flag register */ + +#define DMAMUX_RGCFR_COF(x) (1 << (x)) /* Clear trigger overrun event flag */ + +/* DMA channel mapping + * + * D.CCCCCCC + * C - DMAMUX1 request + * D - DMA controller (DMA1, DMA2) + */ + +#define DMAMAP_MAP(d,c) ((((d) & 0x01) << 7) | ((c) & 0x7f)) +#define DMAMAP_CONTROLLER(m) (((m) >> 7) & 0x01) +#define DMAMAP_REQUEST(m) (((m) >> 0) & 0x7f) + +/* DMAMUX1 mapping ******************************************************************/ + +/* NOTE: DMAMUX1 channels 0 to 6 are connected to DMA1 channels 1 to 7. + * DMAMUX1 channels 7 to 13 are connected to DMA2 channels 1 to 7. + */ + +#define DMAMUX1_REQ_GEN0 (1) +#define DMAMUX1_REQ_GEN1 (2) +#define DMAMUX1_REQ_GEN2 (3) +#define DMAMUX1_REQ_GEN3 (4) +#define DMAMUX1_ADC1 (5) +#define DMAMUX1_DAC1 (6) +#define DMAMUX1_DAC2 (7) +#define DMAMUX1_TIM6_UP (8) +#define DMAMUX1_TIM7_UP (9) +#define DMAMUX1_SPI1_RX (10) +#define DMAMUX1_SPI1_TX (11) +#define DMAMUX1_SPI2_RX (12) +#define DMAMUX1_SPI2_TX (13) +#define DMAMUX1_SPI3_RX (14) +#define DMAMUX1_SPI3_TX (15) +#define DMAMUX1_I2C1_RX (16) +#define DMAMUX1_I2C1_TX (17) +#define DMAMUX1_I2C2_RX (18) +#define DMAMUX1_I2C2_TX (19) +#define DMAMUX1_I2C3_RX (20) +#define DMAMUX1_I2C3_TX (21) +#define DMAMUX1_I2C4_RX (22) +#define DMAMUX1_I2C4_TX (23) +#define DMAMUX1_USART1_RX (24) +#define DMAMUX1_USART1_TX (25) +#define DMAMUX1_USART2_RX (26) +#define DMAMUX1_USART2_TX (27) +#define DMAMUX1_USART3_RX (28) +#define DMAMUX1_USART3_TX (29) +#define DMAMUX1_UART4_RX (30) +#define DMAMUX1_UART4_TX (31) +#define DMAMUX1_UART5_RX (32) +#define DMAMUX1_UART5_TX (33) +#define DMAMUX1_LPUART1_RX (34) +#define DMAMUX1_LPUART1_TX (35) +#define DMAMUX1_SAI1_A (36) +#define DMAMUX1_SAI1_B (37) +#define DMAMUX1_SAI2_A (38) +#define DMAMUX1_SAI2_B (39) +#define DMAMUX1_OCTOSPI1 (40) +#define DMAMUX1_OCTOSPI2 (41) +#define DMAMUX1_TIM1_CH1 (42) +#define DMAMUX1_TIM1_CH2 (43) +#define DMAMUX1_TIM1_CH3 (44) +#define DMAMUX1_TIM1_CH4 (45) +#define DMAMUX1_TIM1_UP (46) +#define DMAMUX1_TIM1_TRIG (47) +#define DMAMUX1_TIM1_COM (48) +#define DMAMUX1_TIM8_CH1 (49) +#define DMAMUX1_TIM8_CH2 (50) +#define DMAMUX1_TIM8_CH3 (51) +#define DMAMUX1_TIM8_CH4 (52) +#define DMAMUX1_TIM8_UP (53) +#define DMAMUX1_TIM8_TRIG (54) +#define DMAMUX1_TIM8_COM (55) +#define DMAMUX1_TIM2_CH1 (56) +#define DMAMUX1_TIM2_CH2 (57) +#define DMAMUX1_TIM2_CH3 (58) +#define DMAMUX1_TIM2_CH4 (59) +#define DMAMUX1_TIM2_UP (60) +#define DMAMUX1_TIM3_CH1 (61) +#define DMAMUX1_TIM3_CH2 (62) +#define DMAMUX1_TIM3_CH3 (63) +#define DMAMUX1_TIM3_CH4 (64) +#define DMAMUX1_TIM3_UP (65) +#define DMAMUX1_TIM3_TRIG (66) +#define DMAMUX1_TIM4_CH1 (67) +#define DMAMUX1_TIM4_CH2 (68) +#define DMAMUX1_TIM4_CH3 (69) +#define DMAMUX1_TIM4_CH4 (70) +#define DMAMUX1_TIM4_UP (71) +#define DMAMUX1_TIM5_CH1 (72) +#define DMAMUX1_TIM5_CH2 (73) +#define DMAMUX1_TIM5_CH3 (74) +#define DMAMUX1_TIM5_CH4 (75) +#define DMAMUX1_TIM5_UP (76) +#define DMAMUX1_TIM5_TRIG (77) +#define DMAMUX1_TIM15_CH1 (78) +#define DMAMUX1_TIM15_UP (79) +#define DMAMUX1_TIM15_TRIG (80) +#define DMAMUX1_TIM15_COM (81) +#define DMAMUX1_TIM16_CH1 (82) +#define DMAMUX1_TIM16_UP (83) +#define DMAMUX1_TIM17_CH1 (84) +#define DMAMUX1_TIM17_UP (85) +#define DMAMUX1_DFSDM1_0 (86) +#define DMAMUX1_DFSDM1_1 (87) +#define DMAMUX1_DFSDM1_2 (88) +#define DMAMUX1_DFSDM1_3 (89) +#define DMAMUX1_DCMI (90) +#define DMAMUX1_AES_IN (91) +#define DMAMUX1_AES_OUT (92) +#define DMAMUX1_HASH_IN (93) +/* DMAMUX1 94-127: Reserved */ + +/* DMAMAP for DMA1 and DMA2 (DMAMUX1) ***********************************************/ + +#define DMAMAP_REQ_GEN0_0 DMAMAP_MAP(DMA1, DMAMUX1_REQ_GEN0) +#define DMAMAP_REQ_GEN0_1 DMAMAP_MAP(DMA2, DMAMUX1_REQ_GEN0) +#define DMAMAP_REQ_GEN1_0 DMAMAP_MAP(DMA1, DMAMUX1_REQ_GEN1) +#define DMAMAP_REQ_GEN1_1 DMAMAP_MAP(DMA2, DMAMUX1_REQ_GEN1) +#define DMAMAP_REQ_GEN2_0 DMAMAP_MAP(DMA1, DMAMUX1_REQ_GEN2) +#define DMAMAP_REQ_GEN2_1 DMAMAP_MAP(DMA2, DMAMUX1_REQ_GEN2) +#define DMAMAP_REQ_GEN3_0 DMAMAP_MAP(DMA1, DMAMUX1_REQ_GEN3) +#define DMAMAP_REQ_GEN3_1 DMAMAP_MAP(DMA2, DMAMUX1_REQ_GEN3) +#define DMAMAP_ADC1_0 DMAMAP_MAP(DMA1, DMAMUX1_ADC1) +#define DMAMAP_ADC1_1 DMAMAP_MAP(DMA2, DMAMUX1_ADC1) +#define DMAMAP_DAC1_0 DMAMAP_MAP(DMA1, DMAMUX1_DAC1) +#define DMAMAP_DAC1_1 DMAMAP_MAP(DMA2, DMAMUX1_DAC1) +#define DMAMAP_DAC2_0 DMAMAP_MAP(DMA1, DMAMUX1_DAC2) +#define DMAMAP_DAC2_1 DMAMAP_MAP(DMA2, DMAMUX1_DAC2) +#define DMAMAP_TIM6_UP_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM6_UP) +#define DMAMAP_TIM6_UP_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM6_UP) +#define DMAMAP_TIM7_UP_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM7_UP) +#define DMAMAP_TIM7_UP_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM7_UP) +#define DMAMAP_SPI1_RX_0 DMAMAP_MAP(DMA1, DMAMUX1_SPI1_RX) +#define DMAMAP_SPI1_RX_1 DMAMAP_MAP(DMA2, DMAMUX1_SPI1_RX) +#define DMAMAP_SPI1_TX_0 DMAMAP_MAP(DMA1, DMAMUX1_SPI1_TX) +#define DMAMAP_SPI1_TX_1 DMAMAP_MAP(DMA2, DMAMUX1_SPI1_TX) +#define DMAMAP_SPI2_RX_0 DMAMAP_MAP(DMA1, DMAMUX1_SPI2_RX) +#define DMAMAP_SPI2_RX_1 DMAMAP_MAP(DMA2, DMAMUX1_SPI2_RX) +#define DMAMAP_SPI2_TX_0 DMAMAP_MAP(DMA1, DMAMUX1_SPI2_TX) +#define DMAMAP_SPI2_TX_1 DMAMAP_MAP(DMA2, DMAMUX1_SPI2_TX) +#define DMAMAP_SPI3_RX_0 DMAMAP_MAP(DMA1, DMAMUX1_SPI3_RX) +#define DMAMAP_SPI3_RX_1 DMAMAP_MAP(DMA2, DMAMUX1_SPI3_RX) +#define DMAMAP_SPI3_TX_0 DMAMAP_MAP(DMA1, DMAMUX1_SPI3_TX) +#define DMAMAP_SPI3_TX_1 DMAMAP_MAP(DMA2, DMAMUX1_SPI3_TX) +#define DMAMAP_I2C1_RX_0 DMAMAP_MAP(DMA1, DMAMUX1_I2C1_RX) +#define DMAMAP_I2C1_RX_1 DMAMAP_MAP(DMA2, DMAMUX1_I2C1_RX) +#define DMAMAP_I2C1_TX_0 DMAMAP_MAP(DMA1, DMAMUX1_I2C1_TX) +#define DMAMAP_I2C1_TX_1 DMAMAP_MAP(DMA2, DMAMUX1_I2C1_TX) +#define DMAMAP_I2C2_RX_0 DMAMAP_MAP(DMA1, DMAMUX1_I2C2_RX) +#define DMAMAP_I2C2_RX_1 DMAMAP_MAP(DMA2, DMAMUX1_I2C2_RX) +#define DMAMAP_I2C2_TX_0 DMAMAP_MAP(DMA1, DMAMUX1_I2C2_TX) +#define DMAMAP_I2C2_TX_1 DMAMAP_MAP(DMA2, DMAMUX1_I2C2_TX) +#define DMAMAP_I2C3_RX_0 DMAMAP_MAP(DMA1, DMAMUX1_I2C3_RX) +#define DMAMAP_I2C3_RX_1 DMAMAP_MAP(DMA2, DMAMUX1_I2C3_RX) +#define DMAMAP_I2C3_TX_0 DMAMAP_MAP(DMA1, DMAMUX1_I2C3_TX) +#define DMAMAP_I2C3_TX_1 DMAMAP_MAP(DMA2, DMAMUX1_I2C3_TX) +#define DMAMAP_I2C4_RX_0 DMAMAP_MAP(DMA1, DMAMUX1_I2C4_RX) +#define DMAMAP_I2C4_RX_1 DMAMAP_MAP(DMA2, DMAMUX1_I2C4_RX) +#define DMAMAP_I2C4_TX_0 DMAMAP_MAP(DMA1, DMAMUX1_I2C4_TX) +#define DMAMAP_I2C4_TX_1 DMAMAP_MAP(DMA2, DMAMUX1_I2C4_TX) +#define DMAMAP_USART1_RX_0 DMAMAP_MAP(DMA1, DMAMUX1_USART1_RX) +#define DMAMAP_USART1_RX_1 DMAMAP_MAP(DMA2, DMAMUX1_USART1_RX) +#define DMAMAP_USART1_TX_0 DMAMAP_MAP(DMA1, DMAMUX1_USART1_TX) +#define DMAMAP_USART1_TX_1 DMAMAP_MAP(DMA2, DMAMUX1_USART1_TX) +#define DMAMAP_USART2_RX_0 DMAMAP_MAP(DMA1, DMAMUX1_USART2_RX) +#define DMAMAP_USART2_RX_1 DMAMAP_MAP(DMA2, DMAMUX1_USART2_RX) +#define DMAMAP_USART2_TX_0 DMAMAP_MAP(DMA1, DMAMUX1_USART2_TX) +#define DMAMAP_USART2_TX_1 DMAMAP_MAP(DMA2, DMAMUX1_USART2_TX) +#define DMAMAP_USART3_RX_0 DMAMAP_MAP(DMA1, DMAMUX1_USART3_RX) +#define DMAMAP_USART3_RX_1 DMAMAP_MAP(DMA2, DMAMUX1_USART3_RX) +#define DMAMAP_USART3_TX_0 DMAMAP_MAP(DMA1, DMAMUX1_USART3_TX) +#define DMAMAP_USART3_TX_1 DMAMAP_MAP(DMA2, DMAMUX1_USART3_TX) +#define DMAMAP_UART4_RX_0 DMAMAP_MAP(DMA1, DMAMUX1_UART4_RX) +#define DMAMAP_UART4_RX_1 DMAMAP_MAP(DMA2, DMAMUX1_UART4_RX) +#define DMAMAP_UART4_TX_0 DMAMAP_MAP(DMA1, DMAMUX1_UART4_TX) +#define DMAMAP_UART4_TX_1 DMAMAP_MAP(DMA2, DMAMUX1_UART4_TX) +#define DMAMAP_UART5_RX_0 DMAMAP_MAP(DMA1, DMAMUX1_UART5_RX) +#define DMAMAP_UART5_RX_1 DMAMAP_MAP(DMA2, DMAMUX1_UART5_RX) +#define DMAMAP_UART5_TX_0 DMAMAP_MAP(DMA1, DMAMUX1_UART5_TX) +#define DMAMAP_UART5_TX_1 DMAMAP_MAP(DMA2, DMAMUX1_UART5_TX) +#define DMAMAP_LPUART1_RX_0 DMAMAP_MAP(DMA1, DMAMUX1_LPUART1_RX) +#define DMAMAP_LPUART1_RX_1 DMAMAP_MAP(DMA2, DMAMUX1_LPUART1_RX) +#define DMAMAP_LPUART1_TX_0 DMAMAP_MAP(DMA1, DMAMUX1_LPUART1_TX) +#define DMAMAP_LPUART1_TX_1 DMAMAP_MAP(DMA2, DMAMUX1_LPUART1_TX) +#define DMAMAP_SAI1_A_0 DMAMAP_MAP(DMA1, DMAMUX1_SAI1_A) +#define DMAMAP_SAI1_A_1 DMAMAP_MAP(DMA2, DMAMUX1_SAI1_A) +#define DMAMAP_SAI1_B_0 DMAMAP_MAP(DMA1, DMAMUX1_SAI1_B) +#define DMAMAP_SAI1_B_1 DMAMAP_MAP(DMA2, DMAMUX1_SAI1_B) +#define DMAMAP_SAI2_A_0 DMAMAP_MAP(DMA1, DMAMUX1_SAI2_A) +#define DMAMAP_SAI2_A_1 DMAMAP_MAP(DMA2, DMAMUX1_SAI2_A) +#define DMAMAP_SAI2_B_0 DMAMAP_MAP(DMA1, DMAMUX1_SAI2_B) +#define DMAMAP_SAI2_B_1 DMAMAP_MAP(DMA2, DMAMUX1_SAI2_B) +#define DMAMAP_OCTOSPI1_0 DMAMAP_MAP(DMA1, DMAMUX1_OCTOSPI1) +#define DMAMAP_OCTOSPI1_1 DMAMAP_MAP(DMA2, DMAMUX1_OCTOSPI1) +#define DMAMAP_OCTOSPI2_0 DMAMAP_MAP(DMA1, DMAMUX1_OCTOSPI2) +#define DMAMAP_OCTOSPI2_1 DMAMAP_MAP(DMA2, DMAMUX1_OCTOSPI2) +#define DMAMAP_TIM1_CH1_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM1_CH1) +#define DMAMAP_TIM1_CH1_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM1_CH1) +#define DMAMAP_TIM1_CH2_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM1_CH2) +#define DMAMAP_TIM1_CH2_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM1_CH2) +#define DMAMAP_TIM1_CH3_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM1_CH3) +#define DMAMAP_TIM1_CH3_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM1_CH3) +#define DMAMAP_TIM1_CH4_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM1_CH4) +#define DMAMAP_TIM1_CH4_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM1_CH4) +#define DMAMAP_TIM1_UP_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM1_UP) +#define DMAMAP_TIM1_UP_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM1_UP) +#define DMAMAP_TIM1_TRIG_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM1_TRIG) +#define DMAMAP_TIM1_TRIG_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM1_TRIG) +#define DMAMAP_TIM1_COM_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM1_COM) +#define DMAMAP_TIM1_COM_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM1_COM) +#define DMAMAP_TIM8_CH1_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM8_CH1) +#define DMAMAP_TIM8_CH1_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM8_CH1) +#define DMAMAP_TIM8_CH2_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM8_CH2) +#define DMAMAP_TIM8_CH2_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM8_CH2) +#define DMAMAP_TIM8_CH3_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM8_CH3) +#define DMAMAP_TIM8_CH3_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM8_CH3) +#define DMAMAP_TIM8_CH4_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM8_CH4) +#define DMAMAP_TIM8_CH4_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM8_CH4) +#define DMAMAP_TIM8_UP_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM8_UP) +#define DMAMAP_TIM8_UP_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM8_UP) +#define DMAMAP_TIM8_TRIG_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM8_TRIG) +#define DMAMAP_TIM8_TRIG_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM8_TRIG) +#define DMAMAP_TIM8_COM_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM8_COM) +#define DMAMAP_TIM8_COM_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM8_COM) +#define DMAMAP_TIM2_CH1_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM2_CH1) +#define DMAMAP_TIM2_CH1_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM2_CH1) +#define DMAMAP_TIM2_CH2_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM2_CH2) +#define DMAMAP_TIM2_CH2_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM2_CH2) +#define DMAMAP_TIM2_CH3_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM2_CH3) +#define DMAMAP_TIM2_CH3_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM2_CH3) +#define DMAMAP_TIM2_CH4_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM2_CH4) +#define DMAMAP_TIM2_CH4_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM2_CH4) +#define DMAMAP_TIM2_UP_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM2_UP) +#define DMAMAP_TIM2_UP_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM2_UP) +#define DMAMAP_TIM3_CH1_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM3_CH1) +#define DMAMAP_TIM3_CH1_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM3_CH1) +#define DMAMAP_TIM3_CH2_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM3_CH2) +#define DMAMAP_TIM3_CH2_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM3_CH2) +#define DMAMAP_TIM3_CH3_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM3_CH3) +#define DMAMAP_TIM3_CH3_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM3_CH3) +#define DMAMAP_TIM3_CH4_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM3_CH4) +#define DMAMAP_TIM3_CH4_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM3_CH4) +#define DMAMAP_TIM3_UP_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM3_UP) +#define DMAMAP_TIM3_UP_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM3_UP) +#define DMAMAP_TIM3_TRIG_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM3_TRIG) +#define DMAMAP_TIM3_TRIG_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM3_TRIG) +#define DMAMAP_TIM4_CH1_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM4_CH1) +#define DMAMAP_TIM4_CH1_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM4_CH1) +#define DMAMAP_TIM4_CH2_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM4_CH2) +#define DMAMAP_TIM4_CH2_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM4_CH2) +#define DMAMAP_TIM4_CH3_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM4_CH3) +#define DMAMAP_TIM4_CH3_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM4_CH3) +#define DMAMAP_TIM4_CH4_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM4_CH4) +#define DMAMAP_TIM4_CH4_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM4_CH4) +#define DMAMAP_TIM4_UP_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM4_UP) +#define DMAMAP_TIM4_UP_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM4_UP) +#define DMAMAP_TIM5_CH1_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM5_CH1) +#define DMAMAP_TIM5_CH1_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM5_CH1) +#define DMAMAP_TIM5_CH2_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM5_CH2) +#define DMAMAP_TIM5_CH2_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM5_CH2) +#define DMAMAP_TIM5_CH3_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM5_CH3) +#define DMAMAP_TIM5_CH3_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM5_CH3) +#define DMAMAP_TIM5_CH4_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM5_CH4) +#define DMAMAP_TIM5_CH4_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM5_CH4) +#define DMAMAP_TIM5_UP_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM5_UP) +#define DMAMAP_TIM5_UP_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM5_UP) +#define DMAMAP_TIM5_TRIG_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM5_TRIG) +#define DMAMAP_TIM5_TRIG_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM5_TRIG) +#define DMAMAP_TIM15_CH1_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM15_CH1) +#define DMAMAP_TIM15_CH1_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM15_CH1) +#define DMAMAP_TIM15_UP_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM15_UP) +#define DMAMAP_TIM15_UP_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM15_UP) +#define DMAMAP_TIM15_TRIG_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM15_TRIG) +#define DMAMAP_TIM15_TRIG_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM15_TRIG) +#define DMAMAP_TIM15_COM_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM15_COM) +#define DMAMAP_TIM15_COM_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM15_COM) +#define DMAMAP_TIM16_CH1_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM16_CH1) +#define DMAMAP_TIM16_CH1_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM16_CH1) +#define DMAMAP_TIM16_UP_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM16_UP) +#define DMAMAP_TIM16_UP_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM16_UP) +#define DMAMAP_TIM17_CH1_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM17_CH1) +#define DMAMAP_TIM17_CH1_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM17_CH1) +#define DMAMAP_TIM17_UP_0 DMAMAP_MAP(DMA1, DMAMUX1_TIM17_UP) +#define DMAMAP_TIM17_UP_1 DMAMAP_MAP(DMA2, DMAMUX1_TIM17_UP) +#define DMAMAP_DFSDM0_0 DMAMAP_MAP(DMA1, DMAMUX1_DFSDM1_0) +#define DMAMAP_DFSDM0_1 DMAMAP_MAP(DMA2, DMAMUX1_DFSDM1_0) +#define DMAMAP_DFSDM1_0 DMAMAP_MAP(DMA1, DMAMUX1_DFSDM1_1) +#define DMAMAP_DFSDM1_1 DMAMAP_MAP(DMA2, DMAMUX1_DFSDM1_1) +#define DMAMAP_DFSDM2_0 DMAMAP_MAP(DMA1, DMAMUX1_DFSDM1_2) +#define DMAMAP_DFSDM2_1 DMAMAP_MAP(DMA2, DMAMUX1_DFSDM1_2) +#define DMAMAP_DFSDM3_0 DMAMAP_MAP(DMA1, DMAMUX1_DFSDM1_3) +#define DMAMAP_DFSDM3_1 DMAMAP_MAP(DMA2, DMAMUX1_DFSDM1_3) +#define DMAMAP_DCMI_0 DMAMAP_MAP(DMA1, DMAMUX1_DCMI) +#define DMAMAP_DCMI_1 DMAMAP_MAP(DMA2, DMAMUX1_DCMI) +#define DMAMAP_AES_IN_0 DMAMAP_MAP(DMA1, DMAMUX1_AES_IN) +#define DMAMAP_AES_IN_1 DMAMAP_MAP(DMA2, DMAMUX1_AES_IN) +#define DMAMAP_AES_OUT_0 DMAMAP_MAP(DMA1, DMAMUX1_AES_OUT) +#define DMAMAP_AES_OUT_1 DMAMAP_MAP(DMA2, DMAMUX1_AES_OUT) +#define DMAMAP_HASH_IN_0 DMAMAP_MAP(DMA1, DMAMUX1_HASH_IN) +#define DMAMAP_HASH_IN_1 DMAMAP_MAP(DMA2, DMAMUX1_HASH_IN) + +#endif /* __ARCH_ARM_SRC_STM32L4_HARDWARE_STM32L4XRXX_DMAMUX_H */ diff --git a/arch/arm/src/stm32l4/stm32l4_dac.c b/arch/arm/src/stm32l4/stm32l4_dac.c index 473fa9fd5d3..69dfe16f71c 100644 --- a/arch/arm/src/stm32l4/stm32l4_dac.c +++ b/arch/arm/src/stm32l4/stm32l4_dac.c @@ -133,7 +133,11 @@ #undef HAVE_DMA #ifdef CONFIG_STM32L4_DAC1_DMA -# if defined(CONFIG_STM32L4_DMA1) +# if defined(CONFIG_STM32L4_DMAMUX1) && defined(CONFIG_STM32L4_DMA1) +# define DAC1_DMA_CHAN DMAMAP_DAC1_0 +# elif defined(CONFIG_STM32L4_DMAMUX1) && defined(CONFIG_STM32L4_DMA2) +# define DAC1_DMA_CHAN DMAMAP_DAC1_1 +# elif defined(CONFIG_STM32L4_DMA1) # define DAC1_DMA_CHAN DMACHAN_DAC1_1 # elif defined(CONFIG_STM32L4_DMA2) # define DAC1_DMA_CHAN DMACHAN_DAC1_2 @@ -143,7 +147,11 @@ # define HAVE_DMA #endif #ifdef CONFIG_STM32L4_DAC2_DMA -# if defined(CONFIG_STM32L4_DMA1) +# if defined(CONFIG_STM32L4_DMAMUX1) && defined(CONFIG_STM32L4_DMA1) +# define DAC2_DMA_CHAN DMAMAP_DAC2_0 +# elif defined(CONFIG_STM32L4_DMAMUX1) && defined(CONFIG_STM32L4_DMA2) +# define DAC2_DMA_CHAN DMAMAP_DAC2_1 +# elif defined(CONFIG_STM32L4_DMA1) # define DAC2_DMA_CHAN DMACHAN_DAC2_1 # elif defined(CONFIG_STM32L4_DMA2) # define DAC2_DMA_CHAN DMACHAN_DAC2_2 diff --git a/arch/arm/src/stm32l4/stm32l4_dfsdm.c b/arch/arm/src/stm32l4/stm32l4_dfsdm.c index d8328cebd52..1cd9edf0bba 100644 --- a/arch/arm/src/stm32l4/stm32l4_dfsdm.c +++ b/arch/arm/src/stm32l4/stm32l4_dfsdm.c @@ -143,7 +143,7 @@ #endif #ifdef DFSDM_HAVE_DMA -# if !defined(CONFIG_STM32L4_DMA1) +# if !defined(CONFIG_STM32L4_DMA1) && !defined(CONFIG_STM32L4_DMAMUX) # error "STM32L4 DFSDM DMA support requires CONFIG_STM32L4_DMA1" # endif #endif diff --git a/arch/arm/src/stm32l4/stm32l4_dma.c b/arch/arm/src/stm32l4/stm32l4_dma.c index 18095182bf0..897e3231e24 100644 --- a/arch/arm/src/stm32l4/stm32l4_dma.c +++ b/arch/arm/src/stm32l4/stm32l4_dma.c @@ -45,13 +45,13 @@ * for the selected STM32 family. The correct file cannot be selected by * the make system because it needs the intelligence that only exists in * chip.h that can associate an STM32 part number with an STM32 family. - * - * TODO: do we need separate implementation for STM32L4X3? */ #if defined(CONFIG_STM32L4_STM32L4X3) || defined(CONFIG_STM32L4_STM32L4X5) || \ - defined(CONFIG_STM32L4_STM32L4X6) || defined(CONFIG_STM32L4_STM32L4XR) + defined(CONFIG_STM32L4_STM32L4X6) #include "stm32l4x6xx_dma.c" +#elif defined(CONFIG_STM32L4_STM32L4XR) +#include "stm32l4xrxx_dma.c" #else # error "Unsupported STM32L4 chip" #endif diff --git a/arch/arm/src/stm32l4/stm32l4_dma.h b/arch/arm/src/stm32l4/stm32l4_dma.h index be5dc34fad8..76069aa4e15 100644 --- a/arch/arm/src/stm32l4/stm32l4_dma.h +++ b/arch/arm/src/stm32l4/stm32l4_dma.h @@ -57,6 +57,7 @@ # include "hardware/stm32l4x6xx_dma.h" #elif defined(CONFIG_STM32L4_STM32L4XR) # include "hardware/stm32l4xrxx_dma.h" +# include "hardware/stm32l4xrxx_dmamux.h" #else # error "Unsupported STM32L4 chip" #endif @@ -87,7 +88,7 @@ typedef FAR void *DMA_HANDLE; * completion of the DMA. * * Input Parameters: - * handle - Refers tot he DMA channel + * handle - Refers to the DMA channel * status - A bit encoded value that provides the completion status. See the * DMASTATUS_* definitions above. * arg - A user-provided value that was provided when stm32l4_dmastart() was @@ -100,11 +101,24 @@ typedef void (*dma_callback_t)(DMA_HANDLE handle, uint8_t status, void *arg); struct stm32l4_dmaregs_s { uint32_t isr; /* Interrupt Status Register; each channel gets 4 bits */ - uint32_t cselr; /* Channel Selection Register; chooses peripheral bound */ uint32_t ccr; /* Channel Configuration Register; determines functionality */ uint32_t cndtr; /* Channel Count Register; determines number of transfers */ uint32_t cpar; /* Channel Peripheral Address Register; determines start */ uint32_t cmar; /* Channel Memory Address Register; determines start */ +#ifndef CONFIG_STM32L4_HAVE_DMAMUX + uint32_t cselr; /* Channel Selection Register; chooses peripheral bound */ +#else + struct + { + uint32_t ccr; /* Channel Configuration Register */ + uint32_t csr; /* Channel Status Register */ + uint32_t rg0cr; /* Request Generator Channel 0 Configuration Register */ + uint32_t rg1cr; /* Request Generator Channel 1 Configuration Register */ + uint32_t rg2cr; /* Request Generator Channel 2 Configuration Register */ + uint32_t rg3cr; /* Request Generator Channel 3 Configuration Register */ + uint32_t rgsr; /* Request Generator Interrupt Status Register */ + } dmamux; +#endif }; #endif @@ -127,6 +141,9 @@ extern "C" * Public Functions ************************************************************************************/ +#if defined(CONFIG_STM32L4_STM32L4X3) || defined(CONFIG_STM32L4_STM32L4X5) || \ + defined(CONFIG_STM32L4_STM32L4X6) + /**************************************************************************** * Name: stm32l4_dmachannel * @@ -166,6 +183,37 @@ extern "C" DMA_HANDLE stm32l4_dmachannel(unsigned int chan); +#elif defined(CONFIG_STM32L4_STM32L4XR) + +/**************************************************************************** + * Name: stm32_dmachannel + * + * Description: + * Allocate a DMA channel. This function gives the caller mutually + * exclusive access to the DMA channel specified by the 'dmamap' argument. + * It is common for both DMA controllers (DMA1 and DMA2). + * + * Input Parameters: + * dmamap - Identifies the stream/channel resource. For the STM32L4+, this + * is a bit-encoded value as provided by the DMAMAP_* definitions + * in hardware/stm32l4xrxx_dmamux.h + * + * Returned Value: + * One success, this function returns a non-NULL, void* DMA channel + * handle. NULL is returned on any failure. This function can fail only + * if no DMA channel is available. + * + * Assumptions: + * - The caller does not hold he DMA channel. + * - The caller can wait for the DMA channel to be freed if it is no + * available. + * + ****************************************************************************/ + +DMA_HANDLE stm32l4_dmachannel(unsigned int dmamap); + +#endif + /**************************************************************************** * Name: stm32l4_dmafree * @@ -196,7 +244,7 @@ void stm32l4_dmafree(DMA_HANDLE handle); ****************************************************************************/ void stm32l4_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, - size_t ntransfers, uint32_t ccr); + size_t ntransfers, uint32_t ccr); /**************************************************************************** * Name: stm32l4_dmastart @@ -211,7 +259,7 @@ void stm32l4_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, ****************************************************************************/ void stm32l4_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, - bool half); + bool half); /**************************************************************************** * Name: stm32l4_dmastop @@ -276,7 +324,7 @@ bool stm32l4_dmacapable(uintptr_t maddr, uint32_t count, uint32_t ccr); #ifdef CONFIG_DEBUG_DMA_INFO void stm32l4_dmasample(DMA_HANDLE handle, struct stm32l4_dmaregs_s *regs); #else -# define stm32l4_dmasample(handle,regs) +# define stm32l4_dmasample(handle,regs) ((void)0) #endif /**************************************************************************** @@ -292,9 +340,9 @@ void stm32l4_dmasample(DMA_HANDLE handle, struct stm32l4_dmaregs_s *regs); #ifdef CONFIG_DEBUG_DMA_INFO void stm32l4_dmadump(DMA_HANDLE handle, const struct stm32l4_dmaregs_s *regs, - const char *msg); + const char *msg); #else -# define stm32l4_dmadump(handle,regs,msg) +# define stm32l4_dmadump(handle,regs,msg) ((void)0) #endif #undef EXTERN diff --git a/arch/arm/src/stm32l4/stm32l4_sdmmc.c b/arch/arm/src/stm32l4/stm32l4_sdmmc.c index b131c3f9b41..a8d59a8d18a 100644 --- a/arch/arm/src/stm32l4/stm32l4_sdmmc.c +++ b/arch/arm/src/stm32l4/stm32l4_sdmmc.c @@ -102,7 +102,7 @@ #ifndef CONFIG_STM32L4_SDMMC_DMA # warning "Large Non-DMA transfer may result in RX overrun failures" #else -# ifndef CONFIG_STM32L4_DMA2 +# if !defined(CONFIG_STM32L4_DMA2) && !defined(CONFIG_STM32L4_DMAMUX) # error "CONFIG_STM32L4_SDMMC_DMA support requires CONFIG_STM32L4_DMA2" # endif # ifndef CONFIG_SDIO_DMA diff --git a/arch/arm/src/stm32l4/stm32l4_serial.c b/arch/arm/src/stm32l4/stm32l4_serial.c index 45dc13ae0e1..cc9a4d12ee9 100644 --- a/arch/arm/src/stm32l4/stm32l4_serial.c +++ b/arch/arm/src/stm32l4/stm32l4_serial.c @@ -92,13 +92,13 @@ */ # if defined(CONFIG_USART2_RXDMA) || defined(CONFIG_USART3_RXDMA) -# ifndef CONFIG_STM32L4_DMA1 +# if !defined(CONFIG_STM32L4_DMA1) && !defined(CONFIG_STM32L4_DMAMUX) # error STM32L4 USART2/3 receive DMA requires CONFIG_STM32L4_DMA1 # endif # endif # if defined(CONFIG_UART4_RXDMA) || defined(CONFIG_UART5_RXDMA) -# ifndef CONFIG_STM32L4_DMA2 +# if !defined(CONFIG_STM32L4_DMA2) && !defined(CONFIG_STM32L4_DMAMUX) # error STM32L4 UART4/5 receive DMA requires CONFIG_STM32L4_DMA2 # endif # endif @@ -124,12 +124,30 @@ # error "USART1 DMA channel not defined (DMAMAP_USART1_RX)" # endif -/* UART2-5 have no alternate channels */ +/* UART2-5 have no alternate channels without DMAMUX */ -# define DMAMAP_USART2_RX DMACHAN_USART2_RX -# define DMAMAP_USART3_RX DMACHAN_USART3_RX -# define DMAMAP_UART4_RX DMACHAN_UART4_RX -# define DMAMAP_UART5_RX DMACHAN_UART5_RX +# ifndef CONFIG_STM32L4_HAVE_DMAMUX +# define DMAMAP_USART2_RX DMACHAN_USART2_RX +# define DMAMAP_USART3_RX DMACHAN_USART3_RX +# define DMAMAP_UART4_RX DMACHAN_UART4_RX +# define DMAMAP_UART5_RX DMACHAN_UART5_RX +# endif + +# if defined(CONFIG_USART2_RXDMA) && !defined(DMAMAP_USART2_RX) +# error "USART2 DMA channel not defined (DMAMAP_USART2_RX)" +# endif + +# if defined(CONFIG_USART3_RXDMA) && !defined(DMAMAP_USART3_RX) +# error "USART3 DMA channel not defined (DMAMAP_USART3_RX)" +# endif + +# if defined(CONFIG_UART4_RXDMA) && !defined(DMAMAP_UART4_RX) +# error "UART4 DMA channel not defined (DMAMAP_UART4_RX)" +# endif + +# if defined(CONFIG_UART5_RXDMA) && !defined(DMAMAP_UART5_RX) +# error "UART5 DMA channel not defined (DMAMAP_UART5_RX)" +# endif /* The DMA buffer size when using RX DMA to emulate a FIFO. * diff --git a/arch/arm/src/stm32l4/stm32l4xrxx_dma.c b/arch/arm/src/stm32l4/stm32l4xrxx_dma.c new file mode 100644 index 00000000000..1554b8eb403 --- /dev/null +++ b/arch/arm/src/stm32l4/stm32l4xrxx_dma.c @@ -0,0 +1,1396 @@ +/**************************************************************************** + * arch/arm/src/stm32l4/stm32l4xrxx_dma.c + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Jussi Kivilinna + * + * Based on STM32H7 DMAMUX/DMA driver: + * Author: Mateusz Szafoni + * + * Based on STM32L4X6XX DMA driver: + * Author: Gregory Nutt + * Author: Sebastien Lorquet + * Author: dev@ziggurat29.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "up_arch.h" + +#include "up_internal.h" +#include "sched/sched.h" +#include "stm32l4_dma.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_STM32L4_DMAMUX +# error "Configuration error, CONFIG_STM32L4_DMAMUX not defined!" +#endif + +#ifndef CONFIG_STM32L4_DMAMUX1 +# error "Configuration error, CONFIG_STM32L4_DMAMUX1 not defined!" +#endif + +#define DMAMUX_NUM 1 +#define DMA_CONTROLLERS 2 + +#ifdef CONFIG_STM32L4_DMA1 +# define DMA1_NCHAN 7 +#else +# define DMA1_NCHAN 0 +#endif +#ifdef CONFIG_STM32L4_DMA2 +# define DMA2_NCHAN 7 +#else +# define DMA2_NCHAN 0 +#endif + +#define DMA1_FIRST (0) +#define DMA1_LAST (DMA1_FIRST+DMA1_NCHAN) +#define DMA2_FIRST (DMA1_LAST) +#define DMA2_LAST (DMA2_FIRST+DMA2_NCHAN) + +/* All available DMA channels */ + +#define DMA_NCHANNELS (DMA1_NCHAN+DMA2_NCHAN) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure described one DMAMUX device */ + +struct stm32l4_dmamux_s +{ + uint8_t id; /* DMAMUX id */ + uint8_t nchan; /* DMAMUX channels */ + uint32_t base; /* DMAMUX base address */ +}; + +typedef FAR const struct stm32l4_dmamux_s *DMA_MUX; + +/* This structure describes one DMA controller */ + +struct stm32l4_dma_s +{ + uint8_t first; /* Offset in stm32l4_dmach_s array */ + uint8_t nchan; /* Number of channels */ + uint8_t dmamux_offset; /* DMAMUX channel offset */ + uint32_t base; /* Base address */ + DMA_MUX dmamux; /* DMAMUX associated with controller */ +}; + +/* This structure describes one DMA channel (DMA1, DMA2) */ + +struct stm32l4_dmach_s +{ + bool used; /* Channel in use */ + uint8_t dmamux_req; /* Configured DMAMUX input request */ + uint8_t ctrl; /* DMA controller */ + uint8_t chan; /* DMA channel channel id */ + uint8_t irq; /* DMA channel IRQ number */ + uint8_t shift; /* IFCR bit shift value */ + uint32_t base; /* DMA register channel base address */ + dma_callback_t callback; /* Callback invoked when the DMA completes */ + void *arg; /* Argument passed to callback function */ +}; + +typedef FAR struct stm32l4_dmach_s *DMA_CHANNEL; + +/* DMA operations */ + +struct stm32l4_dma_ops_s +{ + /* Disable the DMA transfer */ + + CODE void (*dma_disable)(DMA_CHANNEL dmachan); + + /* DMA interrupt */ + + CODE int (*dma_interrupt)(int irq, void *context, FAR void *arg); + + /* Setup the DMA */ + + CODE void (*dma_setup)(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, + size_t ntransfers, uint32_t ccr); + + /* Start the DMA */ + + CODE void (*dma_start)(DMA_HANDLE handle, dma_callback_t callback, + void *arg, bool half); + + /* Read remaining DMA bytes */ + + CODE size_t (*dma_residual)(DMA_HANDLE handle); + + /* Check the DMA configuration */ + + CODE bool (*dma_capable)(uint32_t maddr, uint32_t count, uint32_t ccr); + +#ifdef CONFIG_DEBUG_DMA_INFO + /* Sample the DMA registers */ + + CODE void (*dma_sample)(DMA_HANDLE handle, struct stm32l4_dmaregs_s *regs); + + /* Dump the DMA registers */ + + CODE void (*dma_dump)(DMA_HANDLE handle, + const struct stm32l4_dmaregs_s *regs, const char *msg); +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#if defined(CONFIG_STM32L4_DMA1) || defined(CONFIG_STM32L4_DMA2) +static void stm32l4_dma12_disable(DMA_CHANNEL dmachan); +static int stm32l4_dma12_interrupt(int irq, void *context, FAR void *arg); +static void stm32l4_dma12_setup(DMA_HANDLE handle, uint32_t paddr, + uint32_t maddr, size_t ntransfers, + uint32_t ccr); +static void stm32l4_dma12_start(DMA_HANDLE handle, dma_callback_t callback, + void *arg, bool half); +static size_t stm32l4_dma12_residual(DMA_HANDLE handle); +#ifdef CONFIG_DEBUG_DMA_INFO +static void stm32l4_dma12_sample(DMA_HANDLE handle, + struct stm32l4_dmaregs_s *regs); +static void stm32l4_dma12_dump(DMA_HANDLE handle, + const struct stm32l4_dmaregs_s *regs, + const char *msg); +#endif +#endif + +static uint32_t dmachan_getbase(DMA_CHANNEL dmachan); +static uint32_t dmabase_getreg(DMA_CHANNEL dmachan, uint32_t offset); +static void dmabase_putreg(DMA_CHANNEL dmachan, uint32_t offset, + uint32_t value); +static uint32_t dmachan_getreg(DMA_CHANNEL dmachan, uint32_t offset); +static void dmachan_putreg(DMA_CHANNEL dmachan, uint32_t offset, + uint32_t value); +static void dmamux_putreg(DMA_MUX dmamux, uint32_t offset, uint32_t value); +#ifdef CONFIG_DEBUG_DMA_INFO +static uint32_t dmamux_getreg(DMA_MUX dmamux, uint32_t offset); +static void stm32l4_dmamux_sample(DMA_MUX dmamux, uint8_t chan, + struct stm32l4_dmaregs_s *regs); +static void stm32l4_dmamux_dump(DMA_MUX dmamux, uint8_t channel, + const struct stm32l4_dmaregs_s *regs); +#endif +static DMA_CHANNEL stm32l4_dma_channel_get(uint8_t channel, uint8_t controller); +static void stm32l4_gdma_limits_get(uint8_t controller, FAR uint8_t *first, + FAR uint8_t *last); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Operations specific to DMA controller */ + +static const struct stm32l4_dma_ops_s g_dma_ops[DMA_CONTROLLERS] = +{ +#ifdef CONFIG_STM32L4_DMA1 + /* 0 - DMA1 */ + + { + .dma_disable = stm32l4_dma12_disable, + .dma_interrupt = stm32l4_dma12_interrupt, + .dma_setup = stm32l4_dma12_setup, + .dma_start = stm32l4_dma12_start, + .dma_residual = stm32l4_dma12_residual, +#ifdef CONFIG_DEBUG_DMA_INFO + .dma_sample = stm32l4_dma12_sample, + .dma_dump = stm32l4_dma12_dump, +#endif + }, +#else + { NULL }, +#endif + +#ifdef CONFIG_STM32L4_DMA2 + /* 1 - DMA2 */ + + { + .dma_disable = stm32l4_dma12_disable, + .dma_interrupt = stm32l4_dma12_interrupt, + .dma_setup = stm32l4_dma12_setup, + .dma_start = stm32l4_dma12_start, + .dma_residual = stm32l4_dma12_residual, +#ifdef CONFIG_DEBUG_DMA_INFO + .dma_sample = stm32l4_dma12_sample, + .dma_dump = stm32l4_dma12_dump, +#endif + } +#else + { NULL } +#endif +}; + +/* This array describes the state of DMAMUX controller */ + +static const struct stm32l4_dmamux_s g_dmamux[DMAMUX_NUM] = +{ + { + .id = 1, + .nchan = 14, /* 0-6 - DMA1, 7-13 - DMA2 */ + .base = STM32L4_DMAMUX1_BASE + } +}; + +/* This array describes the state of each controller */ + +static const struct stm32l4_dma_s g_dma[DMA_NCHANNELS] = +{ + /* 0 - DMA1 */ + + { + .base = STM32L4_DMA1_BASE, + .first = DMA1_FIRST, + .nchan = DMA1_NCHAN, + .dmamux = &g_dmamux[DMAMUX1], /* DMAMUX1 channels 0-6 */ + .dmamux_offset = 0 + }, + + /* 1 - DMA2 */ + + { + .base = STM32L4_DMA2_BASE, + .first = DMA2_FIRST, + .nchan = DMA2_NCHAN, + .dmamux = &g_dmamux[DMAMUX1], /* DMAMUX1 channels 7-13 */ + .dmamux_offset = 7 + } +}; + +/* This array describes the state of each DMA channel. */ + +static struct stm32l4_dmach_s g_dmach[DMA_NCHANNELS] = +{ +#ifdef CONFIG_STM32L4_DMA1 + /* DMA1 */ + + { + .ctrl = DMA1, + .chan = 0, + .irq = STM32L4_IRQ_DMA1CH1, + .shift = DMA_CHAN_SHIFT(0), + .base = STM32L4_DMA1_BASE + STM32L4_DMACHAN_OFFSET(0), + }, + { + .ctrl = DMA1, + .chan = 1, + .irq = STM32L4_IRQ_DMA1CH2, + .shift = DMA_CHAN_SHIFT(1), + .base = STM32L4_DMA1_BASE + STM32L4_DMACHAN_OFFSET(1), + }, + { + .ctrl = DMA1, + .chan = 2, + .irq = STM32L4_IRQ_DMA1CH3, + .shift = DMA_CHAN_SHIFT(2), + .base = STM32L4_DMA1_BASE + STM32L4_DMACHAN_OFFSET(2), + }, + { + .ctrl = DMA1, + .chan = 3, + .irq = STM32L4_IRQ_DMA1CH4, + .shift = DMA_CHAN_SHIFT(3), + .base = STM32L4_DMA1_BASE + STM32L4_DMACHAN_OFFSET(3), + }, + { + .ctrl = DMA1, + .chan = 4, + .irq = STM32L4_IRQ_DMA1CH5, + .shift = DMA_CHAN_SHIFT(4), + .base = STM32L4_DMA1_BASE + STM32L4_DMACHAN_OFFSET(4), + }, + { + .ctrl = DMA1, + .chan = 5, + .irq = STM32L4_IRQ_DMA1CH6, + .shift = DMA_CHAN_SHIFT(5), + .base = STM32L4_DMA1_BASE + STM32L4_DMACHAN_OFFSET(5), + }, + { + .ctrl = DMA1, + .chan = 6, + .irq = STM32L4_IRQ_DMA1CH7, + .shift = DMA_CHAN_SHIFT(6), + .base = STM32L4_DMA1_BASE + STM32L4_DMACHAN_OFFSET(6), + }, +#endif + +#ifdef CONFIG_STM32L4_DMA2 + /* DMA2 */ + + + { + .ctrl = DMA2, + .chan = 0, + .irq = STM32L4_IRQ_DMA2CH1, + .shift = DMA_CHAN_SHIFT(0), + .base = STM32L4_DMA2_BASE + STM32L4_DMACHAN_OFFSET(0), + }, + { + .ctrl = DMA2, + .chan = 1, + .irq = STM32L4_IRQ_DMA2CH2, + .shift = DMA_CHAN_SHIFT(1), + .base = STM32L4_DMA2_BASE + STM32L4_DMACHAN_OFFSET(1), + }, + { + .ctrl = DMA2, + .chan = 2, + .irq = STM32L4_IRQ_DMA2CH3, + .shift = DMA_CHAN_SHIFT(2), + .base = STM32L4_DMA2_BASE + STM32L4_DMACHAN_OFFSET(2), + }, + { + .ctrl = DMA2, + .chan = 3, + .irq = STM32L4_IRQ_DMA2CH4, + .shift = DMA_CHAN_SHIFT(3), + .base = STM32L4_DMA2_BASE + STM32L4_DMACHAN_OFFSET(3), + }, + { + .ctrl = DMA2, + .chan = 4, + .irq = STM32L4_IRQ_DMA2CH5, + .shift = DMA_CHAN_SHIFT(4), + .base = STM32L4_DMA2_BASE + STM32L4_DMACHAN_OFFSET(4), + }, + { + .ctrl = DMA2, + .chan = 5, + .irq = STM32L4_IRQ_DMA2CH6, + .shift = DMA_CHAN_SHIFT(5), + .base = STM32L4_DMA2_BASE + STM32L4_DMACHAN_OFFSET(5), + }, + { + .ctrl = DMA2, + .chan = 6, + .irq = STM32L4_IRQ_DMA2CH7, + .shift = DMA_CHAN_SHIFT(6), + .base = STM32L4_DMA2_BASE + STM32L4_DMACHAN_OFFSET(6), + }, +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * DMA register access functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dmachan_getbase + * + * Description: + * Get base DMA address for dmachan + * + ****************************************************************************/ + +static uint32_t dmachan_getbase(DMA_CHANNEL dmachan) +{ + uint8_t controller = dmachan->ctrl; + + return g_dma[controller].base; +} + +/********************************************************************** + * Name: dmabase_getreg + * + * Description: + * Get non-channel register from DMA controller + * + ****************************************************************************/ + +static uint32_t dmabase_getreg(DMA_CHANNEL dmachan, uint32_t offset) +{ + uint32_t dmabase = dmachan_getbase(dmachan); + + return getreg32(dmabase + offset); +} + +/**************************************************************************** + * Name: dmabase_putreg + * + * Description: + * Write to non-channel register in DMA controller + * + ****************************************************************************/ + +static void dmabase_putreg(DMA_CHANNEL dmachan, uint32_t offset, uint32_t value) +{ + uint32_t dmabase = dmachan_getbase(dmachan); + + putreg32(value, dmabase + offset); +} + +/**************************************************************************** + * Name: dmachan_getreg + * + * Description: + * Get channel register. + * + ****************************************************************************/ + +static uint32_t dmachan_getreg(DMA_CHANNEL dmachan, uint32_t offset) +{ + return getreg32(dmachan->base + offset); +} + +/**************************************************************************** + * Name: dmachan_putreg + * + * Description: + * Write to channel register. + * + ****************************************************************************/ + +static void dmachan_putreg(DMA_CHANNEL dmachan, uint32_t offset, uint32_t value) +{ + putreg32(value, dmachan->base + offset); +} + +/**************************************************************************** + * Name: dmamux_getreg + * + * Description: + * Write to DMAMUX + * + ****************************************************************************/ + +static void dmamux_putreg(DMA_MUX dmamux, uint32_t offset, uint32_t value) +{ + putreg32(value, dmamux->base + offset); +} + +/**************************************************************************** + * Name: dmamux_getreg + * + * Description: + * Get DMAMUX register. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA_INFO +static uint32_t dmamux_getreg(DMA_MUX dmamux, uint32_t offset) +{ + return getreg32(dmamux->base + offset); +} +#endif + +/**************************************************************************** + * Name: stm32l4_dma_channel_get + * + * Description: + * Get the g_dmach table entry associated with a given DMA controller + * and channel number. + * + ****************************************************************************/ + +static DMA_CHANNEL stm32l4_dma_channel_get(uint8_t channel, uint8_t controller) +{ + uint8_t first = 0; + uint8_t nchan = 0; + + /* Get limits for g_dma array */ + + stm32l4_gdma_limits_get(controller, &first, &nchan); + + DEBUGASSERT(channel <= nchan); + + return &g_dmach[first + channel]; +} + +/**************************************************************************** + * Name: stm32l4_gdma_limits_get + * + * Description: + * Get g_dma array limits for a given DMA controller. + * + ****************************************************************************/ + +static void stm32l4_gdma_limits_get(uint8_t controller, FAR uint8_t *first, + FAR uint8_t *nchan) +{ + DEBUGASSERT(first != NULL); + DEBUGASSERT(nchan != NULL); + + DEBUGASSERT(controller >= DMA1 && controller <= DMA2); + + *first = g_dma[controller].first; + *nchan = g_dma[controller].nchan; +} + +/**************************************************************************** + * DMA controller functions + ****************************************************************************/ + +#if defined(CONFIG_STM32L4_DMA1) || defined(CONFIG_STM32L4_DMA2) + +/**************************************************************************** + * Name: stm32l4_dma12_disable + * + * Description: + * Disable DMA channel (DMA1/DMA2) + * + ****************************************************************************/ + +static void stm32l4_dma12_disable(DMA_CHANNEL dmachan) +{ + uint32_t regval; + + DEBUGASSERT(dmachan->ctrl == DMA1 || dmachan->ctrl == DMA2); + + /* Disable all interrupts at the DMA controller */ + + regval = dmachan_getreg(dmachan, STM32L4_DMACHAN_CCR_OFFSET); + regval &= ~DMA_CCR_ALLINTS; + + /* Disable the DMA channel */ + + regval &= ~DMA_CCR_EN; + dmachan_putreg(dmachan, STM32L4_DMACHAN_CCR_OFFSET, regval); + + /* Clear pending channel interrupts */ + + dmabase_putreg(dmachan, STM32L4_DMA_IFCR_OFFSET, + DMA_ISR_CHAN_MASK(dmachan->chan)); +} + +/**************************************************************************** + * Name: stm32l4_dma12_interrupt + * + * Description: + * DMA channel interrupt handler + * + ****************************************************************************/ + +static int stm32l4_dma12_interrupt(int irq, void *context, FAR void *arg) +{ + DMA_CHANNEL dmachan; + uint32_t isr; + uint8_t channel; + uint8_t controller; + + /* Get the channel and the controller that generated the interrupt */ + + if (0) {} +#ifdef CONFIG_STM32L4_DMA1 + else if (irq >= STM32L4_IRQ_DMA1CH1 && irq <= STM32L4_IRQ_DMA1CH7) + { + channel = irq - STM32L4_IRQ_DMA1CH1; + controller = DMA1; + } +#endif +#ifdef CONFIG_STM32L4_DMA2 + else if (irq >= STM32L4_IRQ_DMA2CH1 && irq <= STM32L4_IRQ_DMA2CH5) + { + channel = irq - STM32L4_IRQ_DMA2CH1; + controller = DMA2; + } + else if (irq >= STM32L4_IRQ_DMA2CH6 && irq <= STM32L4_IRQ_DMA2CH7) + { + channel = irq - STM32L4_IRQ_DMA2CH6 + (6 - 1); + controller = DMA2; + } +#endif + else + { + DEBUGPANIC(); + return OK; + } + + /* Get the channel structure from the stream and controller numbers */ + + dmachan = stm32l4_dma_channel_get(channel, controller); + + /* Get the interrupt status (for this channel only) */ + + isr = dmabase_getreg(dmachan, STM32L4_DMA_ISR_OFFSET) & + DMA_ISR_CHAN_MASK(dmachan->chan); + + /* Invoke the callback */ + + if (dmachan->callback) + { + dmachan->callback(dmachan, isr >> DMA_ISR_CHAN_SHIFT(dmachan->chan), + dmachan->arg); + } + + /* Clear the interrupts we are handling */ + + dmabase_putreg(dmachan, STM32L4_DMA_IFCR_OFFSET, isr); + + return OK; +} + +/**************************************************************************** + * Name: stm32l4_dma12_setup + * + * Description: + * Configure DMA before using + * + ****************************************************************************/ + +static void stm32l4_dma12_setup(DMA_HANDLE handle, uint32_t paddr, + uint32_t maddr, size_t ntransfers, uint32_t ccr) +{ + DMA_CHANNEL dmachan = (DMA_CHANNEL)handle; + uint32_t regval; + + DEBUGASSERT(handle != NULL); + DEBUGASSERT(ntransfers < 65536); + + DEBUGASSERT(dmachan->ctrl == DMA1 || dmachan->ctrl == DMA2); + + dmainfo("paddr: %08x maddr: %08x ntransfers: %d ccr: %08x\n", + paddr, maddr, ntransfers, ccr); + +#ifdef CONFIG_STM32L4_DMACAPABLE + DEBUGASSERT(g_dma_ops[dmachan->ctrl].dma_capable(maddr, ntransfers, ccr)); +#endif + + /* Then DMA_CNDTRx register can only be modified if the DMA channel is + * disabled. + */ + + regval = dmachan_getreg(dmachan, STM32L4_DMACHAN_CCR_OFFSET); + regval &= ~(DMA_CCR_EN); + dmachan_putreg(dmachan, STM32L4_DMACHAN_CCR_OFFSET, regval); + + /* Set the peripheral register address in the DMA_CPARx register. The data + * will be moved from/to this address to/from the memory after the + * peripheral event. + */ + + dmachan_putreg(dmachan, STM32L4_DMACHAN_CPAR_OFFSET, paddr); + + /* Set the memory address in the DMA_CMARx register. The data will be + * written to or read from this memory after the peripheral event. + */ + + dmachan_putreg(dmachan, STM32L4_DMACHAN_CMAR_OFFSET, maddr); + + /* Configure the total number of data to be transferred in the DMA_CNDTRx + * register. After each peripheral event, this value will be decremented. + */ + + dmachan_putreg(dmachan, STM32L4_DMACHAN_CNDTR_OFFSET, ntransfers); + + /* Configure the channel priority using the PL[1:0] bits in the DMA_CCRx + * register. Configure data transfer direction, circular mode, peripheral & + * memory incremented mode, peripheral & memory data size, and interrupt + * after half and/or full transfer in the DMA_CCRx register. + */ + + regval = dmachan_getreg(dmachan, STM32L4_DMACHAN_CCR_OFFSET); + regval &= ~(DMA_CCR_MEM2MEM | DMA_CCR_PL_MASK | DMA_CCR_MSIZE_MASK | + DMA_CCR_PSIZE_MASK | DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | + DMA_CCR_DIR); + ccr &= (DMA_CCR_MEM2MEM | DMA_CCR_PL_MASK | DMA_CCR_MSIZE_MASK | + DMA_CCR_PSIZE_MASK | DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | + DMA_CCR_DIR); + regval |= ccr; + dmachan_putreg(dmachan, STM32L4_DMACHAN_CCR_OFFSET, regval); +} + +/**************************************************************************** + * Name: stm32l4_dma12_start + * + * Description: + * Start the standard DMA transfer + ****************************************************************************/ + +static void stm32l4_dma12_start(DMA_HANDLE handle, dma_callback_t callback, + void *arg, bool half) +{ + DMA_CHANNEL dmachan = (DMA_CHANNEL)handle; + uint32_t ccr; + + DEBUGASSERT(dmachan->ctrl == DMA1 || dmachan->ctrl == DMA2); + + /* Save the callback info. This will be invoked when the DMA completes */ + + dmachan->callback = callback; + dmachan->arg = arg; + + /* Activate the channel by setting the ENABLE bit in the DMA_CCRx register. + * As soon as the channel is enabled, it can serve any DMA request from the + * peripheral connected on the channel. + */ + + ccr = dmachan_getreg(dmachan, STM32L4_DMACHAN_CCR_OFFSET); + ccr |= DMA_CCR_EN; + + /* In normal mode, interrupt at either half or full completion. In circular + * mode, always interrupt on buffer wrap, and optionally interrupt at the + * halfway point. + */ + + if ((ccr & DMA_CCR_CIRC) == 0) + { + /* Once half of the bytes are transferred, the half-transfer flag (HTIF) + * is set and an interrupt is generated if the Half-Transfer Interrupt + * Enable bit (HTIE) is set. At the end of the transfer, the Transfer + * Complete Flag (TCIF) is set and an interrupt is generated if the + * Transfer Complete Interrupt Enable bit (TCIE) is set. + */ + + ccr |= (half ? (DMA_CCR_HTIE | DMA_CCR_TEIE) : + (DMA_CCR_TCIE | DMA_CCR_TEIE)); + } + else + { + /* In nonstop mode, when the transfer completes it immediately resets + * and starts again. The transfer-complete interrupt is thus always + * enabled, and the half-complete interrupt can be used in circular + * mode to determine when the buffer is half-full, or in double-buffered + * mode to determine when one of the two buffers is full. + */ + + ccr |= (half ? DMA_CCR_HTIE : 0) | DMA_CCR_TCIE | DMA_CCR_TEIE; + } + + dmachan_putreg(dmachan, STM32L4_DMACHAN_CCR_OFFSET, ccr); +} + +/**************************************************************************** + * Name: stm32l4_dma12_residual + ****************************************************************************/ + +static size_t stm32l4_dma12_residual(DMA_HANDLE handle) +{ + DMA_CHANNEL dmachan = (DMA_CHANNEL)handle; + + DEBUGASSERT(dmachan->ctrl == DMA1 || dmachan->ctrl == DMA2); + + return dmachan_getreg(dmachan, STM32L4_DMACHAN_CNDTR_OFFSET); +} + +/**************************************************************************** + * Name: stm32l4_dma12_sample + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA_INFO +void stm32l4_dma12_sample(DMA_HANDLE handle, struct stm32l4_dmaregs_s *regs) +{ + DMA_CHANNEL dmachan = (DMA_CHANNEL)handle; + irqstate_t flags; + + flags = enter_critical_section(); + + regs->isr = dmabase_getreg(dmachan, STM32L4_DMA_ISR_OFFSET); + regs->ccr = dmachan_getreg(dmachan, STM32L4_DMACHAN_CCR_OFFSET); + regs->cndtr = dmachan_getreg(dmachan, STM32L4_DMACHAN_CNDTR_OFFSET); + regs->cpar = dmachan_getreg(dmachan, STM32L4_DMACHAN_CPAR_OFFSET); + regs->cmar = dmachan_getreg(dmachan, STM32L4_DMACHAN_CMAR_OFFSET); + + stm32l4_dmamux_sample(g_dma[dmachan->ctrl].dmamux, + dmachan->chan + g_dma[dmachan->ctrl].dmamux_offset, + regs); + + leave_critical_section(flags); +} +#endif + +/**************************************************************************** + * Name: stm32l4_dma12_dump + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA_INFO +static void stm32l4_dma12_dump(DMA_HANDLE handle, + const struct stm32l4_dmaregs_s *regs, + const char *msg) +{ + DMA_CHANNEL dmachan = (DMA_CHANNEL)handle; + + DEBUGASSERT(dmachan->ctrl == DMA1 || dmachan->ctrl == DMA2); + + uint32_t dmabase = dmachan_getbase(dmachan); + + dmainfo("DMA%d Registers: %s\n", dmachan->ctrl + 1, msg); + dmainfo(" ISR[%08x]: %08x\n", dmabase + STM32L4_DMA_ISR_OFFSET, + regs->isr); + dmainfo(" CCR[%08x]: %08x\n", dmachan->base + STM32L4_DMACHAN_CCR_OFFSET, + regs->ccr); + dmainfo(" CNDTR[%08x]: %08x\n", dmachan->base + STM32L4_DMACHAN_CNDTR_OFFSET, + regs->cndtr); + dmainfo(" CPAR[%08x]: %08x\n", dmachan->base + STM32L4_DMACHAN_CPAR_OFFSET, + regs->cpar); + dmainfo(" CMAR[%08x]: %08x\n", dmachan->base + STM32L4_DMACHAN_CMAR_OFFSET, + regs->cmar); + + stm32l4_dmamux_dump(g_dma[dmachan->ctrl].dmamux, + dmachan->chan + g_dma[dmachan->ctrl].dmamux_offset, + regs); +} +#endif + +#endif /* CONFIG_STM32L4_DMA1 || CONFIG_STM32L4_DMA2 */ + +/**************************************************************************** + * Name: stm32l4_dmamux_sample + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA_INFO +static void stm32l4_dmamux_sample(DMA_MUX dmamux, uint8_t chan, + struct stm32l4_dmaregs_s *regs) +{ + regs->dmamux.ccr = dmamux_getreg(dmamux, STM32L4_DMAMUX_CXCR_OFFSET(chan)); + regs->dmamux.csr = dmamux_getreg(dmamux, STM32L4_DMAMUX_CSR_OFFSET); + regs->dmamux.rg0cr = dmamux_getreg(dmamux, STM32L4_DMAMUX_RG0CR_OFFSET); + regs->dmamux.rg1cr = dmamux_getreg(dmamux, STM32L4_DMAMUX_RG1CR_OFFSET); + regs->dmamux.rg2cr = dmamux_getreg(dmamux, STM32L4_DMAMUX_RG2CR_OFFSET); + regs->dmamux.rg3cr = dmamux_getreg(dmamux, STM32L4_DMAMUX_RG3CR_OFFSET); + regs->dmamux.rgsr = dmamux_getreg(dmamux, STM32L4_DMAMUX_RGSR_OFFSET); +} +#endif + +/**************************************************************************** + * Name: stm32l4_dmamux_dump + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA_INFO +static void stm32l4_dmamux_dump(DMA_MUX dmamux, uint8_t channel, + const struct stm32l4_dmaregs_s *regs) +{ + dmainfo("DMAMUX%d CH=%d\n", dmamux->id, channel); + dmainfo(" CCR[%08x]: %08x\n", + dmamux->base + STM32L4_DMAMUX_CXCR_OFFSET(channel), regs->dmamux.ccr); + dmainfo(" CSR[%08x]: %08x\n", + dmamux->base + STM32L4_DMAMUX_CSR_OFFSET, regs->dmamux.csr); + dmainfo(" RG0CR[%08x]: %08x\n", + dmamux->base + STM32L4_DMAMUX_RG0CR_OFFSET, regs->dmamux.rg0cr); + dmainfo(" RG1CR[%08x]: %08x\n", + dmamux->base + STM32L4_DMAMUX_RG1CR_OFFSET, regs->dmamux.rg1cr); + dmainfo(" RG2CR[%08x]: %08x\n", + dmamux->base + STM32L4_DMAMUX_RG2CR_OFFSET, regs->dmamux.rg2cr); + dmainfo(" RG3CR[%08x]: %08x\n", + dmamux->base + STM32L4_DMAMUX_RG3CR_OFFSET, regs->dmamux.rg3cr); + dmainfo(" RGSR[%08x]: %08x\n", + dmamux->base + STM32L4_DMAMUX_RGSR_OFFSET, regs->dmamux.rgsr); +}; +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_dma_initialize + * + * Description: + * Initialize the DMA subsystem (DMA1, DMA2) + * + * Returned Value: + * None + * + ****************************************************************************/ + +void weak_function up_dma_initialize(void) +{ + DMA_CHANNEL dmachan; + uint8_t controller; + int channel; + + dmainfo("Initialize DMA\n"); + + /* Initialize DMA channels */ + + for (channel = 0; channel < DMA_NCHANNELS; channel++) + { + dmachan = &g_dmach[channel]; + + /* Initialize flag */ + + dmachan->used = false; + + /* Get DMA controller associated with channel */ + + controller = dmachan->ctrl; + + DEBUGASSERT(controller >= DMA1 && controller <= DMA2); + + /* Attach standard DMA interrupt vectors */ + + (void)irq_attach(dmachan->irq, g_dma_ops[controller].dma_interrupt, + dmachan); + + /* Disable the DMA channel */ + + g_dma_ops[controller].dma_disable(dmachan); + + /* Enable the IRQ at the NVIC (still disabled at the DMA controller) */ + + up_enable_irq(dmachan->irq); + } +} + +/**************************************************************************** + * Name: stm32l4_dmachannel + * + * Description: + * Allocate a DMA channel. This function gives the caller mutually + * exclusive access to the DMA channel specified by the 'dmamap' argument. + * It is common for both DMA controllers (DMA1 and DMA2). + * + * Input Parameters: + * dmamap - Identifies the stream/channel resource. For the STM32L4+, this + * is a bit-encoded value as provided by the DMAMAP_* definitions + * in hardware/stm32l4xrxx_dmamux.h + * + * Returned Value: + * One success, this function returns a non-NULL, void* DMA channel + * handle. NULL is returned on any failure. This function can fail only + * if no DMA channel is available. + * + * Assumptions: + * - The caller does not hold he DMA channel. + * - The caller can wait for the DMA channel to be freed if it is no + * available. + * + ****************************************************************************/ + +DMA_HANDLE stm32l4_dmachannel(unsigned int dmamap) +{ + DMA_CHANNEL dmachan; + uint8_t dmamux_req; + irqstate_t flags; + uint8_t controller; + uint8_t first = 0; + uint8_t nchan = 0; + int item = -1; + int i; + + /* Get DMA controller from encoded DMAMAP value */ + + controller = DMAMAP_CONTROLLER(dmamap); + DEBUGASSERT(controller >= DMA1 && controller <= DMA2); + + /* Get DMAMUX channel from encoded DMAMAP value */ + + dmamux_req = DMAMAP_REQUEST(dmamap); + + /* Get g_dma array limits for given controller */ + + stm32l4_gdma_limits_get(controller, &first, &nchan); + + /* Find available channel for given controller */ + + flags = enter_critical_section(); + for (i = first; i < first + nchan; i += 1) + { + if (g_dmach[i].used == false) + { + item = i; + g_dmach[i].used = true; + g_dmach[i].dmamux_req = dmamux_req; + break; + } + } + leave_critical_section(flags); + + dmainfo("ctrl=%d item=%d\n", controller, item); + + if (item == -1) + { + dmainfo("No available DMA chan for CTRL=%d\n", + controller); + + /* No available channel */ + + return NULL; + } + + /* Assign DMA item */ + + dmachan = &g_dmach[item]; + + dmainfo("Get g_dmach[%d] CTRL=%d CH=%d\n", i, controller, dmachan->chan); + + /* Be sure that we have proper DMA controller */ + + DEBUGASSERT(dmachan->ctrl == controller); + + return (DMA_HANDLE)dmachan; +} + +/**************************************************************************** + * Name: stm32l4_dmafree + * + * Description: + * Release a DMA channel and unmap DMAMUX if required. + * + * NOTE: The 'handle' used in this argument must NEVER be used again + * until stm32l4_dmachannel() is called again to re-gain access to the + * channel. + * + * Returned Value: + * None + * + * Assumptions: + * - The caller holds the DMA channel. + * - There is no DMA in progress + * + ****************************************************************************/ + +void stm32l4_dmafree(DMA_HANDLE handle) +{ + DMA_CHANNEL dmachan = (DMA_CHANNEL)handle; + uint8_t controller; + irqstate_t flags; + + DEBUGASSERT(handle != NULL); + + /* Get DMA controller */ + + controller = dmachan->ctrl; + DEBUGASSERT(controller >= DMA1 && controller <= DMA2); + + dmainfo("Free g_dmach[%d] CTRL=%d CH=%d\n", dmachan - g_dmach, controller, + dmachan->chan); + + /* Release the channel */ + + flags = enter_critical_section(); + dmachan->used = false; + dmachan->dmamux_req = 0; + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: stm32l4_dmasetup + * + * Description: + * Configure DMA before using + * + ****************************************************************************/ + +void stm32l4_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, + size_t ntransfers, uint32_t ccr) +{ + DMA_CHANNEL dmachan = (DMA_CHANNEL)handle; + uint8_t controller; + + DEBUGASSERT(handle != NULL); + + /* Get DMA controller */ + + controller = dmachan->ctrl; + DEBUGASSERT(controller >= DMA1 && controller <= DMA2); + + g_dma_ops[controller].dma_setup(handle, paddr, maddr, ntransfers, ccr); +} + +/**************************************************************************** + * Name: stm32l4_dmastart + * + * Description: + * Start the DMA transfer + * + * Assumptions: + * - DMA handle allocated by stm32l4_dmachannel() + * - No DMA in progress + * + ****************************************************************************/ + +void stm32l4_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, + bool half) +{ + DMA_CHANNEL dmachan = (DMA_CHANNEL)handle; + DMA_MUX dmamux; + uint32_t regval; + uint8_t dmamux_chan; + uint8_t controller; + + DEBUGASSERT(handle != NULL); + + /* Get DMA controller */ + + controller = dmachan->ctrl; + DEBUGASSERT(controller >= DMA1 && controller <= DMA2); + + /* Recommended channel configure procedure in reference manual: + * 1. Set and configure the DMA channel y, except enabling the channel y. + * 2. Set and configure the related DMAMUX y channel. + * 3. Last, activate the DMA channel y. + */ + + /* Get DMAMUX associated with DMA controller */ + + dmamux = g_dma[controller].dmamux; + dmamux_chan = dmachan->chan + g_dma[controller].dmamux_offset; + + /* DMAMUX Set DMA channel source */ + + regval = dmachan->dmamux_req << DMAMUX_CCR_DMAREQID_SHIFT; + dmamux_putreg(dmamux, STM32L4_DMAMUX_CXCR_OFFSET(dmamux_chan), regval); + + /* Enable DMA channel */ + + g_dma_ops[controller].dma_start(handle, callback, arg, half); +} + +/**************************************************************************** + * Name: stm32l4_dmastop + * + * Description: + * Cancel the DMA. After stm32l4_dmastop() is called, the DMA channel is + * reset and stm32l4_dmasetup() must be called before stm32l4_dmastart() can + * be called again + * + * Assumptions: + * - DMA handle allocated by stm32l4_dmachannel() + * + ****************************************************************************/ + +void stm32l4_dmastop(DMA_HANDLE handle) +{ + DMA_CHANNEL dmachan = (DMA_CHANNEL)handle; + DMA_MUX dmamux; + uint8_t dmamux_chan; + uint8_t controller; + + DEBUGASSERT(handle != NULL); + + /* Get DMA controller */ + + controller = dmachan->ctrl; + DEBUGASSERT(controller >= DMA1 && controller <= DMA2); + + /* Get DMAMUX associated with DMA controller */ + + dmamux = g_dma[controller].dmamux; + dmamux_chan = dmachan->chan + g_dma[controller].dmamux_offset; + + /* Disable DMA channel */ + + g_dma_ops[controller].dma_disable(dmachan); + + /* DMAMUX Clear DMA channel source */ + + dmamux_putreg(dmamux, STM32L4_DMAMUX_CXCR_OFFSET(dmamux_chan), 0); +} + +/**************************************************************************** + * Name: stm32l4_dmaresidual + * + * Description: + * Read the DMA bytes-remaining register. + * + * Assumptions: + * - DMA handle allocated by stm32l4_dmachannel() + * + ****************************************************************************/ + +size_t stm32l4_dmaresidual(DMA_HANDLE handle) +{ + DMA_CHANNEL dmachan = (DMA_CHANNEL)handle; + uint8_t controller; + + DEBUGASSERT(handle != NULL); + + /* Get DMA controller */ + + controller = dmachan->ctrl; + DEBUGASSERT(controller >= DMA1 && controller <= DMA2); + + return g_dma_ops[controller].dma_residual(handle); +} + +/**************************************************************************** + * Name: stm32l4_dmacapable + * + * Description: + * Check if the DMA controller can transfer data to/from given memory + * address. This depends on the internal connections in the ARM bus matrix + * of the processor. Note that this only applies to memory addresses, it + * will return false for any peripheral address. + * + * Input Parameters: + * cfg - DMA transfer configuration + * + * Returned Value: + * True, if transfer is possible. + * + ****************************************************************************/ + +#ifdef CONFIG_STM32L4_DMACAPABLE +bool stm32l4_dmacapable(uint32_t maddr, uint32_t count, uint32_t ccr) +{ + unsigned int msize_shift; + uint32_t transfer_size; + uint32_t mend; + + /* Verify that the address conforms to the memory transfer size. + * Transfers to/from memory performed by the DMA controller are + * required to be aligned to their size. + * + * Datasheet 3.13 claims + * "Access to Flash, SRAM, APB and AHB peripherals as source + * and destination" + */ + + switch (ccr & DMA_CCR_MSIZE_MASK) + { + case DMA_CCR_MSIZE_8BITS: + msize_shift = 0; + break; + + case DMA_CCR_MSIZE_16BITS: + msize_shift = 1; + break; + + case DMA_CCR_MSIZE_32BITS: + msize_shift = 2; + break; + + default: + return false; + } + + transfer_size = 1 << msize_shift; + + if ((maddr & (transfer_size - 1)) != 0) + { + return false; + } + + /* Verify that the transfer is to a memory region that supports DMA. */ + + mend = maddr + (count << msize_shift) - 1; + + if ((maddr & STM32L4_REGION_MASK) != (mend & STM32L4_REGION_MASK)) + { + return false; + } + + switch (maddr & STM32L4_REGION_MASK) + { + case STM32L4_PERIPH_BASE: + case STM32L4_FSMC_BASE: + case STM32L4_FSMC_BANK1: + case STM32L4_FSMC_BANK2: + case STM32L4_FSMC_BANK3: + case STM32L4_QSPI_BANK: + case STM32L4_SRAM_BASE: + case STM32L4_SRAM2_BASE: + case STM32L4_SRAM3_BASE: + case STM32L4_CODE_BASE: + /* All RAM and flash is supported */ + + return true; + + default: + /* Everything else is unsupported by DMA */ + + return false; + } +} +#endif + +/**************************************************************************** + * Name: stm32l4_dmasample + * + * Description: + * Sample DMA register contents + * + * Assumptions: + * - DMA handle allocated by stm32l4_dmachannel() + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA_INFO +void stm32l4_dmasample(DMA_HANDLE handle, struct stm32l4_dmaregs_s *regs) +{ + DMA_CHANNEL dmachan = (DMA_CHANNEL)handle; + uint8_t controller; + + DEBUGASSERT(handle != NULL); + + /* Get DMA controller */ + + controller = dmachan->ctrl; + DEBUGASSERT(controller >= DMA1 && controller <= DMA2); + + g_dma_ops[controller].dma_sample(handle, regs); +} +#endif + +/**************************************************************************** + * Name: stm32l4_dmadump + * + * Description: + * Dump previously sampled DMA register contents + * + * Assumptions: + * - DMA handle allocated by stm32l4_dmachannel() + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA_INFO +void stm32l4_dmadump(DMA_HANDLE handle, const struct stm32l4_dmaregs_s *regs, + const char *msg) +{ + DMA_CHANNEL dmachan = (DMA_CHANNEL)handle; + uint8_t controller; + + DEBUGASSERT(handle != NULL); + + /* Get DMA controller */ + + controller = dmachan->ctrl; + DEBUGASSERT(controller >= DMA1 && controller <= DMA2); + + dmainfo("DMA %d CH%d Registers: %s\n", dmachan->ctrl, dmachan->ctrl, msg); + + g_dma_ops[controller].dma_dump(handle, regs, msg); +} +#endif diff --git a/arch/arm/src/stm32l4/stm32l4xrxx_rcc.c b/arch/arm/src/stm32l4/stm32l4xrxx_rcc.c index 60f4126d2fa..7d36d12f753 100644 --- a/arch/arm/src/stm32l4/stm32l4xrxx_rcc.c +++ b/arch/arm/src/stm32l4/stm32l4xrxx_rcc.c @@ -144,6 +144,12 @@ static inline void rcc_enableahb1(void) regval = getreg32(STM32L4_RCC_AHB1ENR); +#ifdef CONFIG_STM32L4_DMAMUX1 + /* DMAMUX 1 clock enable */ + + regval |= RCC_AHB1ENR_DMAMUX1EN; +#endif + #ifdef CONFIG_STM32L4_DMA1 /* DMA 1 clock enable */ @@ -762,11 +768,16 @@ static void stm32l4_stdclockconfig(void) regval |= RCC_APB1ENR1_PWREN; putreg32(regval, STM32L4_RCC_APB1ENR1); - /* Switch to Range 1 boost mode to support system - * frequencies up to 120 MHz. Range 2 is not supported. + /* Switch to Range 1 boost mode to support system frequencies up to + * 120 MHz. + * If any PLL has output frequency higher than 80 Mhz, Range 1 boost + * mode needs to be used (RM0432, "6.2.9 Clock source frequency versus + * voltage scaling"). + * Range 2 is not supported. */ -#if STM32L4_SYSCLK_FREQUENCY > 80000000 +#if STM32L4_SYSCLK_FREQUENCY > 80000000 || \ + (defined(BOARD_MAX_PLL_FREQUENCY) && BOARD_MAX_PLL_FREQUENCY > 80000000) regval = getreg32(STM32L4_PWR_CR5); regval &= ~PWR_CR5_R1MODE; putreg32(regval, STM32L4_PWR_CR5); diff --git a/boards/arm/stm32l4/stm32l4r9ai-disco/configs/nsh/defconfig b/boards/arm/stm32l4/stm32l4r9ai-disco/configs/nsh/defconfig index 767781ca6cd..27cf5e0f063 100644 --- a/boards/arm/stm32l4/stm32l4r9ai-disco/configs/nsh/defconfig +++ b/boards/arm/stm32l4/stm32l4r9ai-disco/configs/nsh/defconfig @@ -67,6 +67,7 @@ CONFIG_SCHED_WAITPID=y CONFIG_SDCLONE_DISABLE=y CONFIG_SPI_DRIVER=y CONFIG_STM32L4_DISABLE_IDLE_SLEEP_DURING_DEBUG=y +CONFIG_STM32L4_DMA1=y CONFIG_STM32L4_I2C1=y CONFIG_STM32L4_I2C3=y CONFIG_STM32L4_PWR=y