A simple library to access the DMA functionality.

Fork of SimpleDMA by Erik -

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SimpleDMA_KL25.cpp Source File

SimpleDMA_KL25.cpp

00001 #ifdef TARGET_KL25Z
00002 #include "SimpleDMA.h"
00003 
00004 
00005 
00006 SimpleDMA *SimpleDMA::irq_owner[4] = {NULL};
00007 
00008 SimpleDMA::SimpleDMA(int channel) {
00009     this->channel(channel);
00010        
00011     //Enable DMA
00012     SIM->SCGC6 |= 1<<1;     //Enable clock to DMA mux
00013     SIM->SCGC7 |= 1<<8;     //Enable clock to DMA
00014     
00015     trigger(Trigger_ALWAYS);
00016    
00017     NVIC_SetVector(DMA0_IRQn, (uint32_t)&irq_handler0);
00018     NVIC_SetVector(DMA1_IRQn, (uint32_t)&irq_handler1);
00019     NVIC_SetVector(DMA2_IRQn, (uint32_t)&irq_handler2);
00020     NVIC_SetVector(DMA3_IRQn, (uint32_t)&irq_handler3);
00021     NVIC_EnableIRQ(DMA0_IRQn);
00022     NVIC_EnableIRQ(DMA1_IRQn);
00023     NVIC_EnableIRQ(DMA2_IRQn);
00024     NVIC_EnableIRQ(DMA3_IRQn);
00025 }
00026 
00027 
00028 int SimpleDMA::start(int length) {  
00029     if (auto_channel)
00030         _channel = getFreeChannel();
00031     else
00032         while(isBusy());
00033     
00034     if (length > DMA_DSR_BCR_BCR_MASK)
00035         return -1;
00036 
00037     irq_owner[_channel] = this;
00038     
00039     DMA0->DMA[_channel].SAR = _source;
00040     DMA0->DMA[_channel].DAR = _destination;
00041     DMA0->DMA[_channel].DSR_BCR = length;
00042     DMAMUX0->CHCFG[_channel] = _trigger;
00043     
00044     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);
00045     switch (source_size) {
00046         case 8:
00047             config |= 1 << DMA_DCR_SSIZE_SHIFT;
00048             break;
00049         case 16:
00050             config |= 2 << DMA_DCR_SSIZE_SHIFT; 
00051             break;
00052     }
00053     switch (destination_size) {
00054         case 8:
00055             config |= 1 << DMA_DCR_DSIZE_SHIFT;
00056             break;
00057         case 16:
00058             config |= 2 << DMA_DCR_DSIZE_SHIFT; 
00059             break;
00060     }
00061     
00062     DMA0->DMA[_channel].DCR = config;      
00063            
00064     //Start
00065     DMAMUX0->CHCFG[_channel] |= 1<<7;
00066     
00067     return 0;
00068 }
00069 
00070 bool SimpleDMA::isBusy( int channel ) {
00071     //Busy bit doesn't work as I expect it to do, so just check if counter is at zero
00072     //return (DMA0->DMA[_channel].DSR_BCR & (1<<25) == 1<<25);
00073     if (channel == -1)
00074         channel = _channel;
00075     
00076     return (DMA0->DMA[channel].DSR_BCR & 0xFFFFFF);
00077 }
00078 
00079 
00080 /*****************************************************************/
00081 void SimpleDMA::irq_handler(void) {
00082     DMAMUX0->CHCFG[_channel] = 0;
00083     DMA0->DMA[_channel].DSR_BCR |= DMA_DSR_BCR_DONE_MASK ; 
00084     _callback.call();
00085 }
00086 
00087 void SimpleDMA::irq_handler0( void ) {
00088     if (irq_owner[0]!=NULL)
00089         irq_owner[0]->irq_handler();
00090 }
00091 
00092 void SimpleDMA::irq_handler1( void ) {
00093     if (irq_owner[1]!=NULL)
00094         irq_owner[1]->irq_handler();
00095 }
00096 
00097 void SimpleDMA::irq_handler2( void ) {
00098     if (irq_owner[2]!=NULL)
00099         irq_owner[2]->irq_handler();
00100 }
00101 
00102 void SimpleDMA::irq_handler3( void ) {
00103     if (irq_owner[3]!=NULL)
00104         irq_owner[3]->irq_handler();
00105 }
00106 #endif