diff --git a/arch/arm/src/stm32/chip/stm32_dma_v1.h b/arch/arm/src/stm32/chip/stm32_dma_v1.h index 12654068a37..0a2ddeb80b9 100644 --- a/arch/arm/src/stm32/chip/stm32_dma_v1.h +++ b/arch/arm/src/stm32/chip/stm32_dma_v1.h @@ -45,6 +45,10 @@ #define HAVE_IP_DMA_V1 1 #undef HAVE_IP_DMA_V2 +/* F0, L0, L4 have additional CSELR register */ + +#undef DMA_HAVE_CSELR 1 + /* These definitions apply to both the STM32 F1 and F3 families */ /* 12 Channels Total: 7 DMA1 Channels(1-7) and 5 DMA2 channels (1-5) */ @@ -112,6 +116,10 @@ #define STM32_DMA_CMAR6_OFFSET 0x0078 /* DMA channel 6 memory address register */ #define STM32_DMA_CMAR7_OFFSET 0x008c /* DMA channel 7 memory address register */ +#ifdef DMA_HAVE_CSELR +# define STM32_DMA_CSELR_OFFSET 0x00a8 /* DMA channel selection register */ +#endif + /* Register Addresses ***************************************************************/ #define STM32_DMA1_ISRC (STM32_DMA1_BASE+STM32_DMA_ISR_OFFSET) @@ -301,6 +309,14 @@ #define STM32_DMA2_CHAN4 (10) #define STM32_DMA2_CHAN5 (11) +#ifdef DMA_HAVE_CSELR +# define DMACHAN_SETTING(chan, sel) ((((sel) & 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) +#endif + #if defined(CONFIG_STM32_STM32L15XX) # define DMACHAN_ADC1 STM32_DMA1_CHAN1 diff --git a/arch/arm/src/stm32/stm32_dma_v1.c b/arch/arm/src/stm32/stm32_dma_v1.c index 12d53f8f6b8..30f3606a43b 100644 --- a/arch/arm/src/stm32/stm32_dma_v1.c +++ b/arch/arm/src/stm32/stm32_dma_v1.c @@ -55,7 +55,11 @@ #include "stm32_dma.h" #include "stm32.h" -/* This file supports the STM32 DMA IP core version 1 - F0, F1, F3, L1, L4 */ +/* This file supports the STM32 DMA IP core version 1 - F0, F1, F3, L0, L1, L4 + * + * F0, L0 and L4 have the additional CSELR register which is used to reamap + * the DMA requests for each channel. + */ /**************************************************************************** * Pre-processor Definitions @@ -82,6 +86,9 @@ struct stm32_dma_s { uint8_t chan; /* DMA channel number (0-6) */ +#ifdef DMA_HAVE_CSELR + uint8_t function; /* DMA peripheral connected to this channel (0-7) */ +#endif uint8_t irq; /* DMA channel IRQ number */ sem_t sem; /* Used to wait for DMA channel to become available */ uint32_t base; /* DMA register channel base address */ @@ -399,9 +406,19 @@ void weak_function up_dma_initialize(void) * ****************************************************************************/ -DMA_HANDLE stm32_dmachannel(unsigned int chndx) +DMA_HANDLE stm32_dmachannel(unsigned int chndef) { - struct stm32_dma_s *dmach = &g_dma[chndx]; + int chndx = 0; + struct stm32_dma_s *dmach = NULL; + +#ifdef DMA_HAVE_CSELR + chndx = (chndef & DMACHAN_SETTING_CHANNEL_MASK) >> + DMACHAN_SETTING_CHANNEL_SHIFT; +#else + chndx = chndef; +#endif + + dmach = &g_dma[chndx]; DEBUGASSERT(chndx < DMA_NCHANNELS); @@ -413,6 +430,15 @@ DMA_HANDLE stm32_dmachannel(unsigned int chndx) /* The caller now has exclusive use of the DMA channel */ +#ifdef DMA_HAVE_CSELR + /* Define the peripheral that will use the channel. This is stored until + * dmasetup is called. + */ + + dmach->function = (chndef & DMACHAN_SETTING_FUNCTION_MASK) >> + DMACHAN_SETTING_FUNCTION_SHIFT; +#endif + return (DMA_HANDLE)dmach; } @@ -502,6 +528,15 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, DMA_CCR_DIR); regval |= ccr; dmachan_putreg(dmach, STM32_DMACHAN_CCR_OFFSET, regval); + +#ifdef DMA_HAVE_CSELR + /* Define peripheral indicated in dmach->function */ + + regval = dmabase_getreg(dmach, STM32_DMA_CSELR_OFFSET); + regval &= ~(0x0f << (dmach->chan << 2)); + regval |= (dmach->function << (dmach->chan << 2)); + dmabase_putreg(dmach, STM32_DMA_CSELR_OFFSET, regval); +#endif } /**************************************************************************** @@ -708,6 +743,9 @@ void stm32_dmasample(DMA_HANDLE handle, struct stm32_dmaregs_s *regs) flags = enter_critical_section(); regs->isr = dmabase_getreg(dmach, STM32_DMA_ISR_OFFSET); +#ifdef DMA_HAVE_CSELR + regs->cselr = dmabase_getreg(dmach, STM32_DMA_CSELR_OFFSET); +#endif regs->ccr = dmachan_getreg(dmach, STM32_DMACHAN_CCR_OFFSET); regs->cndtr = dmachan_getreg(dmach, STM32_DMACHAN_CNDTR_OFFSET); regs->cpar = dmachan_getreg(dmach, STM32_DMACHAN_CPAR_OFFSET); @@ -736,6 +774,9 @@ void stm32_dmadump(DMA_HANDLE handle, const struct stm32_dmaregs_s *regs, dmainfo("DMA Registers: %s\n", msg); dmainfo(" ISRC[%08x]: %08x\n", dmabase + STM32_DMA_ISR_OFFSET, regs->isr); +#ifdef DMA_HAVE_CSELR + dmainfo(" CSELR[%08x]: %08x\n", dmabase + STM32_DMA_CSELR_OFFSET, regs->cselr); +#endif dmainfo(" CCR[%08x]: %08x\n", dmach->base + STM32_DMACHAN_CCR_OFFSET, regs->ccr); dmainfo(" CNDTR[%08x]: %08x\n", dmach->base + STM32_DMACHAN_CNDTR_OFFSET, regs->cndtr); dmainfo(" CPAR[%08x]: %08x\n", dmach->base + STM32_DMACHAN_CPAR_OFFSET, regs->cpar);