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