diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2009-10-16 18:31:15 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2009-10-16 18:31:15 +0000 |
commit | eb656e4df53bf5104923834a6bc76a113ac6a1fa (patch) | |
tree | 47660a7d0e2e9414a1c63f06f966ea23590ea579 | |
parent | 924ac140ffa79ed26a00b9b8d7e7fd09d7b1002d (diff) | |
download | nuttx-eb656e4df53bf5104923834a6bc76a113ac6a1fa.tar.gz nuttx-eb656e4df53bf5104923834a6bc76a113ac6a1fa.tar.bz2 nuttx-eb656e4df53bf5104923834a6bc76a113ac6a1fa.zip |
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
-rwxr-xr-x | nuttx/arch/arm/src/stm32/stm32_dma.c | 93 | ||||
-rwxr-xr-x | nuttx/arch/arm/src/stm32/stm32_internal.h | 13 |
2 files changed, 74 insertions, 32 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_dma.c b/nuttx/arch/arm/src/stm32/stm32_dma.c index f456d458e..961c498c7 100755 --- a/nuttx/arch/arm/src/stm32/stm32_dma.c +++ b/nuttx/arch/arm/src/stm32/stm32_dma.c @@ -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] = @@ -203,6 +192,33 @@ static inline void dmachan_putreg(struct stm32_dma_s *dmach, uint32 offset, uint } /************************************************************************************ + * 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 * * Description: @@ -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,36 +309,48 @@ 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 * * Description: diff --git a/nuttx/arch/arm/src/stm32/stm32_internal.h b/nuttx/arch/arm/src/stm32/stm32_internal.h index 61169e7b5..ec5aa5822 100755 --- a/nuttx/arch/arm/src/stm32/stm32_internal.h +++ b/nuttx/arch/arm/src/stm32/stm32_internal.h @@ -504,6 +504,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 * * Description: |