From 8d8305d76c7b217870e948ae67f73b9e32f4f3f2 Mon Sep 17 00:00:00 2001
From: patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>
Date: Sun, 28 Mar 2010 16:25:48 +0000
Subject: [PATCH] A little more DMA logic

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2559 42af7a65-404d-4744-a932-0658087f49c3
---
 arch/arm/src/sam3u/sam3u_dmac.c | 56 ++++++++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/arch/arm/src/sam3u/sam3u_dmac.c b/arch/arm/src/sam3u/sam3u_dmac.c
index 7a686ca153..e97d4d0a53 100755
--- a/arch/arm/src/sam3u/sam3u_dmac.c
+++ b/arch/arm/src/sam3u/sam3u_dmac.c
@@ -76,6 +76,7 @@ struct sam3u_dma_s
   void             *arg;        /* Argument passed to callback function */
   uint16_t          bufsize;    /* Transfer buffer size in bytes */
   volatile uint16_t remaining;  /* Total number of bytes remaining to be transferred */
+  int               result;     /* Transfer result (OK or negated errno) */
 };
 
 /****************************************************************************
@@ -364,7 +365,60 @@ static inline void sam3u_flowcontrol(struct sam3u_dma_s *dmach, uint32_t setting
 
 static int sam3u_dmainterrupt(int irq, void *context)
 {
-# warning "Missing logic"
+ struct sam3u_dma_s *dmach;
+  unsigned int chndx;
+  uint32_t regval;
+
+  /* Get the DMAC status register value */
+
+  regval = getreg32(SAM3U_DMAC_EBCISR);
+
+  /* Check if the any buffer transfer has completed */
+
+  if (regval & DMAC_EBC_BTC_MASK)
+    {
+      /* Check each channel status */
+
+      for (chndx = 0; chndx < DMA_CHANNEL_NUM; chndx++)
+        {
+          /* Are interrupts enabled for this channel? */
+
+          if ((regval & DMAC_EBC_BTC(chndx)) != 0)
+            {
+              /* Subtract the number of bytes transferred so far */
+             
+              dmach->remaining -= dmach->bufsize;
+
+              /* Is the transfer finished? */
+
+              if (dmach->remaining == 0)
+               {
+                  /* Disable Buffer Transfer Complete interrupts */
+
+                  dmach = &g_dma[chndx];
+                  putreg32(DMAC_EBC_BTC(dmach->chan), SAM3U_DMAC_EBCIDR);
+
+                  /* Disable the DMA channel */
+
+                  putreg32(DMAC_CHDR_DIS(dmach->chan), SAM3U_DMAC_CHDR);
+ 
+                  /* Perform the DMA complete callback */
+
+                  if (dmach->callback)
+                    {
+                      dmach->callback(dmach->arg);
+                    }
+                }
+              else
+                {
+                  /* Write the KEEPON field to clear the STALL states */
+
+                  putreg32(DMAC_CHER_KEEP(dmach->chan), SAM3U_DMAC_CHER);
+                }
+            }
+        }
+    }
+  return OK;
 }
 
 /****************************************************************************
-- 
GitLab