summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2009-10-16 18:31:15 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2009-10-16 18:31:15 +0000
commiteb656e4df53bf5104923834a6bc76a113ac6a1fa (patch)
tree47660a7d0e2e9414a1c63f06f966ea23590ea579
parent924ac140ffa79ed26a00b9b8d7e7fd09d7b1002d (diff)
downloadnuttx-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-xnuttx/arch/arm/src/stm32/stm32_dma.c93
-rwxr-xr-xnuttx/arch/arm/src/stm32/stm32_internal.h13
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: