Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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();
}
