diff --git a/arch/arm/src/stm32/stm32_dma.c b/arch/arm/src/stm32/stm32_dma.c index 3cf6ae0a1b..9824be7e83 100755 --- a/arch/arm/src/stm32/stm32_dma.c +++ b/arch/arm/src/stm32/stm32_dma.c @@ -39,10 +39,15 @@ #include #include + +#include #include +#include + #include #include "up_arch.h" +#include "os_internal.h" #include "chip.h" #include "stm32_dma.h" #include "stm32_internal.h" @@ -50,23 +55,262 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ + +#define DMA1_NCHANNELS 7 +#if STM32_NDMA > 1 +# define DMA2_NCHANNELS 5 +# define DMA_NCHANNELS (DMA1_NCHANNELS+DMA2_NCHANNELS) +#else +# define DMA_NCHANNELS DMA1_NCHANNELS +#endif + +/* Convert the DMA channel base address to the DMA register block address */ +#define DMA_BASE(ch) (ch & 0xfffffc00) + /**************************************************************************** * Private Types ****************************************************************************/ +/* Pinch a byte if is possible if there are not very many DMA channels */ + +#if DMA_NCHANNELS > 8 +typedef uint16 dma_bitset_t; +#else +typedef uint8 dma_bitset_t; +#endif + +/* This structure descibes one DMA channel */ + +struct stm32_dma_s +{ + ubyte chan; /* DMA channel number */ + ubyte irq; /* DMA channel IRQ number */ + uint32 base; /* DMA register channel base address */ + dma_callback_t callback; /* Callback invoked when the DMA completes */ +}; + /**************************************************************************** * Private Data ****************************************************************************/ +/* This bitset indicates which DMA channels have been allocated */ + +static dma_bitset_t g_dmaallocated; +static sem_t g_allocsem; + +/* This array describes the state of each DMA */ + +static struct stm32_dma_s g_dma[DMA_NCHANNELS] = +{ + { + .chan = 0, + .irq = STM32_IRQ_DMA1CH1, + .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(0), + }, + { + .chan = 1, + .irq = STM32_IRQ_DMA1CH2, + .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(1), + }, + { + .chan = 2, + .irq = STM32_IRQ_DMA1CH3, + .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(2), + }, + { + .chan = 3, + .irq = STM32_IRQ_DMA1CH4, + .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(3), + }, + { + .chan = 4, + .irq = STM32_IRQ_DMA1CH5, + .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(4), + }, + { + .chan = 5, + .irq = STM32_IRQ_DMA1CH6, + .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(5), + }, + { + .chan = 6, + .irq = STM32_IRQ_DMA1CH7, + .base = STM32_DMA1_BASE + STM32_DMACHAN_OFFSET(6), + }, +#if STM32_NDMA > 1 + { + .chan = 7, + .irq = STM32_IRQ_DMA2CH1, + .base = STM32_DMA2_BASE + STM32_DMACHAN_OFFSET(0), + }, + { + .chan = 8, + .irq = STM32_IRQ_DMA2CH2, + .base = STM32_DMA2_BASE + STM32_DMACHAN_OFFSET(1), + }, + { + .chan = 9, + .irq = STM32_IRQ_DMA2CH3, + .base = STM32_DMA2_BASE + STM32_DMACHAN_OFFSET(2), + }, + { + .chan = 10, + .irq = STM32_IRQ_DMA2CH4, + .base = STM32_DMA2_BASE + STM32_DMACHAN_OFFSET(3), + }, + { + .chan = 11, + .irq = STM32_IRQ_DMA2CH5, + .base = STM32_DMA2_BASE + STM32_DMACHAN_OFFSET(4), + }, +#endif +}; + /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** - * Global Functions + * DMA register access functions ****************************************************************************/ +/* Get non-channel register from DMA1 or DMA2 */ + +static inline uint32 dmabase_getreg(struct stm32_dma_s *dmach, uint32 offset) +{ + return getreg32(DMA_BASE(dmach->base) + offset); +} + +/* Write to non-channel register in DMA1 or DMA2 */ + +static inline void dmabase_putreg(struct stm32_dma_s *dmach, uint32 offset, uint32 value) +{ + putreg32(value, DMA_BASE(dmach->base) + offset); +} + +/* Get channel register from DMA1 or DMA2 */ + +static inline uint32 dmachan_getreg(struct stm32_dma_s *dmach, uint32 offset) +{ + return getreg32(dmach->base + offset); +} + +/* Write to channel register in DMA1 or DMA2 */ + +static inline void dmachan_putreg(struct stm32_dma_s *dmach, uint32 offset, uint32 value) +{ + putreg32(value, dmach->base + offset); +} + +/************************************************************************************ + * Name: stm32_dmatake() and stm32_dmagive() + * + * Description: + * Take/give semaphore that protects the channel allocation bitset + * + ************************************************************************************/ + +static void stm32_dmatake(void) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&g_allocsem) != 0) + { + /* The only case that an error should occur here is if the wait was awakened + * by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +static inline void stm32_dmagive(void) +{ + (void)sem_post(&g_allocsem); +} + +/************************************************************************************ + * Name: stm32_dmainterrupt + * + * Description: + * DMA interrupt handler + * + ************************************************************************************/ + +static int stm32_dmainterrupt(int irq, void *context) +{ + struct stm32_dma_s *dmach; + uint32 isr; + int chan; + + /* Get the channel structure from the interrupt number */ + + if (irq >= STM32_IRQ_DMA1CH1 && irq <= STM32_IRQ_DMA1CH7) + { + chan = irq - STM32_IRQ_DMA1CH1; + } + else +#if STM32_NDMA > 1 + if (irq >= STM32_IRQ_DMA2CH1 && irq <= STM32_IRQ_DMA2CH5) + { + chan = irq - STM32_IRQ_DMA2CH1 + DMA1_NCHANNELS; + } + else +#endif + { + PANIC(OSERR_INTERNAL); + } + dmach = &g_dma[chan]; + + /* Get the interrupt status (for this channel only) */ + + isr = dmabase_getreg(dmach, STM32_DMA_ISR_OFFSET) & ~DMA_ISR_CHAN_MASK(chan); + + /* Clear pending interrupts (for this channel only) */ + + dmabase_putreg(dmach, STM32_DMA_IFCR_OFFSET, isr); + + /* Invoke the callback */ + + if (dmach->callback) + { + dmach->callback(dmach, isr >> DMA_ISR_CHAN_SHIFT(chan)); + } + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_dmainitialize + * + * Description: + * Initialize the DMA subsystem + * + * Returned Value: + * None + * + ****************************************************************************/ + +void weak_function stm32_dmainitialize(void) +{ + int chan; + + /* Initialize the semaphore used to protect the allocation bitset */ + + sem_init(&g_allocsem, 0, 1); + + /* Attach DMA interrupt vectors */ + + for (chan = 0; chan < DMA_NCHANNELS; chan++) + { + irq_attach(g_dma[chan].irq, stm32_dmainterrupt); + } +} + /**************************************************************************** * Name: stm32_dmachannel * @@ -80,5 +324,116 @@ DMA_HANDLE stm32_dmachannel(void) { - return NULL; + struct stm32_dma_s *dmach = NULL; + int chan; + int bit; + + /* Make sure that we exclusive access to the DMA bitset */ + + stm32_dmatake(); + + /* Try each possible channel */ + + for (chan = 0, bit = 1; chan < DMA_NCHANNELS; chan++, bit <<= 1) + { + /* Has this channel been allocated? */ + + if ((g_dmaallocated & bit) == 0) + { + /* No.. grab it and return */ + + g_dmaallocated |= bit; + dmach = &g_dma[chan]; + break; + } + } + + stm32_dmagive(); + return (DMA_HANDLE)dmach; +} + +/**************************************************************************** + * Name: stm32_dmasetup + * + * Description: + * Configure DMA before using + * + ****************************************************************************/ + +void stm32_dmasetup(DMA_HANDLE handle, uint32 paddr, uint32 maddr, size_t ntransfers, uint32 ccr) +{ + struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle; + uint32 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(dmach, STM32_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(dmach, STM32_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(dmach, STM32_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_gettreg(dmach, STM32_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(dmach, STM32_DMACHAN_CCR_OFFSET, regval); +} + +/**************************************************************************** + * Name: stm32_dmastart + * + * Description: + * Start the DMA transfer + * + ****************************************************************************/ + +void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, boolean half) +{ + struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle; + int irq; + uint32 ccr; + + DEBUGASSERT(handle != NULL); + + /* Save the callback. This will be invoked whent the DMA commpletes */ + + dmach->callback = callback; + + /* 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_gettreg(dmach, STM32_DMACHAN_CCR_OFFSET); + ccr |= DMA_CCR_EN; + + /* 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)); + dmachan_putreg(dmach, STM32_DMACHAN_CCR_OFFSET, ccr); } diff --git a/arch/arm/src/stm32/stm32_dma.h b/arch/arm/src/stm32/stm32_dma.h index f62acccf47..8c44674aa4 100644 --- a/arch/arm/src/stm32/stm32_dma.h +++ b/arch/arm/src/stm32/stm32_dma.h @@ -60,10 +60,20 @@ /* Register Offsets *****************************************************************/ -#define STM32_DMA_ISR_OFFSET 0x0000 /* DMA interrupt status register */ -#define STM32_DMA_IFCR_OFFSET 0x0004 /* DMA interrupt flag clear register */ +#define STM32_DMA_ISR_OFFSET 0x0000 /* DMA interrupt status register */ +#define STM32_DMA_IFCR_OFFSET 0x0004 /* DMA interrupt flag clear register */ + +#define STM32_DMACHAN_OFFSET(n) (0x0014*(n)) +#define STM32_DMACHAN_CCR_OFFSET 0x0008 +#define STM32_DMACHAN_CNDTR_OFFSET 0x000c +#define STM32_DMACHAN_CPAR_OFFSET 0x0010 +#define STM32_DMACHAN_CMAR_OFFSET 0x0014 + +#define STM32_DMA_CCR_OFFSET(n) (STM32_DMACHAN_CCR_OFFSET+STM32_DMACHAN_OFFSET(n)) +#define STM32_DMA_CNDTR_OFFSET(n) (STM32_DMACHAN_CNDTR_OFFSET+STM32_DMACHAN_OFFSET(n)) +#define STM32_DMA_CPAR_OFFSET(n) (STM32_DMACHAN_CPAR_OFFSET+STM32_DMACHAN_OFFSET(n)) +#define STM32_DMA_CMAR_OFFSET(n) (STM32_DMACHAN_CMAR_OFFSET+STM32_DMACHAN_OFFSET(n)) -#define STM32_DMA_CCR_OFFSET(n) (0x0008+0x0014*(n)) #define STM32_DMA_CCR1_OFFSET 0x0008 /* DMA channel 1 configuration register */ #define STM32_DMA_CCR2_OFFSET 0x001c /* DMA channel 2 configuration register */ #define STM32_DMA_CCR3_OFFSET 0x0030 /* DMA channel 3 configuration register */ @@ -72,7 +82,6 @@ #define STM32_DMA_CCR6_OFFSET 0x006c /* DMA channel 6 configuration register */ #define STM32_DMA_CCR7_OFFSET 0x0080 /* DMA channel 7 configuration register */ -#define STM32_DMA_CNDTR_OFFSET(n) (0x000c+0x0014*(n)) #define STM32_DMA_CNDTR1_OFFSET 0x000c /* DMA channel 1 number of data register */ #define STM32_DMA_CNDTR2_OFFSET 0x0020 /* DMA channel 2 number of data register */ #define STM32_DMA_CNDTR3_OFFSET 0x0034 /* DMA channel 3 number of data register */ @@ -81,7 +90,6 @@ #define STM32_DMA_CNDTR6_OFFSET 0x0070 /* DMA channel 6 number of data register */ #define STM32_DMA_CNDTR7_OFFSET 0x0084 /* DMA channel 7 number of data register */ -#define STM32_DMA_CPAR_OFFSET(n) (0x0010+0x0014*(n)) #define STM32_DMA_CPAR1_OFFSET 0x0010 /* DMA channel 1 peripheral address register */ #define STM32_DMA_CPAR2_OFFSET 0x0024 /* DMA channel 2 peripheral address register */ #define STM32_DMA_CPAR3_OFFSET 0x0038 /* DMA channel 3 peripheral address register */ @@ -90,7 +98,6 @@ #define STM32_DMA_CPAR6_OFFSET 0x0074 /* DMA channel 6 peripheral address register */ #define STM32_DMA_CPAR7_OFFSET 0x0088 /* DMA channel 7 peripheral address register */ -#define STM32_DMA_CMAR_OFFSET(n) (0x0014+0x0014*(n)) #define STM32_DMA_CMAR1_OFFSET 0x0014 /* DMA channel 1 memory address register */ #define STM32_DMA_CMAR2_OFFSET 0x0028 /* DMA channel 2 memory address register */ #define STM32_DMA_CMAR3_OFFSET 0x003c /* DMA channel 3 memory address register */ @@ -101,102 +108,132 @@ /* Register Addresses ***************************************************************/ -#define STM32_DMA_ISRC (STM32_DMA_BASE+STM32_DMA_ISRC_OFFSET) -#define STM32_DMA_IFCR (STM32_DMA_BASE+STM32_DMA_IFCR_OFFSET) +#define STM32_DMA1_ISRC (STM32_DMA1_BASE+STM32_DMA_ISR_OFFSET) +#define STM32_DMA1_IFCR (STM32_DMA1_BASE+STM32_DMA_IFCR_OFFSET) -#define STM32_DMA_CCR(n) (STM32_DMA_BASE+STM32_DMA_CCR_OFFSET(n)) -#define STM32_DMA_CCR1 (STM32_DMA_BASE+STM32_DMA_CCR1_OFFSET) -#define STM32_DMA_CCR2 (STM32_DMA_BASE+STM32_DMA_CCR2_OFFSET) -#define STM32_DMA_CCR3 (STM32_DMA_BASE+STM32_DMA_CCR3_OFFSET) -#define STM32_DMA_CCR4 (STM32_DMA_BASE+STM32_DMA_CCR4_OFFSET) -#define STM32_DMA_CCR5 (STM32_DMA_BASE+STM32_DMA_CCR5_OFFSET) -#define STM32_DMA_CCR6 (STM32_DMA_BASE+STM32_DMA_CCR6_OFFSET) -#define STM32_DMA_CCR7 (STM32_DMA_BASE+STM32_DMA_CCR7_OFFSET) +#define STM32_DMA1_CCR(n) (STM32_DMA1_BASE+STM32_DMA_CCR_OFFSET(n)) +#define STM32_DMA1_CCR1 (STM32_DMA1_BASE+STM32_DMA_CCR1_OFFSET) +#define STM32_DMA1_CCR2 (STM32_DMA1_BASE+STM32_DMA_CCR2_OFFSET) +#define STM32_DMA1_CCR3 (STM32_DMA1_BASE+STM32_DMA_CCR3_OFFSET) +#define STM32_DMA1_CCR4 (STM32_DMA1_BASE+STM32_DMA_CCR4_OFFSET) +#define STM32_DMA1_CCR5 (STM32_DMA1_BASE+STM32_DMA_CCR5_OFFSET) +#define STM32_DMA1_CCR6 (STM32_DMA1_BASE+STM32_DMA_CCR6_OFFSET) +#define STM32_DMA1_CCR7 (STM32_DMA1_BASE+STM32_DMA_CCR7_OFFSET) -#define STM32_DMA_CNDTR(n) (STM32_DMA_BASE+STM32_DMA_CNDTR_OFFSET(n)) -#define STM32_DMA_CNDTR1 (STM32_DMA_BASE+STM32_DMA_CNDTR1_OFFSET) -#define STM32_DMA_CNDTR2 (STM32_DMA_BASE+STM32_DMA_CNDTR2_OFFSET) -#define STM32_DMA_CNDTR3 (STM32_DMA_BASE+STM32_DMA_CNDTR3_OFFSET) -#define STM32_DMA_CNDTR4 (STM32_DMA_BASE+STM32_DMA_CNDTR4_OFFSET) -#define STM32_DMA_CNDTR5 (STM32_DMA_BASE+STM32_DMA_CNDTR5_OFFSET) -#define STM32_DMA_CNDTR6 (STM32_DMA_BASE+STM32_DMA_CNDTR6_OFFSET) -#define STM32_DMA_CNDTR7 (STM32_DMA_BASE+STM32_DMA_CNDTR7_OFFSET) +#define STM32_DMA1_CNDTR(n) (STM32_DMA1_BASE+STM32_DMA_CNDTR_OFFSET(n)) +#define STM32_DMA1_CNDTR1 (STM32_DMA1_BASE+STM32_DMA_CNDTR1_OFFSET) +#define STM32_DMA1_CNDTR2 (STM32_DMA1_BASE+STM32_DMA_CNDTR2_OFFSET) +#define STM32_DMA1_CNDTR3 (STM32_DMA1_BASE+STM32_DMA_CNDTR3_OFFSET) +#define STM32_DMA1_CNDTR4 (STM32_DMA1_BASE+STM32_DMA_CNDTR4_OFFSET) +#define STM32_DMA1_CNDTR5 (STM32_DMA1_BASE+STM32_DMA_CNDTR5_OFFSET) +#define STM32_DMA1_CNDTR6 (STM32_DMA1_BASE+STM32_DMA_CNDTR6_OFFSET) +#define STM32_DMA1_CNDTR7 (STM32_DMA1_BASE+STM32_DMA_CNDTR7_OFFSET) -#define STM32_DMA_CPAR(n) (STM32_DMA_BASE+STM32_DMA_CPAR_OFFSET(n)) -#define STM32_DMA_CPAR1 (STM32_DMA_BASE+STM32_DMA_CPAR1_OFFSET) -#define STM32_DMA_CPAR2 (STM32_DMA_BASE+STM32_DMA_CPAR2_OFFSET) -#define STM32_DMA_CPAR3 (STM32_DMA_BASE+STM32_DMA_CPAR3_OFFSET) -#define STM32_DMA_CPAR4 (STM32_DMA_BASE+STM32_DMA_CPAR4_OFFSET) -#define STM32_DMA_CPAR5 (STM32_DMA_BASE+STM32_DMA_CPAR5_OFFSET) -#define STM32_DMA_CPAR6 (STM32_DMA_BASE+STM32_DMA_CPAR6_OFFSET) -#define STM32_DMA_CPAR7 (STM32_DMA_BASE+STM32_DMA_CPAR7_OFFSET) +#define STM32_DMA1_CPAR(n) (STM32_DMA1_BASE+STM32_DMA_CPAR_OFFSET(n)) +#define STM32_DMA1_CPAR1 (STM32_DMA1_BASE+STM32_DMA_CPAR1_OFFSET) +#define STM32_DMA1_CPAR2 (STM32_DMA1_BASE+STM32_DMA_CPAR2_OFFSET) +#define STM32_DMA1_CPAR3 (STM32_DMA1_BASE+STM32_DMA_CPAR3_OFFSET) +#define STM32_DMA1_CPAR4 (STM32_DMA1_BASE+STM32_DMA_CPAR4_OFFSET) +#define STM32_DMA1_CPAR5 (STM32_DMA1_BASE+STM32_DMA_CPAR5_OFFSET) +#define STM32_DMA1_CPAR6 (STM32_DMA1_BASE+STM32_DMA_CPAR6_OFFSET) +#define STM32_DMA1_CPAR7 (STM32_DMA1_BASE+STM32_DMA_CPAR7_OFFSET) -#define STM32_DMA_CMAR(n) (STM32_DMA_BASE+STM32_DMA_CMAR_OFFSET(n)) -#define STM32_DMA_CMAR1 (STM32_DMA_BASE+STM32_DMA_CMAR1_OFFSET) -#define STM32_DMA_CMAR2 (STM32_DMA_BASE+STM32_DMA_CMAR2_OFFSET) -#define STM32_DMA_CMAR3 (STM32_DMA_BASE+STM32_DMA_CMAR3_OFFSET) -#define STM32_DMA_CMAR4 (STM32_DMA_BASE+STM32_DMA_CMAR4_OFFSET) -#define STM32_DMA_CMAR5 (STM32_DMA_BASE+STM32_DMA_CMAR5_OFFSET) -#define STM32_DMA_CMAR6 (STM32_DMA_BASE+STM32_DMA_CMAR6_OFFSET) -#define STM32_DMA_CMAR7 (STM32_DMA_BASE+STM32_DMA_CMAR7_OFFSET) +#define STM32_DMA1_CMAR(n) (STM32_DMA1_BASE+STM32_DMA_CMAR_OFFSET(n)) +#define STM32_DMA1_CMAR1 (STM32_DMA1_BASE+STM32_DMA_CMAR1_OFFSET) +#define STM32_DMA1_CMAR2 (STM32_DMA1_BASE+STM32_DMA_CMAR2_OFFSET) +#define STM32_DMA1_CMAR3 (STM32_DMA1_BASE+STM32_DMA_CMAR3_OFFSET) +#define STM32_DMA1_CMAR4 (STM32_DMA1_BASE+STM32_DMA_CMAR4_OFFSET) +#define STM32_DMA1_CMAR5 (STM32_DMA1_BASE+STM32_DMA_CMAR5_OFFSET) +#define STM32_DMA1_CMAR6 (STM32_DMA1_BASE+STM32_DMA_CMAR6_OFFSET) +#define STM32_DMA1_CMAR7 (STM32_DMA1_BASE+STM32_DMA_CMAR7_OFFSET) + +#define STM32_DMA2_ISRC (STM32_DMA2_BASE+STM32_DMA_ISR_OFFSET) +#define STM32_DMA2_IFCR (STM32_DMA2_BASE+STM32_DMA_IFCR_OFFSET) + +#define STM32_DMA2_CCR(n) (STM32_DMA2_BASE+STM32_DMA_CCR_OFFSET(n)) +#define STM32_DMA2_CCR1 (STM32_DMA2_BASE+STM32_DMA_CCR1_OFFSET) +#define STM32_DMA2_CCR2 (STM32_DMA2_BASE+STM32_DMA_CCR2_OFFSET) +#define STM32_DMA2_CCR3 (STM32_DMA2_BASE+STM32_DMA_CCR3_OFFSET) +#define STM32_DMA2_CCR4 (STM32_DMA2_BASE+STM32_DMA_CCR4_OFFSET) +#define STM32_DMA2_CCR5 (STM32_DMA2_BASE+STM32_DMA_CCR5_OFFSET) + +#define STM32_DMA2_CNDTR(n) (STM32_DMA2_BASE+STM32_DMA_CNDTR_OFFSET(n)) +#define STM32_DMA2_CNDTR1 (STM32_DMA2_BASE+STM32_DMA_CNDTR1_OFFSET) +#define STM32_DMA2_CNDTR2 (STM32_DMA2_BASE+STM32_DMA_CNDTR2_OFFSET) +#define STM32_DMA2_CNDTR3 (STM32_DMA2_BASE+STM32_DMA_CNDTR3_OFFSET) +#define STM32_DMA2_CNDTR4 (STM32_DMA2_BASE+STM32_DMA_CNDTR4_OFFSET) +#define STM32_DMA2_CNDTR5 (STM32_DMA2_BASE+STM32_DMA_CNDTR5_OFFSET) + +#define STM32_DMA2_CPAR(n) (STM32_DMA2_BASE+STM32_DMA_CPAR_OFFSET(n)) +#define STM32_DMA2_CPAR1 (STM32_DMA2_BASE+STM32_DMA_CPAR1_OFFSET) +#define STM32_DMA2_CPAR2 (STM32_DMA2_BASE+STM32_DMA_CPAR2_OFFSET) +#define STM32_DMA2_CPAR3 (STM32_DMA2_BASE+STM32_DMA_CPAR3_OFFSET) +#define STM32_DMA2_CPAR4 (STM32_DMA2_BASE+STM32_DMA_CPAR4_OFFSET) +#define STM32_DMA2_CPAR5 (STM32_DMA2_BASE+STM32_DMA_CPAR5_OFFSET) + +#define STM32_DMA2_CMAR(n) (STM32_DMA2_BASE+STM32_DMA_CMAR_OFFSET(n)) +#define STM32_DMA2_CMAR1 (STM32_DMA2_BASE+STM32_DMA_CMAR1_OFFSET) +#define STM32_DMA2_CMAR2 (STM32_DMA2_BASE+STM32_DMA_CMAR2_OFFSET) +#define STM32_DMA2_CMAR3 (STM32_DMA2_BASE+STM32_DMA_CMAR3_OFFSET) +#define STM32_DMA2_CMAR4 (STM32_DMA2_BASE+STM32_DMA_CMAR4_OFFSET) +#define STM32_DMA2_CMAR5 (STM32_DMA2_BASE+STM32_DMA_CMAR5_OFFSET) /* Register Bitfield Definitions ****************************************************/ +#define DMA_CHAN_SHIFT(n) ((n) << 2) +#define DMA_CHAN_MASK 0x0f +#define DMA_CHAN_GIF_BIT (1 << 0) /* Bit 0: Channel Global interrupt flag */ +#define DMA_CHAN_TCIF_BIT (1 << 1) /* Bit 1: Channel Transfer Complete flag */ +#define DMA_CHAN_HTIF_BIT (1 << 2) /* Bit 2: Channel Half Transfer flag */ +#define DMA_CHAN_TEIF_BIT (1 << 3) /* Bit 3: Channel Transfer Error flag */ + /* DMA interrupt status register */ -#define DMA_ISRC_CHAN_SHIFT(n) (4*(n)) -#define DMA_ISRC_CHAN_MASK(n) (0x0f << DMA_ISRC_CHAN_SHIFT(n)) -#define DMA_ISRC_CHAN1_SHIFT (0) /* Bits 3-0: DMA Channel 1 interrupt status */ -#define DMA_ISRC_CHAN1_MASK (0x0f << DMA_ISRC_CHAN1_SHIFT) -#define DMA_ISRC_CHAN2_SHIFT (4) /* Bits 7-4: DMA Channel 2 interrupt status */ -#define DMA_ISRC_CHAN2_MASK (0x0f << DMA_ISRC_CHAN2_SHIFT) -#define DMA_ISRC_CHAN3_SHIFT (8) /* Bits 11-8: DMA Channel 3 interrupt status */ -#define DMA_ISRC_CHAN3_MASK (0x0f << DMA_ISRC_CHAN3_SHIFT) -#define DMA_ISRC_CHAN4_SHIFT (12) /* Bits 15-12: DMA Channel 4 interrupt status */ -#define DMA_ISRC_CHAN4_MASK (0x0f << DMA_ISRC_CHAN4_SHIFT) -#define DMA_ISRC_CHAN5_SHIFT (16) /* Bits 19-16: DMA Channel 5 interrupt status */ -#define DMA_ISRC_CHAN5_MASK (0x0f << DMA_ISRC_CHAN5_SHIFT) -#define DMA_ISRC_CHAN6_SHIFT (20) /* Bits 23-20: DMA Channel 6 interrupt status */ -#define DMA_ISRC_CHAN6_MASK (0x0f << DMA_ISRC_CHAN6_SHIFT) -#define DMA_ISRC_CHAN7_SHIFT (24) /* Bits 27-24: DMA Channel 7 interrupt status */ -#define DMA_ISRC_CHAN7_MASK (0x0f << DMA_ISRC_CHAN7_SHIFT) +#define DMA_ISR_CHAN_SHIFT(n) DMA_CHAN_SHIFT(n) +#define DMA_ISR_CHAN_MASK(n) (DMA_CHAN_MASK << DMA_ISR_CHAN_SHIFT(n)) +#define DMA_ISR_CHAN1_SHIFT (0) /* Bits 3-0: DMA Channel 1 interrupt status */ +#define DMA_ISR_CHAN1_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN1_SHIFT) +#define DMA_ISR_CHAN2_SHIFT (4) /* Bits 7-4: DMA Channel 2 interrupt status */ +#define DMA_ISR_CHAN2_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN2_SHIFT) +#define DMA_ISR_CHAN3_SHIFT (8) /* Bits 11-8: DMA Channel 3 interrupt status */ +#define DMA_ISR_CHAN3_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN3_SHIFT) +#define DMA_ISR_CHAN4_SHIFT (12) /* Bits 15-12: DMA Channel 4 interrupt status */ +#define DMA_ISR_CHAN4_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN4_SHIFT) +#define DMA_ISR_CHAN5_SHIFT (16) /* Bits 19-16: DMA Channel 5 interrupt status */ +#define DMA_ISR_CHAN5_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN5_SHIFT) +#define DMA_ISR_CHAN6_SHIFT (20) /* Bits 23-20: DMA Channel 6 interrupt status */ +#define DMA_ISR_CHAN6_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN6_SHIFT) +#define DMA_ISR_CHAN7_SHIFT (24) /* Bits 27-24: DMA Channel 7 interrupt status */ +#define DMA_ISR_CHAN7_MASK (DMA_CHAN_MASK << DMA_ISR_CHAN7_SHIFT) -#define DMA_ISRC_GIF_BIT (1 << 0) /* Bit 0: Channel Global interrupt flag */ -#define DMA_ISRC_GIF(n) (DMA_ISRC_GIF_BIT << DMA_ISRC_CHAN_SHIFT(n)) -#define DMA_ISRC_TCIF_BIT (1 << 1) /* Bit 1: Channel Transfer Complete flag */ -#define DMA_ISRC_TCIF(n) (DMA_ISRC_TCIF_BIT << DMA_ISRC_CHAN_SHIFT(n)) -#define DMA_ISRC_HTIF_BIT (1 << 2) /* Bit 2: Channel Half Transfer flag */ -#define DMA_ISRC_HTIF(n) (DMA_ISRC_HTIF_BIT << DMA_ISRC_CHAN_SHIFT(n)) -#define DMA_ISRC_TEIF_BIT (1 << 3) /* Bit 3: Channel Transfer Error flag */ -#define DMA_ISRC_TEIF(n) (DMA_ISRC_TEIF_BIT << DMA_ISRC_CHAN_SHIFT(n)) +#define DMA_ISR_GIF(n) (DMA_CHAN_GIF_BIT << DMA_ISR_CHAN_SHIFT(n)) +#define DMA_ISR_TCIF(n) (DMA_CHAN_TCIF_BIT << DMA_ISR_CHAN_SHIFT(n)) +#define DMA_ISR_HTIF(n) (DMA_CHAN_HTIF_BIT << DMA_ISR_CHAN_SHIFT(n)) +#define DMA_ISR_TEIF(n) (DMA_CHAN_TEIF_BIT << DMA_ISR_CHAN_SHIFT(n)) /* DMA interrupt flag clear register */ -#define DMA_IFCR_CHAN_SHIFT(n) (4*(n)) -#define DMA_IFCR_CHAN_MASK(n) (0x0f << DMA_IFCR_CHAN_SHIFT(n)) +#define DMA_IFCR_CHAN_SHIFT(n) DMA_CHAN_SHIFT(n) +#define DMA_IFCR_CHAN_MASK(n) (DMA_CHAN_MASK << DMA_IFCR_CHAN_SHIFT(n)) #define DMA_IFCR_CHAN1_SHIFT (0) /* Bits 3-0: DMA Channel 1 interrupt flag clear */ -#define DMA_IFCR_CHAN1_MASK (0x0f << DMA_IFCR_CHAN1_SHIFT) +#define DMA_IFCR_CHAN1_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN1_SHIFT) #define DMA_IFCR_CHAN2_SHIFT (4) /* Bits 7-4: DMA Channel 2 interrupt flag clear */ -#define DMA_IFCR_CHAN2_MASK (0x0f << DMA_IFCR_CHAN2_SHIFT) +#define DMA_IFCR_CHAN2_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN2_SHIFT) #define DMA_IFCR_CHAN3_SHIFT (8) /* Bits 11-8: DMA Channel 3 interrupt flag clear */ -#define DMA_IFCR_CHAN3_MASK (0x0f << DMA_IFCR_CHAN3_SHIFT) +#define DMA_IFCR_CHAN3_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN3_SHIFT) #define DMA_IFCR_CHAN4_SHIFT (12) /* Bits 15-12: DMA Channel 4 interrupt flag clear */ -#define DMA_IFCR_CHAN4_MASK (0x0f << DMA_IFCR_CHAN4_SHIFT) +#define DMA_IFCR_CHAN4_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN4_SHIFT) #define DMA_IFCR_CHAN5_SHIFT (16) /* Bits 19-16: DMA Channel 5 interrupt flag clear */ -#define DMA_IFCR_CHAN5_MASK (0x0f << DMA_IFCR_CHAN5_SHIFT) +#define DMA_IFCR_CHAN5_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN5_SHIFT) #define DMA_IFCR_CHAN6_SHIFT (20) /* Bits 23-20: DMA Channel 6 interrupt flag clear */ -#define DMA_IFCR_CHAN6_MASK (0x0f << DMA_IFCR_CHAN6_SHIFT) +#define DMA_IFCR_CHAN6_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN6_SHIFT) #define DMA_IFCR_CHAN7_SHIFT (24) /* Bits 27-24: DMA Channel 7 interrupt flag clear */ -#define DMA_IFCR_CHAN7_MASK (0x0f << DMA_IFCR_CHAN7_SHIFT) +#define DMA_IFCR_CHAN7_MASK (DMA_CHAN_MASK << DMA_IFCR_CHAN7_SHIFT) -#define DMA_IFCR_CGIF_BIT (1 << 0) /* Bit 0: Channel Global interrupt clear */ -#define DMA_IFCR_CGIF(n) (DMA_IFCR_CGIF_BIT << DMA_IFCR_CHAN_SHIFT(n)) -#define DMA_IFCR_CTCIF_BIT (1 << 1) /* Bit 1: Channel Transfer Complete clear */ -#define DMA_IFCR_CTCIF(n) (DMA_IFCR_CTCIF_BIT << DMA_IFCR_CHAN_SHIFT(n)) -#define DMA_IFCR_CHTIF_BIT (1 << 2) /* Bit 2: Channel Half Transfer clear */ -#define DMA_IFCR_CHTIF(n) (DMA_IFCR_CHTIF_BIT << DMA_IFCR_CHAN_SHIFT(n)) -#define DMA_IFCR_CTEIF_BIT (1 << 3) /* Bit 3: Channel Transfer Error clear */ -#define DMA_IFCR_CTEIF(n) (DMA_IFCR_CTEIF_BIT << DMA_IFCR_CHAN_SHIFT(n)) +#define DMA_IFCR_CGIF(n) (DMA_CHAN_GIF_BIT << DMA_IFCR_CHAN_SHIFT(n)) +#define DMA_IFCR_CTCIF(n) (DMA_CHAN_TCIF_BIT << DMA_IFCR_CHAN_SHIFT(n)) +#define DMA_IFCR_CHTIF(n) (DMA_CHAN_HTIF_BIT << DMA_IFCR_CHAN_SHIFT(n)) +#define DMA_IFCR_CTEIF(n) (DMA_CHAN_TEIF_BIT << DMA_IFCR_CHAN_SHIFT(n)) /* DMA channel configuration register */ diff --git a/arch/arm/src/stm32/stm32_internal.h b/arch/arm/src/stm32/stm32_internal.h index fc2df7d68d..ee0c639bf8 100755 --- a/arch/arm/src/stm32/stm32_internal.h +++ b/arch/arm/src/stm32/stm32_internal.h @@ -380,6 +380,7 @@ ************************************************************************************/ typedef FAR void *DMA_HANDLE; +typedef void (*dma_callback_t)(DMA_HANDLE handle, ubyte isr); /************************************************************************************ * Inline Functions @@ -476,6 +477,19 @@ EXTERN int stm32_dumpgpio(uint32 pinset, const char *msg); # define stm32_dumpgpio(p,m) #endif +/**************************************************************************** + * Name: stm32_dmainitialize + * + * Description: + * Initialize the DMA subsystem + * + * Returned Value: + * None + * + ****************************************************************************/ + +EXTERN void weak_function stm32_dmainitialize(void); + /**************************************************************************** * Name: stm32_dmachannel * @@ -489,6 +503,27 @@ EXTERN int stm32_dumpgpio(uint32 pinset, const char *msg); EXTERN DMA_HANDLE stm32_dmachannel(void); +/**************************************************************************** + * Name: stm32_dmasetup + * + * Description: + * Configure DMA before using + * + ****************************************************************************/ + +EXTERN void stm32_dmasetup(DMA_HANDLE handle, uint32 paddr, uint32 maddr, + size_t ntransfers, uint32 ccr); + +/**************************************************************************** + * Name: stm32_dmastart + * + * Description: + * Start the DMA transfer + * + ****************************************************************************/ + +EXTERN void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, boolean half); + /************************************************************************************ * Function: stm32_ethinitialize * diff --git a/arch/arm/src/stm32/stm32_spi.c b/arch/arm/src/stm32/stm32_spi.c index 581c02f695..f485006c61 100755 --- a/arch/arm/src/stm32/stm32_spi.c +++ b/arch/arm/src/stm32/stm32_spi.c @@ -869,7 +869,7 @@ void stm32_spitake(FAR struct spi_dev_s *dev) * by a signal. */ - ASSERT(*get_errno_ptr() == EINTR); + ASSERT(errno == EINTR); } } diff --git a/configs/stm3210e-eval/src/up_boot.c b/configs/stm3210e-eval/src/up_boot.c index aef793520f..9787abaeb1 100755 --- a/configs/stm3210e-eval/src/up_boot.c +++ b/configs/stm3210e-eval/src/up_boot.c @@ -72,6 +72,15 @@ void stm32_boardinitialize(void) { + /* Initialize the DMA subsystem if the weak function stm32_dmainitialize has been + * brought into the build + */ + + if (stm32_dmainitialize) + { + stm32_dmainitialize(); + } + /* Configure SPI chip selects if 1) SPI is not disabled, and 2) the weak function * stm32_spiinitialize() has been brought into the link. */