First cut at DMA code

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2142 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2009-10-16 17:23:28 +00:00
parent 1d90504a84
commit f04860aa46
5 changed files with 520 additions and 84 deletions

View File

@ -39,10 +39,15 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <semaphore.h>
#include <debug.h>
#include <errno.h>
#include <arch/irq.h>
#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);
}

View File

@ -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 */

View File

@ -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
*

View File

@ -869,7 +869,7 @@ void stm32_spitake(FAR struct spi_dev_s *dev)
* by a signal.
*/
ASSERT(*get_errno_ptr() == EINTR);
ASSERT(errno == EINTR);
}
}

View File

@ -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.
*/