Add function to 1) wait for a free channel, and 2) free a DMA channel

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2144 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2009-10-16 18:31:15 +00:00
parent 522251ef65
commit 842fe8c9ab
2 changed files with 74 additions and 32 deletions

View File

@ -40,6 +40,7 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <semaphore.h>
#include <debug.h>
#include <errno.h>
@ -71,20 +72,13 @@
* 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 */
sem_t sem; /* Used to wait for DMA channel to become available */
uint32 base; /* DMA register channel base address */
dma_callback_t callback; /* Callback invoked when the DMA completes */
};
@ -93,11 +87,6 @@ struct stm32_dma_s
* 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] =
@ -202,6 +191,33 @@ static inline void dmachan_putreg(struct stm32_dma_s *dmach, uint32 offset, uint
putreg32(value, dmach->base + offset);
}
/************************************************************************************
* Name: stm32_dmatake() and stm32_dmagive()
*
* Description:
* Used to get exclusive access to a DMA channel.
*
************************************************************************************/
static void stm32_dmatake(FAR struct stm32_dma_s *dmach)
{
/* Take the semaphore (perhaps waiting) */
while (sem_wait(&dmach->sem) != 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(FAR struct stm32_dma_s *dmach)
{
(void)sem_post(&dmach->sem);
}
/************************************************************************************
* Name: stm32_dmainterrupt
*
@ -275,6 +291,7 @@ void weak_function stm32_dmainitialize(void)
for (chan = 0; chan < DMA_NCHANNELS; chan++)
{
sem_init(&g_dma[chan].sem, 0, 1);
irq_attach(g_dma[chan].irq, stm32_dmainterrupt);
}
}
@ -292,35 +309,47 @@ void weak_function stm32_dmainitialize(void)
DMA_HANDLE stm32_dmachannel(int chan)
{
struct stm32_dma_s *dmach = NULL;
irqstate_t flags;
dma_bitset_t before;
int bit = (1 << chan);
struct stm32_dma_s *dmach = &g_dma[chan];
DEBUGASSERT(chan < DMA_NCHANNELS);
/* This is essentially a test and set. We simply disable interrupts to
* create the critical section. This is brutal (but very quich) and assures
* that we have exclusive access to the allocation bitset
/* Get exclusive access to the DMA channel -- OR wait until the channel
* is available if it is currently being used by another driver
*/
flags = irqsave();
before = g_dmaallocated;
g_dmaallocated |= bit;
irq_restore(flags);
stm32_dmatake(dmach);
/* Was this channel been available? */
/* The caller now has exclusive use of the DMA channel */
if ((before & bit) == 0)
{
/* Yes.. then the caller has it, return it */
dmach = &g_dma[chan];
}
return (DMA_HANDLE)dmach;
}
/****************************************************************************
* Name: stm32_dmarelease
*
* Description:
* Release a DMA channel
*
* Returned Value:
* None
*
* Assumptions:
* - The caller holds the DMA channel.
* - There is no DMA in progress
*
****************************************************************************/
void stm32_dmafree(DMA_HANDLE handle)
{
struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle;
DEBUGASSERT(handle != NULL);
/* Release the channel */
stm32_dmagive(dmach);
}
/****************************************************************************
* Name: stm32_dmasetup
*

View File

@ -503,6 +503,19 @@ EXTERN void weak_function stm32_dmainitialize(void);
EXTERN DMA_HANDLE stm32_dmachannel(int chan);
/****************************************************************************
* Name: stm32_dmarelease
*
* Description:
* Release a DMA channel
*
* Returned Value:
* None
*
****************************************************************************/
EXTERN void stm32_dmafree(DMA_HANDLE handle);
/****************************************************************************
* Name: stm32_dmasetup
*