A simple library to access the DMA functionality.
Fork of SimpleDMA by
Revision 1:0b73b00bcee8, committed 2013-12-20
- Comitter:
- Sissors
- Date:
- Fri Dec 20 20:48:17 2013 +0000
- Parent:
- 0:d77ea45fa625
- Child:
- 2:fe2fcaa72434
- Commit message:
- v0.2, KL25, interrupts
Changed in this revision
SimpleDMA.h | Show annotated file Show diff for this revision Revisions of this file |
SimpleDMA_KL25.cpp | Show annotated file Show diff for this revision Revisions of this file |
--- a/SimpleDMA.h Fri Oct 18 07:44:42 2013 +0000 +++ b/SimpleDMA.h Fri Dec 20 20:48:17 2013 +0000 @@ -2,6 +2,7 @@ #define SIMPLEDMA_H #include "mbed.h" +#include "rtos.h" #include "SimpleDMA_KL25.h" @@ -79,28 +80,78 @@ int start(int length); /** -* Set the DMA channel -* -* @param chan - DMA channel to use -*/ -void channel(int chan); - -/** * Is the DMA channel busy * * @return - true if it is busy */ bool isBusy( void ); +/** +* Attach an interrupt upon completion of DMA transfer or error +* +* @param function - function to call upon completion (may be a member function) +*/ +void attach(void (*function)(void)) { + irq_en = function; + _callback.attach(function); + } + +template<typename T> + void attach(T *object, void (T::*member)(void)) { + irq_en = object; + _callback.attach(object, member); + } - +void wait(void) { + id = Thread::gettid(); + this->attach(this, &SimpleDMA::waitCallback); + this->start(8); + Thread::signal_wait(0x1); +} protected: +/** +* Set the DMA channel +* +* @param chan - DMA channel to use +*/ +void channel(int chan); + int setMemory(uint32_t address, int wordsize, bool source, bool autoinc); int _channel; +FunctionPointer _callback; +bool irq_en; +void irq_handler(void); +//IRQ handlers +static SimpleDMA *irq_owner[4]; + +static void irq_handler0( void ) { + if (irq_owner[0]!=NULL) + irq_owner[0]->irq_handler(); +} +static void irq_handler1( void ) { + if (irq_owner[1]!=NULL) + irq_owner[1]->irq_handler(); +} +static void irq_handler2( void ) { + if (irq_owner[2]!=NULL) + irq_owner[2]->irq_handler(); +} +static void irq_handler3( void ) { + if (irq_owner[3]!=NULL) + irq_owner[3]->irq_handler(); +} +public: +osThreadId id; +void waitCallback(void) { + + //id = Thread::gettid(); + osSignalSet(id, 0x1); + +} }; #endif \ No newline at end of file
--- a/SimpleDMA_KL25.cpp Fri Oct 18 07:44:42 2013 +0000 +++ b/SimpleDMA_KL25.cpp Fri Dec 20 20:48:17 2013 +0000 @@ -2,15 +2,41 @@ #define DMA_CHANNELS 4 +SimpleDMA *SimpleDMA::irq_owner[4] = {NULL}; + SimpleDMA::SimpleDMA(int channel) { this->channel(channel); - trigger(Trigger_ALWAYS); - + //Enable DMA SIM->SCGC6 |= 1<<1; //Enable clock to DMA mux SIM->SCGC7 |= 1<<8; //Enable clock to DMA + 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) + + 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; } int SimpleDMA::setMemory(uint32_t address, int wordsize, bool source, bool autoinc) { @@ -56,12 +82,13 @@ }; int SimpleDMA::trigger(SimpleDMA_Trigger trig){ - DMAMUX0->CHCFG[_channel] = 0; + DMAMUX0->CHCFG[_channel] = trig; return 0; } int SimpleDMA::start(int length) { + if (length > 0xFFFFF) return -1; @@ -69,8 +96,13 @@ DMA0->DMA[_channel].DSR_BCR &= ~0xFFFFFF; DMA0->DMA[_channel].DSR_BCR |= length; + //Enable interrupts + if (irq_en) + DMA0->DMA[_channel].DCR |= (uint32_t)(1<<31); + else + DMA0->DMA[_channel].DCR &= ~(1<<31); + //Start - //DMA0->DMA[_channel].DCR|=1<<16; DMAMUX0->CHCFG[_channel] |= 1<<7; return 0; @@ -85,4 +117,10 @@ bool SimpleDMA::isBusy( void ) { return (DMA0->DMA[_channel].DSR_BCR & (1<<25) == 1<<25); -} \ No newline at end of file +} + +void SimpleDMA::irq_handler(void) { + DMAMUX0->CHCFG[_channel] = 0; + DMA0->DMA[0].DSR_BCR |= DMA_DSR_BCR_DONE_MASK ; + _callback.call(); +}