A simple library to access the DMA functionality.

Fork of SimpleDMA by Erik -

Revision:
3:34f5bf8adfa0
Parent:
2:fe2fcaa72434
Child:
4:c3a84c6c432c
--- a/SimpleDMA_KL25.cpp	Sun Dec 22 21:42:49 2013 +0000
+++ b/SimpleDMA_KL25.cpp	Thu Dec 26 12:19:29 2013 +0000
@@ -1,6 +1,6 @@
 #include "SimpleDMA.h"
 
-#define DMA_CHANNELS        4
+
 
 SimpleDMA *SimpleDMA::irq_owner[4] = {NULL};
 
@@ -14,29 +14,15 @@
     trigger(Trigger_ALWAYS);
     
     DCR = (1<<29) + (1<<30);   //Set to always use DMAMUX (If no trigger is needed we route via alwayson)
-
-    uint32_t handler = NULL;
-    switch (_channel) {
-        case 0:
-            handler = (uint32_t)&irq_handler0;
-            break;
-        case 1:
-            handler = (uint32_t)&irq_handler1;
-            break;
-        case 2:
-            handler = (uint32_t)&irq_handler2;
-            break;
-        case 3:
-            handler = (uint32_t)&irq_handler3;
-            break;
-        default:
-            break;
-    }
-
-    NVIC_SetVector((IRQn) (DMA0_IRQn + _channel), handler);
-    NVIC_EnableIRQ((IRQn) (DMA0_IRQn + _channel));
-
-    irq_owner[_channel] = this;
+   
+    NVIC_SetVector(DMA0_IRQn, (uint32_t)&irq_handler0);
+    NVIC_SetVector(DMA1_IRQn, (uint32_t)&irq_handler1);
+    NVIC_SetVector(DMA2_IRQn, (uint32_t)&irq_handler2);
+    NVIC_SetVector(DMA3_IRQn, (uint32_t)&irq_handler3);
+    NVIC_EnableIRQ(DMA0_IRQn);
+    NVIC_EnableIRQ(DMA1_IRQn);
+    NVIC_EnableIRQ(DMA2_IRQn);
+    NVIC_EnableIRQ(DMA3_IRQn);
 }
 
 int SimpleDMA::setAddress(uint32_t address, int wordsize, bool source, bool autoinc) {
@@ -52,6 +38,7 @@
         }
     
     char _size;
+
     switch (wordsize) {
         case 8:
             _size = 1;
@@ -78,6 +65,7 @@
         DCR |= autoinc << 19;
         DCR |= _size << 17;
     }
+
     return 0;
 };
 
@@ -87,15 +75,22 @@
     return 0;
 }
 
+
 int SimpleDMA::start(int length) {
-    while(isBusy());
+    if (auto_channel)
+        _channel = getFreeChannel();
+    else
+        while(isBusy());
+        
     DMA0->DMA[_channel].DSR_BCR |= DMA_DSR_BCR_DONE_MASK ;
     
     if (length > 0xFFFFF)
         return -1;
     
-    if (irq_en)
+    if (irq_en) {
         DCR |= (1UL<<31);
+        irq_owner[_channel] = this;
+        }
     else
         DCR &= ~(1UL<<31);
     
@@ -117,16 +112,25 @@
 }
 
 void SimpleDMA::channel(int chan) {
-    if (chan >= 0 && chan < DMA_CHANNELS)
-        _channel = chan;
-    else
-        _channel = 3;
+    if (chan == -1) {
+        auto_channel = true;
+        _channel = 0;
+    } else {
+        auto_channel = false;
+        if (chan >= 0 && chan < DMA_CHANNELS)
+            _channel = chan;
+        else
+            _channel = 3;
+    }
 }
 
-bool SimpleDMA::isBusy( void ) {
+bool SimpleDMA::isBusy( int channel ) {
     //Busy bit doesn't work as I expect it to do, so just check if counter is at zero
     //return (DMA0->DMA[_channel].DSR_BCR & (1<<25) == 1<<25);
-    return (DMA0->DMA[_channel].DSR_BCR &0xFFFFFF);
+    if (channel == -1)
+        channel = _channel;
+    
+    return (DMA0->DMA[channel].DSR_BCR & 0xFFFFFF);
 }
 
 void SimpleDMA::irq_handler(void) {