MODDMA GPDMA Controller New features: transfer pins to memory buffer under periodic timer control and send double buffers to DAC

Dependents:   FirstTest WaveSim IO-dma-memmem DACDMAfuncgenlib ... more

Files at this revision

API Documentation at this revision

Comitter:
AjK
Date:
Tue Nov 23 21:34:21 2010 +0000
Parent:
5:c39b22fa0c60
Child:
7:347110c7aefc
Commit message:
1.3

Changed in this revision

ChangeLog.c Show annotated file Show diff for this revision Revisions of this file
MODDMA.cpp Show annotated file Show diff for this revision Revisions of this file
MODDMA.h Show annotated file Show diff for this revision Revisions of this file
example1.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/ChangeLog.c	Tue Nov 23 16:04:32 2010 +0000
+++ b/ChangeLog.c	Tue Nov 23 21:34:21 2010 +0000
@@ -1,5 +1,14 @@
 /* $Id:$
 
+1.3 - 23/10/2010
+
+    * Added the LLI class wrapper.
+    * Added checking channel's LLI for non-null before auto-disable
+      of a channel with the ISR.
+    * Tested with MODSERIAL which is now natively MODDMA "aware".
+      MODSERIAL can now, using MODDMA, send blocks of bytes out
+      of it's TX port under DMA control.
+        
 1.2 - 23/10/2010
 
     * Improved the IRQ callback attachment API to make 
--- a/MODDMA.cpp	Tue Nov 23 16:04:32 2010 +0000
+++ b/MODDMA.cpp	Tue Nov 23 21:34:21 2010 +0000
@@ -97,9 +97,12 @@
                     // Not, we don't check Active here as it may block inside
                     // an ISR, we just shut it down immediately. If the user
                     // must wait for completion they should implement their
-                    // own ISR.
+                    // own ISR. But only disable if the LLI linked list register
+                    // is null otherwise we can crap out a series of transfers.
                     if (moddma_p->Enabled( (MODDMA::CHANNELS)channel_number )) {
-                        moddma_p->Disable( (MODDMA::CHANNELS)channel_number );
+                        if (moddma_p->lli(channel_number) == 0 ) {
+                            moddma_p->Disable( (MODDMA::CHANNELS)channel_number );
+                        }
                     }
                 }            
             }
@@ -120,9 +123,12 @@
                     // Not, we don't check Active here as it may block inside
                     // an ISR, we just shut it down immediately. If the user
                     // must wait for completion they should implement their
-                    // own ISR.
+                    // own ISR. But only disable if the LLI linked list register
+                    // is null otherwise we can crap out a series of transfers.
                     if (moddma_p->Enabled( (MODDMA::CHANNELS)channel_number )) {
-                        moddma_p->Disable( (MODDMA::CHANNELS)channel_number );
+                        if (moddma_p->lli(channel_number) == 0 ) {
+                            moddma_p->Disable( (MODDMA::CHANNELS)channel_number );
+                        }
                     }
                 }            
             }
--- a/MODDMA.h	Tue Nov 23 16:04:32 2010 +0000
+++ b/MODDMA.h	Tue Nov 23 21:34:21 2010 +0000
@@ -21,7 +21,7 @@
     
     @file          MODDMA.h 
     @purpose       Adds DMA controller and multiple transfer configurations
-    @version       1.2
+    @version       see ChangeLog.c
     @date          Nov 2010
     @author        Andy Kirkham    
 */
@@ -162,14 +162,31 @@
     FunctionPointer *isrIntErrStat;                        
 };
 
