A simple library to access the DMA functionality.

Fork of SimpleDMA by Erik -

Revision:
5:d9f46ef80e20
Parent:
4:c3a84c6c432c
--- a/SimpleDMA_KL25.cpp	Thu Dec 26 16:31:54 2013 +0000
+++ b/SimpleDMA_KL25.cpp	Sat Jan 04 14:42:33 2014 +0000
@@ -1,3 +1,4 @@
+#ifdef TARGET_KL25Z
 #include "SimpleDMA.h"
 
 
@@ -12,8 +13,6 @@
     SIM->SCGC7 |= 1<<8;     //Enable clock to DMA
     
     trigger(Trigger_ALWAYS);
-    
-    DCR = (1<<29) + (1<<30);   //Set to always use DMAMUX (If no trigger is needed we route via alwayson)
    
     NVIC_SetVector(DMA0_IRQn, (uint32_t)&irq_handler0);
     NVIC_SetVector(DMA1_IRQn, (uint32_t)&irq_handler1);
@@ -25,56 +24,6 @@
     NVIC_EnableIRQ(DMA3_IRQn);
 }
 
-int SimpleDMA::setAddress(uint32_t address, int wordsize, bool source, bool autoinc) {
-    //Check if it is an allowed address
-    switch ((uint32_t) address >> 20) {
-        case 0x000:
-        case 0x1FF:
-        case 0x200:
-        case 0x400:
-        break;
-        default:
-            return -1;
-        }
-    
-    char _size;
-
-    switch (wordsize) {
-        case 8:
-            _size = 1;
-            break;
-        case 16:
-            _size = 2;
-            break;
-        case 32:
-            _size = 0;
-            break;
-        default:
-            _size = 1;
-        }
-    
-    //Check if source or destination
-    if (source) {
-        SAR = address;
-        DCR &= ~(7<<20);
-        DCR |= autoinc << 22;
-        DCR |= _size << 20;
-    } else {
-        DAR = address;
-        DCR &= ~(7<<17);
-        DCR |= autoinc << 19;
-        DCR |= _size << 17;
-    }
-
-    return 0;
-};
-
-int SimpleDMA::trigger(SimpleDMA_Trigger trig){ 
-    
-    CHCFG = trig;
-    return 0;
-}
-
 
 int SimpleDMA::start(int length) {  
     if (auto_channel)
@@ -82,42 +31,42 @@
     else
         while(isBusy());
     
-    if (length > 0xFFFFF)
+    if (length > DMA_DSR_BCR_BCR_MASK)
         return -1;
 
-    DCR |= (1UL<<31);
-        irq_owner[_channel] = this;
+    irq_owner[_channel] = this;
+    
+    DMA0->DMA[_channel].SAR = _source;
+    DMA0->DMA[_channel].DAR = _destination;
+    DMA0->DMA[_channel].DSR_BCR = length;
+    DMAMUX0->CHCFG[_channel] = _trigger;
     
-    //Set registers:
-    DMA0->DMA[_channel].SAR = SAR;
-    DMA0->DMA[_channel].DAR = DAR;
-    DMA0->DMA[_channel].DCR = DCR;
+    uint32_t config = DMA_DCR_EINT_MASK | DMA_DCR_ERQ_MASK | DMA_DCR_CS_MASK | (source_inc << DMA_DCR_SINC_SHIFT) | (destination_inc << DMA_DCR_DINC_SHIFT);
+    switch (source_size) {
+        case 8:
+            config |= 1 << DMA_DCR_SSIZE_SHIFT;
+            break;
+        case 16:
+            config |= 2 << DMA_DCR_SSIZE_SHIFT; 
+            break;
+    }
+    switch (destination_size) {
+        case 8:
+            config |= 1 << DMA_DCR_DSIZE_SHIFT;
+            break;
+        case 16:
+            config |= 2 << DMA_DCR_DSIZE_SHIFT; 
+            break;
+    }
     
-    //Set trigger
-    DMAMUX0->CHCFG[_channel] = CHCFG;
-    
-    //Set length
-    DMA0->DMA[_channel].DSR_BCR = length;
-        
+    DMA0->DMA[_channel].DCR = config;      
+           
     //Start
     DMAMUX0->CHCFG[_channel] |= 1<<7;
     
     return 0;
 }
 
-void SimpleDMA::channel(int chan) {
-    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( 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);
@@ -127,8 +76,31 @@
     return (DMA0->DMA[channel].DSR_BCR & 0xFFFFFF);
 }
 
+
+/*****************************************************************/
 void SimpleDMA::irq_handler(void) {
     DMAMUX0->CHCFG[_channel] = 0;
     DMA0->DMA[_channel].DSR_BCR |= DMA_DSR_BCR_DONE_MASK ; 
     _callback.call();
 }
+
+void SimpleDMA::irq_handler0( void ) {
+    if (irq_owner[0]!=NULL)
+        irq_owner[0]->irq_handler();
+}
+
+void SimpleDMA::irq_handler1( void ) {
+    if (irq_owner[1]!=NULL)
+        irq_owner[1]->irq_handler();
+}
+
+void SimpleDMA::irq_handler2( void ) {
+    if (irq_owner[2]!=NULL)
+        irq_owner[2]->irq_handler();
+}
+
+void SimpleDMA::irq_handler3( void ) {
+    if (irq_owner[3]!=NULL)
+        irq_owner[3]->irq_handler();
+}
+#endif
\ No newline at end of file