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/
SimpleDMA_KL25_46.cpp@7:d3be727fa9d2, 2014-06-27 (annotated)
- Committer:
- Tomo2k
- Date:
- Fri Jun 27 10:12:27 2014 +0000
- Revision:
- 7:d3be727fa9d2
- Child:
- 8:876f3b55e6f5
Added support for KL46
Who changed what in which revision?
User | Revision | Line number | New 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 | |
Tomo2k | 7:d3be727fa9d2 | 4 | |
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) { |
Tomo2k | 7:d3be727fa9d2 | 9 | this->channel(channel); |
Tomo2k | 7:d3be727fa9d2 | 10 | |
Tomo2k | 7:d3be727fa9d2 | 11 | //Enable DMA |
Tomo2k | 7:d3be727fa9d2 | 12 | SIM->SCGC6 |= 1<<1; //Enable clock to DMA mux |
Tomo2k | 7:d3be727fa9d2 | 13 | SIM->SCGC7 |= 1<<8; //Enable clock to DMA |
Tomo2k | 7:d3be727fa9d2 | 14 | |
Tomo2k | 7:d3be727fa9d2 | 15 | trigger(Trigger_ALWAYS); |
Tomo2k | 7:d3be727fa9d2 | 16 | |
Tomo2k | 7:d3be727fa9d2 | 17 | NVIC_SetVector(DMA0_IRQn, (uint32_t)&irq_handler0); |
Tomo2k | 7:d3be727fa9d2 | 18 | NVIC_SetVector(DMA1_IRQn, (uint32_t)&irq_handler1); |
Tomo2k | 7:d3be727fa9d2 | 19 | NVIC_SetVector(DMA2_IRQn, (uint32_t)&irq_handler2); |
Tomo2k | 7:d3be727fa9d2 | 20 | NVIC_SetVector(DMA3_IRQn, (uint32_t)&irq_handler3); |
Tomo2k | 7:d3be727fa9d2 | 21 | NVIC_EnableIRQ(DMA0_IRQn); |
Tomo2k | 7:d3be727fa9d2 | 22 | NVIC_EnableIRQ(DMA1_IRQn); |
Tomo2k | 7:d3be727fa9d2 | 23 | NVIC_EnableIRQ(DMA2_IRQn); |
Tomo2k | 7:d3be727fa9d2 | 24 | NVIC_EnableIRQ(DMA3_IRQn); |
Tomo2k | 7:d3be727fa9d2 | 25 | } |
Tomo2k | 7:d3be727fa9d2 | 26 | |
Tomo2k | 7:d3be727fa9d2 | 27 | |
Tomo2k | 7:d3be727fa9d2 | 28 | int SimpleDMA::start(int length) { |
Tomo2k | 7:d3be727fa9d2 | 29 | if (auto_channel) |
Tomo2k | 7:d3be727fa9d2 | 30 | _channel = getFreeChannel(); |
Tomo2k | 7:d3be727fa9d2 | 31 | else |
Tomo2k | 7:d3be727fa9d2 | 32 | while(isBusy()); |
Tomo2k | 7:d3be727fa9d2 | 33 | |
Tomo2k | 7:d3be727fa9d2 | 34 | if (length > DMA_DSR_BCR_BCR_MASK) |
Tomo2k | 7:d3be727fa9d2 | 35 | return -1; |
Tomo2k | 7:d3be727fa9d2 | 36 | |
Tomo2k | 7:d3be727fa9d2 | 37 | irq_owner[_channel] = this; |
Tomo2k | 7:d3be727fa9d2 | 38 | |
Tomo2k | 7:d3be727fa9d2 | 39 | DMA0->DMA[_channel].SAR = _source; |
Tomo2k | 7:d3be727fa9d2 | 40 | DMA0->DMA[_channel].DAR = _destination; |
Tomo2k | 7:d3be727fa9d2 | 41 | DMA0->DMA[_channel].DSR_BCR = length; |
Tomo2k | 7:d3be727fa9d2 | 42 | DMAMUX0->CHCFG[_channel] = _trigger; |
Tomo2k | 7:d3be727fa9d2 | 43 | |
Tomo2k | 7:d3be727fa9d2 | 44 | 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 | 45 | switch (source_size) { |
Tomo2k | 7:d3be727fa9d2 | 46 | case 8: |
Tomo2k | 7:d3be727fa9d2 | 47 | config |= 1 << DMA_DCR_SSIZE_SHIFT; |
Tomo2k | 7:d3be727fa9d2 | 48 | break; |
Tomo2k | 7:d3be727fa9d2 | 49 | case 16: |
Tomo2k | 7:d3be727fa9d2 | 50 | config |= 2 << DMA_DCR_SSIZE_SHIFT; |
Tomo2k | 7:d3be727fa9d2 | 51 | break; |
Tomo2k | 7:d3be727fa9d2 | 52 | } |
Tomo2k | 7:d3be727fa9d2 | 53 | switch (destination_size) { |
Tomo2k | 7:d3be727fa9d2 | 54 | case 8: |
Tomo2k | 7:d3be727fa9d2 | 55 | config |= 1 << DMA_DCR_DSIZE_SHIFT; |
Tomo2k | 7:d3be727fa9d2 | 56 | break; |
Tomo2k | 7:d3be727fa9d2 | 57 | case 16: |
Tomo2k | 7:d3be727fa9d2 | 58 | config |= 2 << DMA_DCR_DSIZE_SHIFT; |
Tomo2k | 7:d3be727fa9d2 | 59 | break; |
Tomo2k | 7:d3be727fa9d2 | 60 | } |
Tomo2k | 7:d3be727fa9d2 | 61 | |
Tomo2k | 7:d3be727fa9d2 | 62 | DMA0->DMA[_channel].DCR = config; |
Tomo2k | 7:d3be727fa9d2 | 63 | |
Tomo2k | 7:d3be727fa9d2 | 64 | //Start |
Tomo2k | 7:d3be727fa9d2 | 65 | DMAMUX0->CHCFG[_channel] |= 1<<7; |
Tomo2k | 7:d3be727fa9d2 | 66 | |
Tomo2k | 7:d3be727fa9d2 | 67 | return 0; |
Tomo2k | 7:d3be727fa9d2 | 68 | } |
Tomo2k | 7:d3be727fa9d2 | 69 | |
Tomo2k | 7:d3be727fa9d2 | 70 | bool SimpleDMA::isBusy( int channel ) { |
Tomo2k | 7:d3be727fa9d2 | 71 | //Busy bit doesn't work as I expect it to do, so just check if counter is at zero |
Tomo2k | 7:d3be727fa9d2 | 72 | //return (DMA0->DMA[_channel].DSR_BCR & (1<<25) == 1<<25); |
Tomo2k | 7:d3be727fa9d2 | 73 | if (channel == -1) |
Tomo2k | 7:d3be727fa9d2 | 74 | channel = _channel; |
Tomo2k | 7:d3be727fa9d2 | 75 | |
Tomo2k | 7:d3be727fa9d2 | 76 | return (DMA0->DMA[channel].DSR_BCR & 0xFFFFFF); |
Tomo2k | 7:d3be727fa9d2 | 77 | } |
Tomo2k | 7:d3be727fa9d2 | 78 | |
Tomo2k | 7:d3be727fa9d2 | 79 | |
Tomo2k | 7:d3be727fa9d2 | 80 | /*****************************************************************/ |
Tomo2k | 7:d3be727fa9d2 | 81 | void SimpleDMA::irq_handler(void) { |
Tomo2k | 7:d3be727fa9d2 | 82 | DMAMUX0->CHCFG[_channel] = 0; |
Tomo2k | 7:d3be727fa9d2 | 83 | DMA0->DMA[_channel].DSR_BCR |= DMA_DSR_BCR_DONE_MASK ; |
Tomo2k | 7:d3be727fa9d2 | 84 | _callback.call(); |
Tomo2k | 7:d3be727fa9d2 | 85 | } |
Tomo2k | 7:d3be727fa9d2 | 86 | |
Tomo2k | 7:d3be727fa9d2 | 87 | void SimpleDMA::irq_handler0( void ) { |
Tomo2k | 7:d3be727fa9d2 | 88 | if (irq_owner[0]!=NULL) |
Tomo2k | 7:d3be727fa9d2 | 89 | irq_owner[0]->irq_handler(); |
Tomo2k | 7:d3be727fa9d2 | 90 | } |
Tomo2k | 7:d3be727fa9d2 | 91 | |
Tomo2k | 7:d3be727fa9d2 | 92 | void SimpleDMA::irq_handler1( void ) { |
Tomo2k | 7:d3be727fa9d2 | 93 | if (irq_owner[1]!=NULL) |
Tomo2k | 7:d3be727fa9d2 | 94 | irq_owner[1]->irq_handler(); |
Tomo2k | 7:d3be727fa9d2 | 95 | } |
Tomo2k | 7:d3be727fa9d2 | 96 | |
Tomo2k | 7:d3be727fa9d2 | 97 | void SimpleDMA::irq_handler2( void ) { |
Tomo2k | 7:d3be727fa9d2 | 98 | if (irq_owner[2]!=NULL) |
Tomo2k | 7:d3be727fa9d2 | 99 | irq_owner[2]->irq_handler(); |
Tomo2k | 7:d3be727fa9d2 | 100 | } |
Tomo2k | 7:d3be727fa9d2 | 101 | |
Tomo2k | 7:d3be727fa9d2 | 102 | void SimpleDMA::irq_handler3( void ) { |
Tomo2k | 7:d3be727fa9d2 | 103 | if (irq_owner[3]!=NULL) |
Tomo2k | 7:d3be727fa9d2 | 104 | irq_owner[3]->irq_handler(); |
Tomo2k | 7:d3be727fa9d2 | 105 | } |
Tomo2k | 7:d3be727fa9d2 | 106 | #endif |