A simple library to access the DMA functionality.

Fork of SimpleDMA by Erik -

Revision:
2:fe2fcaa72434
Parent:
1:0b73b00bcee8
Child:
3:34f5bf8adfa0
--- a/SimpleDMA_KL25.cpp	Fri Dec 20 20:48:17 2013 +0000
+++ b/SimpleDMA_KL25.cpp	Sun Dec 22 21:42:49 2013 +0000
@@ -13,7 +13,7 @@
     
     trigger(Trigger_ALWAYS);
     
-    DMA0->DMA[_channel].DCR |= (1<<29) + (1<<30);   //Set to always use DMAMUX (If no trigger is needed we route via alwayson)
+    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) {
@@ -39,7 +39,7 @@
     irq_owner[_channel] = this;
 }
 
-int SimpleDMA::setMemory(uint32_t address, int wordsize, bool source, bool autoinc) {
+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:
@@ -68,39 +68,47 @@
     
     //Check if source or destination
     if (source) {
-        DMA0->DMA[_channel].SAR = address;
-        DMA0->DMA[_channel].DCR &= ~(7<<20);
-        DMA0->DMA[_channel].DCR |= autoinc << 22;
-        DMA0->DMA[_channel].DCR |= _size << 20;
+        SAR = address;
+        DCR &= ~(7<<20);
+        DCR |= autoinc << 22;
+        DCR |= _size << 20;
     } else {
-        DMA0->DMA[_channel].DAR = address;
-        DMA0->DMA[_channel].DCR &= ~(7<<17);
-        DMA0->DMA[_channel].DCR |= autoinc << 19;
-        DMA0->DMA[_channel].DCR |= _size << 17;
+        DAR = address;
+        DCR &= ~(7<<17);
+        DCR |= autoinc << 19;
+        DCR |= _size << 17;
     }
     return 0;
 };
 
 int SimpleDMA::trigger(SimpleDMA_Trigger trig){ 
     
-    DMAMUX0->CHCFG[_channel] = trig;
+    CHCFG = trig;
     return 0;
 }
 
 int SimpleDMA::start(int length) {
-
+    while(isBusy());
+    DMA0->DMA[_channel].DSR_BCR |= DMA_DSR_BCR_DONE_MASK ;
+    
     if (length > 0xFFFFF)
         return -1;
     
-    //Set length
-    DMA0->DMA[_channel].DSR_BCR &= ~0xFFFFFF;
-    DMA0->DMA[_channel].DSR_BCR |= length;
+    if (irq_en)
+        DCR |= (1UL<<31);
+    else
+        DCR &= ~(1UL<<31);
     
-    //Enable interrupts
-    if (irq_en)
-        DMA0->DMA[_channel].DCR |= (uint32_t)(1<<31);
-    else
-        DMA0->DMA[_channel].DCR &= ~(1<<31);
+    //Set registers:
+    DMA0->DMA[_channel].SAR = SAR;
+    DMA0->DMA[_channel].DAR = DAR;
+    DMA0->DMA[_channel].DCR = DCR;
+    
+    //Set trigger
+    DMAMUX0->CHCFG[_channel] = CHCFG;
+    
+    //Set length
+    DMA0->DMA[_channel].DSR_BCR = length;
         
     //Start
     DMAMUX0->CHCFG[_channel] |= 1<<7;
@@ -116,11 +124,13 @@
 }
 
 bool SimpleDMA::isBusy( void ) {
-    return (DMA0->DMA[_channel].DSR_BCR & (1<<25) == 1<<25);
+    //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);
 }
 
 void SimpleDMA::irq_handler(void) {
     DMAMUX0->CHCFG[_channel] = 0;
-    DMA0->DMA[0].DSR_BCR |= DMA_DSR_BCR_DONE_MASK ; 
+    DMA0->DMA[_channel].DSR_BCR |= DMA_DSR_BCR_DONE_MASK ; 
     _callback.call();
 }