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
Sissors 5:d9f46ef80e20 1 #ifdef TARGET_LPC1768
Sissors 5:d9f46ef80e20 2
Sissors 5:d9f46ef80e20 3 #include "SimpleDMA.h"
Sissors 5:d9f46ef80e20 4
Sissors 5:d9f46ef80e20 5 SimpleDMA *SimpleDMA::irq_owner[8] = {NULL};
Sissors 5:d9f46ef80e20 6 LPC_GPDMACH_TypeDef *LPC_GPDMACH[8] = {LPC_GPDMACH0, LPC_GPDMACH1, LPC_GPDMACH2, LPC_GPDMACH3, LPC_GPDMACH4, LPC_GPDMACH5, LPC_GPDMACH6, LPC_GPDMACH7};
Sissors 5:d9f46ef80e20 7 uint32_t getTransferType(SimpleDMA_Trigger trig, uint32_t source, uint32_t destination);
Sissors 5:d9f46ef80e20 8
Sissors 5:d9f46ef80e20 9 SimpleDMA::SimpleDMA(int channel) {
Sissors 5:d9f46ef80e20 10 this->channel(channel);
Sissors 5:d9f46ef80e20 11
Sissors 5:d9f46ef80e20 12 //Power up
Sissors 5:d9f46ef80e20 13 LPC_SC->PCONP |= 1<<29;
Sissors 5:d9f46ef80e20 14 LPC_GPDMA->DMACConfig = 1;
Sissors 5:d9f46ef80e20 15 trigger(Trigger_ALWAYS);
Sissors 5:d9f46ef80e20 16
Sissors 5:d9f46ef80e20 17 NVIC_SetVector(DMA_IRQn, (uint32_t)&irq_handler0);
Sissors 5:d9f46ef80e20 18 NVIC_EnableIRQ(DMA_IRQn);
Sissors 5:d9f46ef80e20 19 }
Sissors 5:d9f46ef80e20 20
marcusbirkin 8:876f3b55e6f5 21 int SimpleDMA::start(uint32_t length) {
Sissors 5:d9f46ef80e20 22 if (auto_channel)
Sissors 5:d9f46ef80e20 23 _channel = getFreeChannel();
Sissors 5:d9f46ef80e20 24 else
Sissors 5:d9f46ef80e20 25 while(isBusy());
Sissors 5:d9f46ef80e20 26
Sissors 5:d9f46ef80e20 27 uint32_t control = (source_inc << 26) | (destination_inc << 27) | (1UL << 31);
Sissors 5:d9f46ef80e20 28 switch (source_size) {
Sissors 5:d9f46ef80e20 29 case 16:
Sissors 5:d9f46ef80e20 30 control |= (1<<18) | (length >> 1);
Sissors 5:d9f46ef80e20 31 break;
Sissors 5:d9f46ef80e20 32 case 32:
Sissors 5:d9f46ef80e20 33 control |= (2<<18) | (length >> 2);
Sissors 5:d9f46ef80e20 34 break;
Sissors 5:d9f46ef80e20 35 default:
Sissors 5:d9f46ef80e20 36 control |= length;
Sissors 5:d9f46ef80e20 37 }
Sissors 5:d9f46ef80e20 38 switch (destination_size) {
Sissors 5:d9f46ef80e20 39 case 16:
Sissors 5:d9f46ef80e20 40 control |= (1<<21);
Sissors 5:d9f46ef80e20 41 break;
Sissors 5:d9f46ef80e20 42 case 32:
Sissors 5:d9f46ef80e20 43 control |= (2<<21);
Sissors 5:d9f46ef80e20 44 break;
Sissors 5:d9f46ef80e20 45 }
Sissors 5:d9f46ef80e20 46
Sissors 5:d9f46ef80e20 47 LPC_GPDMACH[_channel]->DMACCSrcAddr = _source;
Sissors 5:d9f46ef80e20 48 LPC_GPDMACH[_channel]->DMACCDestAddr = _destination;
Sissors 5:d9f46ef80e20 49 LPC_GPDMACH[_channel]->DMACCLLI = 0;
Sissors 5:d9f46ef80e20 50 LPC_GPDMACH[_channel]->DMACCControl = control; //Enable interrupt also
Sissors 5:d9f46ef80e20 51
Sissors 5:d9f46ef80e20 52 irq_owner[_channel] = this;
Sissors 5:d9f46ef80e20 53
Sissors 5:d9f46ef80e20 54 if (_trigger != Trigger_ALWAYS) {
Sissors 5:d9f46ef80e20 55 if (_trigger & 16)
Sissors 5:d9f46ef80e20 56 LPC_SC->DMAREQSEL |= 1 << (_trigger - 24);
Sissors 5:d9f46ef80e20 57 else
Sissors 5:d9f46ef80e20 58 LPC_SC->DMAREQSEL &= ~(1 << (_trigger - 24));
Sissors 5:d9f46ef80e20 59
Sissors 5:d9f46ef80e20 60 LPC_GPDMACH[_channel]->DMACCConfig = ((_trigger & 15) << 1) + ((_trigger & 15) << 6) + (getTransferType(_trigger, _source, _destination) << 11) + (1<<15) +1; //Both parts of the transfer get triggered at same time
Sissors 5:d9f46ef80e20 61 } else
Sissors 5:d9f46ef80e20 62 LPC_GPDMACH[_channel]->DMACCConfig = (getTransferType(_trigger, _source, _destination) << 11) + 1 + (1<<15); //Enable channel
Sissors 5:d9f46ef80e20 63
Sissors 5:d9f46ef80e20 64 return 0;
Sissors 5:d9f46ef80e20 65 }
Sissors 5:d9f46ef80e20 66
Sissors 5:d9f46ef80e20 67 bool SimpleDMA::isBusy( int channel ) {
Sissors 5:d9f46ef80e20 68 if (channel == -1)
Sissors 5:d9f46ef80e20 69 channel = _channel;
Sissors 5:d9f46ef80e20 70 return (LPC_GPDMA->DMACEnbldChns & (1<<channel));
Sissors 5:d9f46ef80e20 71 }
Sissors 5:d9f46ef80e20 72
Sissors 5:d9f46ef80e20 73 void SimpleDMA::irq_handler0(void) {
Sissors 5:d9f46ef80e20 74 while(LPC_GPDMA->DMACIntTCStat != 0) {
Sissors 5:d9f46ef80e20 75
Sissors 5:d9f46ef80e20 76 uint32_t intloc = 31 - __CLZ(LPC_GPDMA->DMACIntTCStat & 0xFF);
Sissors 5:d9f46ef80e20 77 if (irq_owner[intloc]!=NULL)
Sissors 5:d9f46ef80e20 78 irq_owner[intloc]->irq_handler();
Sissors 5:d9f46ef80e20 79 }
Sissors 5:d9f46ef80e20 80 }
Sissors 5:d9f46ef80e20 81
Sissors 5:d9f46ef80e20 82 void SimpleDMA::irq_handler(void) {
Sissors 5:d9f46ef80e20 83 LPC_GPDMA->DMACIntTCClear = 1<<_channel;
Sissors 5:d9f46ef80e20 84 _callback.call();
Sissors 5:d9f46ef80e20 85 }
Sissors 5:d9f46ef80e20 86
BaderP 6:e9ab0bb912c8 87 static inline bool isMemory(uint32_t addr)
BaderP 6:e9ab0bb912c8 88 {
BaderP 6:e9ab0bb912c8 89 return (addr >> 28) == 0 || (addr >> 28) == 1 || ((addr >= 0x2007C000) && (addr < (0x2007C000 + 0x8000)));
BaderP 6:e9ab0bb912c8 90 }
BaderP 6:e9ab0bb912c8 91
Sissors 5:d9f46ef80e20 92 uint32_t getTransferType(SimpleDMA_Trigger trig, uint32_t source, uint32_t destination) {
Sissors 5:d9f46ef80e20 93 //If it is always, simply put it on memory-to-memory
Sissors 5:d9f46ef80e20 94 if (trig == Trigger_ALWAYS)
Sissors 5:d9f46ef80e20 95 return 0;
BaderP 6:e9ab0bb912c8 96 else if (isMemory(source)) { //if source is RAM/Flash
BaderP 6:e9ab0bb912c8 97 if (isMemory(destination)) //if destination is RAM/flash
Sissors 5:d9f46ef80e20 98 return 3; //Return p2p for m2m with a trigger (since I have no idea wtf you are trying to do)
Sissors 5:d9f46ef80e20 99 else
Sissors 5:d9f46ef80e20 100 return 1; //Source is memory, destination is peripheral, so m2p
Sissors 5:d9f46ef80e20 101 }
Sissors 5:d9f46ef80e20 102 else {
BaderP 6:e9ab0bb912c8 103 if (isMemory(destination))
Sissors 5:d9f46ef80e20 104 return 2; //Source is peripheral, destination is memory
Sissors 5:d9f46ef80e20 105 else
Sissors 5:d9f46ef80e20 106 return 3; //Both source and destination are peripherals
Sissors 5:d9f46ef80e20 107 }
Sissors 5:d9f46ef80e20 108
Sissors 5:d9f46ef80e20 109 }
Sissors 5:d9f46ef80e20 110 #endif