A simple library to access the DMA functionality.
Fork of SimpleDMA by
SimpleDMA_KL25.cpp
- Committer:
- Sissors
- Date:
- 2013-12-20
- Revision:
- 1:0b73b00bcee8
- Parent:
- 0:d77ea45fa625
- Child:
- 2:fe2fcaa72434
File content as of revision 1:0b73b00bcee8:
#include "SimpleDMA.h" #define DMA_CHANNELS 4 SimpleDMA *SimpleDMA::irq_owner[4] = {NULL}; SimpleDMA::SimpleDMA(int channel) { this->channel(channel); //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) { //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) { DMA0->DMA[_channel].SAR = address; DMA0->DMA[_channel].DCR &= ~(7<<20); DMA0->DMA[_channel].DCR |= autoinc << 22; DMA0->DMA[_channel].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; } return 0; }; int SimpleDMA::trigger(SimpleDMA_Trigger trig){ DMAMUX0->CHCFG[_channel] = trig; return 0; } int SimpleDMA::start(int length) { if (length > 0xFFFFF) return -1; //Set length 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 DMAMUX0->CHCFG[_channel] |= 1<<7; return 0; } void SimpleDMA::channel(int chan) { if (chan >= 0 && chan < DMA_CHANNELS) _channel = chan; else _channel = 3; } bool SimpleDMA::isBusy( void ) { return (DMA0->DMA[_channel].DSR_BCR & (1<<25) == 1<<25); } void SimpleDMA::irq_handler(void) { DMAMUX0->CHCFG[_channel] = 0; DMA0->DMA[0].DSR_BCR |= DMA_DSR_BCR_DONE_MASK ; _callback.call(); }