DMA library for the KL25Z

Dependents:   SimpleDMA_HelloWorld RTOS_SPI spiDMAtest Pinscape_Controller_v1 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SimpleDMA_KL25_46.cpp Source File

SimpleDMA_KL25_46.cpp

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