- /*
-typedef struct {
+/**
+ * @brief The MODDMA configuration system (linked list items)
+ * @author Andy Kirkham
+ * @see http://mbed.org/cookbook/MODDMA_Config
+ * @see MODDMA
+ * @see MODDMA_Config
+ * @see API 
+ */
+class MODDMA_LLI {
+public:
+    class MODDMA_LLI *srcAddr(uint32_t n) { SrcAddr = n; return this; }
+    class MODDMA_LLI *dstAddr(uint32_t n) { DstAddr = n; return this; }
+    class MODDMA_LLI *nextLLI(uint32_t n) { NextLLI = n; return this; }
+    class MODDMA_LLI *control(uint32_t n) { Control = n; return this; }
+    uint32_t srcAddr(void) { return SrcAddr; }
+    uint32_t dstAddr(void) { return DstAddr; }
+    uint32_t nextLLI(void) { return NextLLI; }
+    uint32_t control(void) { return Control; }
+protected:
     uint32_t SrcAddr;    //!< Source Address 
     uint32_t DstAddr;    //!< Destination address 
     uint32_t NextLLI;    //!< Next LLI address, otherwise set to '0' 
     uint32_t Control;    //!< GPDMA Control of this LLI 
-} GPDMA_LLI_t;
-*/
+};
+
 
 
  /**
@@ -346,6 +363,15 @@
      * Used to setup the DMA controller to prepare for a data transfer.
      *
      * @ingroup API
+     * @param isConstructorCalling Set true when called from teh constructor
+     * @param 
+     */
+    void init(bool isConstructorCalling, int Channels = 0xFF, int Tc = 0xFF, int Err = 0xFF);
+    
+    /**
+     * Used to setup the DMA controller to prepare for a data transfer.
+     *
+     * @ingroup API
      * @param c A pointer to an instance of MODDMA_Config to setup.
      */
     Status Setup(MODDMA_Config *c);
@@ -553,10 +579,10 @@
      * @return this
      */
     template<typename T>
-    class MODDMA_Config * attach_tc(T* tptr, void (T::*mptr)(void)) {  
+    void attach_tc(T* tptr, void (T::*mptr)(void)) {  
         if((mptr != NULL) && (tptr != NULL)) {
             isrIntTCStat.attach(tptr, mptr);         
-        }
+        }        
     }
        
     /**
@@ -572,7 +598,7 @@
      * @return this
      */
     void attach_err(void (*fptr)(void)) {  
-        isrIntErrStat.attach(fptr);         
+        isrIntErrStat.attach(fptr);                 
     }
     
     /**
@@ -584,21 +610,30 @@
      * @return this
      */
     template<typename T>
-    class MODDMA_Config * attach_err(T* tptr, void (T::*mptr)(void)) {  
+    void attach_err(T* tptr, void (T::*mptr)(void)) {  
         if((mptr != NULL) && (tptr != NULL)) {
             isrIntErrStat.attach(tptr, mptr);         
         }
     }
     
     /**
+     * Get the Linked List index regsiter for the requested channel.
+     *
+     * @param channelNum The channel number.
+     * @return uint32_t The valie of the DMACCLLI register
+     */
+    uint32_t lli(int channelNum) { 
+        LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( channelNum & 0x7 );
+        return pChannel->DMACCLLI; 
+    }
+    
+    /**
      * The MODDMA controllers error interrupt callback.
      */
     FunctionPointer isrIntErrStat;                        
     
 protected:
-
-    void init(bool isConstructorCalling, int Channels = 0xFF, int Tc = 0xFF, int Err = 0xFF);
-    
+   
     // Data LUTs.
     uint32_t LUTPerAddr(int n);
     uint8_t  LUTPerBurst(int n);
--- a/example1.cpp	Tue Nov 23 16:04:32 2010 +0000
+++ b/example1.cpp	Tue Nov 23 21:34:21 2010 +0000
@@ -2,13 +2,14 @@
 
 #include "mbed.h"
 #include "MODDMA.h"
+#include "MODSERIAL.h"
 
 DigitalOut led1(LED1);
 DigitalOut led2(LED2);
 DigitalOut led3(LED3);
 DigitalOut led4(LED4);
 MODDMA dma;
-Serial pc(USBTX, USBRX);
+MODSERIAL pc(USBTX, USBRX);
 
 // Function prototypes for IRQ callbacks.
 // See definitions following main() below.