DMA library for the KL25Z

Dependents:   SimpleDMA_HelloWorld RTOS_SPI spiDMAtest Pinscape_Controller_v1 ... more

Introduction

SimpleDMA is a standard library for different DMA peripherals. Currently the LPC1768, KL46Z and KL25Z are supported. It provided one set of functions for different peripherals. It does not allow for usage of all the advanced functions, partially because the goal was to provide a simple interface, and partially because they are different for different microcontrollers.

Examples

Helloworld: http://mbed.org/users/Sissors/code/SimpleDMA_HelloWorld/

Example in a library (SPI): http://mbed.org/users/Sissors/code/RTOS_SPI/

Committer:
wkleunen
Date:
Fri May 12 10:26:15 2017 +0000
Revision:
9:f7345d41b076
Parent:
8:876f3b55e6f5
Use callback template class to integrate library with mbed os 5.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Tomo2k 7:d3be727fa9d2 1 #if defined TARGET_KL25Z || defined TARGET_KL46Z
Tomo2k 7:d3be727fa9d2 2 #include "SimpleDMA.h"
Tomo2k 7:d3be727fa9d2 3
wkleunen 9:f7345d41b076 4 static void donothing(int) { }
Tomo2k 7:d3be727fa9d2 5
Tomo2k 7:d3be727fa9d2 6 SimpleDMA *SimpleDMA::irq_owner[4] = {NULL};
Tomo2k 7:d3be727fa9d2 7
Tomo2k 7:d3be727fa9d2 8 SimpleDMA::SimpleDMA(int channel) {
wkleunen 9:f7345d41b076 9 _callback = donothing;
Tomo2k 7:d3be727fa9d2 10 this->channel(channel);
Tomo2k 7:d3be727fa9d2 11
Tomo2k 7:d3be727fa9d2 12 //Enable DMA
Tomo2k 7:d3be727fa9d2 13 SIM->SCGC6 |= 1<<1; //Enable clock to DMA mux
Tomo2k 7:d3be727fa9d2 14 SIM->SCGC7 |= 1<<8; //Enable clock to DMA
Tomo2k 7:d3be727fa9d2 15
Tomo2k 7:d3be727fa9d2 16 trigger(Trigger_ALWAYS);
Tomo2k 7:d3be727fa9d2 17
Tomo2k 7:d3be727fa9d2 18 NVIC_SetVector(DMA0_IRQn, (uint32_t)&irq_handler0);
Tomo2k 7:d3be727fa9d2 19 NVIC_SetVector(DMA1_IRQn, (uint32_t)&irq_handler1);
Tomo2k 7:d3be727fa9d2 20 NVIC_SetVector(DMA2_IRQn, (uint32_t)&irq_handler2);
Tomo2k 7:d3be727fa9d2 21 NVIC_SetVector(DMA3_IRQn, (uint32_t)&irq_handler3);
Tomo2k 7:d3be727fa9d2 22 NVIC_EnableIRQ(DMA0_IRQn);
Tomo2k 7:d3be727fa9d2 23 NVIC_EnableIRQ(DMA1_IRQn);
Tomo2k 7:d3be727fa9d2 24 NVIC_EnableIRQ(DMA2_IRQn);
Tomo2k 7:d3be727fa9d2 25 NVIC_EnableIRQ(DMA3_IRQn);
Tomo2k 7:d3be727fa9d2 26 }
Tomo2k 7:d3be727fa9d2 27
Tomo2k 7:d3be727fa9d2 28
marcusbirkin 8:876f3b55e6f5 29 int SimpleDMA::start(uint32_t length) {
Tomo2k 7:d3be727fa9d2 30 if (auto_channel)
Tomo2k 7:d3be727fa9d2 31 _channel = getFreeChannel();
Tomo2k 7:d3be727fa9d2 32 else
Tomo2k 7:d3be727fa9d2 33 while(isBusy());
Tomo2k 7:d3be727fa9d2 34
Tomo2k 7:d3be727fa9d2 35 if (length > DMA_DSR_BCR_BCR_MASK)
Tomo2k 7:d3be727fa9d2 36 return -1;
Tomo2k 7:d3be727fa9d2 37
Tomo2k 7:d3be727fa9d2 38 irq_owner[_channel] = this;
Tomo2k 7:d3be727fa9d2 39
Tomo2k 7:d3be727fa9d2 40 DMA0->DMA[_channel].SAR = _source;
Tomo2k 7:d3be727fa9d2 41 DMA0->DMA[_channel].DAR = _destination;
Tomo2k 7:d3be727fa9d2 42 DMA0->DMA[_channel].DSR_BCR = length;
Tomo2k 7:d3be727fa9d2 43 DMAMUX0->CHCFG[_channel] = _trigger;
Tomo2k 7:d3be727fa9d2 44
Tomo2k 7:d3be727fa9d2 45 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);
Tomo2k 7:d3be727fa9d2 46 switch (source_size) {
Tomo2k 7:d3be727fa9d2 47 case 8:
Tomo2k 7:d3be727fa9d2 48 config |= 1 << DMA_DCR_SSIZE_SHIFT;
Tomo2k 7:d3be727fa9d2 49 break;
Tomo2k 7:d3be727fa9d2 50 case 16:
Tomo2k 7:d3be727fa9d2 51 config |= 2 << DMA_DCR_SSIZE_SHIFT;
Tomo2k 7:d3be727fa9d2 52 break;
Tomo2k 7:d3be727fa9d2 53 }
Tomo2k 7:d3be727fa9d2 54 switch (destination_size) {
Tomo2k 7:d3be727fa9d2 55 case 8:
Tomo2k 7:d3be727fa9d2 56 config |= 1 << DMA_DCR_DSIZE_SHIFT;
Tomo2k 7:d3be727fa9d2 57 break;
Tomo2k 7:d3be727fa9d2 58 case 16:
Tomo2k 7:d3be727fa9d2 59 config |= 2 << DMA_DCR_DSIZE_SHIFT;
Tomo2k 7:d3be727fa9d2 60 break;
Tomo2k 7:d3be727fa9d2 61 }
Tomo2k 7:d3be727fa9d2 62
Tomo2k 7:d3be727fa9d2 63 DMA0->DMA[_channel].DCR = config;
Tomo2k 7:d3be727fa9d2 64
Tomo2k 7:d3be727fa9d2 65 //Start
Tomo2k 7:d3be727fa9d2 66 DMAMUX0->CHCFG[_channel] |= 1<<7;
Tomo2k 7:d3be727fa9d2 67
Tomo2k 7:d3be727fa9d2 68 return 0;
Tomo2k 7:d3be727fa9d2 69 }
Tomo2k 7:d3be727fa9d2 70
Tomo2k 7:d3be727fa9d2 71 bool SimpleDMA::isBusy( int channel ) {
Tomo2k 7:d3be727fa9d2 72 //Busy bit doesn't work as I expect it to do, so just check if counter is at zero
Tomo2k 7:d3be727fa9d2 73 //return (DMA0->DMA[_channel].DSR_BCR & (1<<25) == 1<<25);
Tomo2k 7:d3be727fa9d2 74 if (channel == -1)
Tomo2k 7:d3be727fa9d2 75 channel = _channel;
Tomo2k 7:d3be727fa9d2 76
Tomo2k 7:d3be727fa9d2 77 return (DMA0->DMA[channel].DSR_BCR & 0xFFFFFF);
Tomo2k 7:d3be727fa9d2 78 }
Tomo2k 7:d3be727fa9d2 79
Tomo2k 7:d3be727fa9d2 80 /*****************************************************************/
Tomo2k 7:d3be727fa9d2 81 void SimpleDMA::irq_handler(void) {
wkleunen 9:f7345d41b076 82 Callback<void(int)> func = _callback;
wkleunen 9:f7345d41b076 83 _callback = donothing;
wkleunen 9:f7345d41b076 84
Tomo2k 7:d3be727fa9d2 85 DMAMUX0->CHCFG[_channel] = 0;
Tomo2k 7:d3be727fa9d2 86 DMA0->DMA[_channel].DSR_BCR |= DMA_DSR_BCR_DONE_MASK ;
wkleunen 9:f7345d41b076 87
wkleunen 9:f7345d41b076 88 func(_channel);
Tomo2k 7:d3be727fa9d2 89 }
Tomo2k 7:d3be727fa9d2 90
Tomo2k 7:d3be727fa9d2 91 void SimpleDMA::irq_handler0( void ) {
Tomo2k 7:d3be727fa9d2 92 if (irq_owner[0]!=NULL)
Tomo2k 7:d3be727fa9d2 93 irq_owner[0]->irq_handler();
Tomo2k 7:d3be727fa9d2 94 }
Tomo2k 7:d3be727fa9d2 95
Tomo2k 7:d3be727fa9d2 96 void SimpleDMA::irq_handler1( void ) {
Tomo2k 7:d3be727fa9d2 97 if (irq_owner[1]!=NULL)
Tomo2k 7:d3be727fa9d2 98 irq_owner[1]->irq_handler();
Tomo2k 7:d3be727fa9d2 99 }
Tomo2k 7:d3be727fa9d2 100
Tomo2k 7:d3be727fa9d2 101 void SimpleDMA::irq_handler2( void ) {
Tomo2k 7:d3be727fa9d2 102 if (irq_owner[2]!=NULL)
Tomo2k 7:d3be727fa9d2 103 irq_owner[2]->irq_handler();
Tomo2k 7:d3be727fa9d2 104 }
Tomo2k 7:d3be727fa9d2 105
Tomo2k 7:d3be727fa9d2 106 void SimpleDMA::irq_handler3( void ) {
Tomo2k 7:d3be727fa9d2 107 if (irq_owner[3]!=NULL)
Tomo2k 7:d3be727fa9d2 108 irq_owner[3]->irq_handler();
Tomo2k 7:d3be727fa9d2 109 }
Tomo2k 7:d3be727fa9d2 110 #endif