A simple library to access the DMA functionality.
Fork of SimpleDMA by
Diff: SimpleDMA_KL25.cpp
- 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) {