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:
Sissors
Date:
Sat Jan 04 14:42:33 2014 +0000
Revision:
5:d9f46ef80e20
Parent:
4:c3a84c6c432c
Child:
7:d3be727fa9d2
Refactored code, added LPC1768 support

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 0:d77ea45fa625 1 #ifndef SIMPLEDMA_H
Sissors 0:d77ea45fa625 2 #define SIMPLEDMA_H
Sissors 0:d77ea45fa625 3
Sissors 2:fe2fcaa72434 4 #ifdef RTOS_H
Sissors 2:fe2fcaa72434 5 #include "rtos.h"
Sissors 2:fe2fcaa72434 6 #endif
Sissors 2:fe2fcaa72434 7
Sissors 0:d77ea45fa625 8 #include "mbed.h"
Sissors 0:d77ea45fa625 9 #include "SimpleDMA_KL25.h"
Sissors 5:d9f46ef80e20 10 #include "SimpleDMA_LPC1768.h"
Sissors 0:d77ea45fa625 11
Sissors 0:d77ea45fa625 12
Sissors 0:d77ea45fa625 13 /**
Sissors 0:d77ea45fa625 14 * SimpleDMA, DMA made simple! (Okay that was bad)
Sissors 0:d77ea45fa625 15 *
Sissors 0:d77ea45fa625 16 * A class to easily make basic DMA operations happen. Not all features
Sissors 0:d77ea45fa625 17 * of the DMA peripherals are used, but the main ones are: From and to memory
Sissors 0:d77ea45fa625 18 * and peripherals, either continiously or triggered
Sissors 0:d77ea45fa625 19 */
Sissors 0:d77ea45fa625 20 class SimpleDMA {
Sissors 0:d77ea45fa625 21 public:
Sissors 3:34f5bf8adfa0 22 /**
Sissors 3:34f5bf8adfa0 23 * Constructor
Sissors 3:34f5bf8adfa0 24 *
Sissors 3:34f5bf8adfa0 25 * @param channel - optional parameter which channel should be used, default is automatic channel selection
Sissors 3:34f5bf8adfa0 26 */
Sissors 3:34f5bf8adfa0 27 SimpleDMA(int channel = -1);
Sissors 0:d77ea45fa625 28
Sissors 0:d77ea45fa625 29 /**
Sissors 0:d77ea45fa625 30 * Set the source of the DMA transfer
Sissors 0:d77ea45fa625 31 *
Sissors 0:d77ea45fa625 32 * Autoincrement increments the pointer after each transfer. If the source
Sissors 0:d77ea45fa625 33 * is an array this should be true, if it is a peripheral or a single memory
Sissors 0:d77ea45fa625 34 * location it should be false.
Sissors 0:d77ea45fa625 35 *
Sissors 0:d77ea45fa625 36 * The source can be any pointer to any memory location. Automatically
Sissors 0:d77ea45fa625 37 * the wordsize is calculated depending on the type, if required you can
Sissors 0:d77ea45fa625 38 * also override this.
Sissors 0:d77ea45fa625 39 *
Sissors 0:d77ea45fa625 40 * @param pointer - pointer to the memory location
Sissors 0:d77ea45fa625 41 * @param autoinc - should the pointer be incremented by the DMA module
Sissors 3:34f5bf8adfa0 42 * @param size - wordsize in bits (optional, generally can be omitted)
Sissors 0:d77ea45fa625 43 * @return - 0 on success
Sissors 0:d77ea45fa625 44 */
Sissors 0:d77ea45fa625 45 template<typename Type>
Sissors 5:d9f46ef80e20 46 void source(Type* pointer, bool autoinc, int size = sizeof(Type) * 8) {
Sissors 5:d9f46ef80e20 47 _source = (uint32_t)pointer;
Sissors 5:d9f46ef80e20 48 source_inc = autoinc;
Sissors 5:d9f46ef80e20 49 source_size = size;
Sissors 0:d77ea45fa625 50 }
Sissors 0:d77ea45fa625 51
Sissors 0:d77ea45fa625 52 /**
Sissors 0:d77ea45fa625 53 * Set the destination of the DMA transfer
Sissors 0:d77ea45fa625 54 *
Sissors 0:d77ea45fa625 55 * Autoincrement increments the pointer after each transfer. If the source
Sissors 0:d77ea45fa625 56 * is an array this should be true, if it is a peripheral or a single memory
Sissors 0:d77ea45fa625 57 * location it should be false.
Sissors 0:d77ea45fa625 58 *
Sissors 0:d77ea45fa625 59 * The destination can be any pointer to any memory location. Automatically
Sissors 0:d77ea45fa625 60 * the wordsize is calculated depending on the type, if required you can
Sissors 0:d77ea45fa625 61 * also override this.
Sissors 0:d77ea45fa625 62 *
Sissors 0:d77ea45fa625 63 * @param pointer - pointer to the memory location
Sissors 0:d77ea45fa625 64 * @param autoinc - should the pointer be incremented by the DMA module
Sissors 3:34f5bf8adfa0 65 * @param size - wordsize in bits (optional, generally can be omitted)
Sissors 0:d77ea45fa625 66 * @return - 0 on success
Sissors 0:d77ea45fa625 67 */
Sissors 0:d77ea45fa625 68 template<typename Type>
Sissors 5:d9f46ef80e20 69 void destination(Type* pointer, bool autoinc, int size = sizeof(Type) * 8) {
Sissors 5:d9f46ef80e20 70 _destination = (uint32_t)pointer;
Sissors 5:d9f46ef80e20 71 destination_inc = autoinc;
Sissors 5:d9f46ef80e20 72 destination_size = size;
Sissors 0:d77ea45fa625 73 }
Sissors 0:d77ea45fa625 74
Sissors 0:d77ea45fa625 75 /**
Sissors 0:d77ea45fa625 76 * Set the trigger for the DMA operation
Sissors 0:d77ea45fa625 77 *
Sissors 0:d77ea45fa625 78 * In SimpleDMA_[yourdevice].h you can find the names of the different triggers.
Sissors 0:d77ea45fa625 79 * Trigger_ALWAYS is defined for all devices, it will simply move the data
Sissors 0:d77ea45fa625 80 * as fast as possible. Used for memory-memory transfers. If nothing else is set
Sissors 0:d77ea45fa625 81 * that will be used by default.
Sissors 0:d77ea45fa625 82 *
Sissors 0:d77ea45fa625 83 * @param trig - trigger to use
Sissors 0:d77ea45fa625 84 * @param return - 0 on success
Sissors 0:d77ea45fa625 85 */
Sissors 5:d9f46ef80e20 86 void trigger(SimpleDMA_Trigger trig) {
Sissors 5:d9f46ef80e20 87 _trigger = trig;
Sissors 5:d9f46ef80e20 88 }
Sissors 0:d77ea45fa625 89
Sissors 0:d77ea45fa625 90 /**
Sissors 3:34f5bf8adfa0 91 * Set the DMA channel
Sissors 3:34f5bf8adfa0 92 *
Sissors 3:34f5bf8adfa0 93 * Generally you will not need to call this function, the constructor does so for you
Sissors 3:34f5bf8adfa0 94 *
Sissors 3:34f5bf8adfa0 95 * @param chan - DMA channel to use, -1 = variable channel (highest priority channel which is available)
Sissors 3:34f5bf8adfa0 96 */
Sissors 3:34f5bf8adfa0 97 void channel(int chan);
Sissors 3:34f5bf8adfa0 98
Sissors 3:34f5bf8adfa0 99 /**
Sissors 0:d77ea45fa625 100 * Start the transfer
Sissors 0:d77ea45fa625 101 *
Sissors 0:d77ea45fa625 102 * @param length - number of BYTES to be moved by the DMA
Sissors 0:d77ea45fa625 103 */
Sissors 0:d77ea45fa625 104 int start(int length);
Sissors 0:d77ea45fa625 105
Sissors 0:d77ea45fa625 106 /**
Sissors 0:d77ea45fa625 107 * Is the DMA channel busy
Sissors 0:d77ea45fa625 108 *
Sissors 3:34f5bf8adfa0 109 * @param channel - channel to check, -1 = current channel
Sissors 0:d77ea45fa625 110 * @return - true if it is busy
Sissors 0:d77ea45fa625 111 */
Sissors 3:34f5bf8adfa0 112 bool isBusy( int channel = -1 );
Sissors 0:d77ea45fa625 113
Sissors 1:0b73b00bcee8 114 /**
Sissors 1:0b73b00bcee8 115 * Attach an interrupt upon completion of DMA transfer or error
Sissors 1:0b73b00bcee8 116 *
Sissors 1:0b73b00bcee8 117 * @param function - function to call upon completion (may be a member function)
Sissors 1:0b73b00bcee8 118 */
Sissors 1:0b73b00bcee8 119 void attach(void (*function)(void)) {
Sissors 1:0b73b00bcee8 120 _callback.attach(function);
Sissors 1:0b73b00bcee8 121 }
Sissors 1:0b73b00bcee8 122
Sissors 1:0b73b00bcee8 123 template<typename T>
Sissors 1:0b73b00bcee8 124 void attach(T *object, void (T::*member)(void)) {
Sissors 1:0b73b00bcee8 125 _callback.attach(object, member);
Sissors 1:0b73b00bcee8 126 }
Sissors 0:d77ea45fa625 127
Sissors 2:fe2fcaa72434 128 #ifdef RTOS_H
Sissors 3:34f5bf8adfa0 129 /**
Sissors 3:34f5bf8adfa0 130 * Start a DMA transfer similar to start, however block current Thread
Sissors 3:34f5bf8adfa0 131 * until the transfer is finished
Sissors 3:34f5bf8adfa0 132 *
Sissors 3:34f5bf8adfa0 133 * When using this function only the current Thread is halted.
Sissors 3:34f5bf8adfa0 134 * The Thread is moved to Waiting state: other Threads will continue
Sissors 3:34f5bf8adfa0 135 * to run normally.
Sissors 3:34f5bf8adfa0 136 *
Sissors 3:34f5bf8adfa0 137 * This function is only available if you included rtos.h before
Sissors 3:34f5bf8adfa0 138 * including SimpleDMA.h.
Sissors 3:34f5bf8adfa0 139 *
Sissors 3:34f5bf8adfa0 140 * @param length - number of BYTES to be moved by the DMA
Sissors 3:34f5bf8adfa0 141 */
Sissors 2:fe2fcaa72434 142 void wait(int length) {
Sissors 1:0b73b00bcee8 143 id = Thread::gettid();
Sissors 1:0b73b00bcee8 144 this->attach(this, &SimpleDMA::waitCallback);
Sissors 2:fe2fcaa72434 145 this->start(length);
Sissors 1:0b73b00bcee8 146 Thread::signal_wait(0x1);
Sissors 1:0b73b00bcee8 147 }
Sissors 2:fe2fcaa72434 148 #endif
Sissors 0:d77ea45fa625 149
Sissors 0:d77ea45fa625 150 protected:
Sissors 5:d9f46ef80e20 151 int _channel;
Sissors 5:d9f46ef80e20 152 SimpleDMA_Trigger _trigger;
Sissors 5:d9f46ef80e20 153 uint32_t _source;
Sissors 5:d9f46ef80e20 154 uint32_t _destination;
Sissors 5:d9f46ef80e20 155 bool source_inc;
Sissors 5:d9f46ef80e20 156 bool destination_inc;
Sissors 5:d9f46ef80e20 157 uint8_t source_size;
Sissors 5:d9f46ef80e20 158 uint8_t destination_size;
Sissors 1:0b73b00bcee8 159
Sissors 3:34f5bf8adfa0 160 bool auto_channel;
Sissors 2:fe2fcaa72434 161
Sissors 2:fe2fcaa72434 162 //IRQ handlers
Sissors 1:0b73b00bcee8 163 FunctionPointer _callback;
Sissors 1:0b73b00bcee8 164 void irq_handler(void);
Sissors 0:d77ea45fa625 165
Sissors 5:d9f46ef80e20 166 static SimpleDMA *irq_owner[DMA_CHANNELS];
Sissors 5:d9f46ef80e20 167
Sissors 5:d9f46ef80e20 168 static void irq_handler0( void );
Sissors 1:0b73b00bcee8 169
Sissors 5:d9f46ef80e20 170 #if DMA_IRQS > 1
Sissors 5:d9f46ef80e20 171 static void irq_handler1( void );
Sissors 5:d9f46ef80e20 172 static void irq_handler2( void );
Sissors 5:d9f46ef80e20 173 static void irq_handler3( void );
Sissors 5:d9f46ef80e20 174 #endif
Sissors 2:fe2fcaa72434 175
Sissors 5:d9f46ef80e20 176 //Keep searching until we find a non-busy channel, start with lowest channel number
Sissors 5:d9f46ef80e20 177 int getFreeChannel(void);
Sissors 2:fe2fcaa72434 178
Sissors 2:fe2fcaa72434 179 #ifdef RTOS_H
Sissors 1:0b73b00bcee8 180 osThreadId id;
Sissors 1:0b73b00bcee8 181 void waitCallback(void) {
Sissors 2:fe2fcaa72434 182 osSignalSet(id, 0x1);
Sissors 1:0b73b00bcee8 183 }
Sissors 2:fe2fcaa72434 184 #endif
Sissors 0:d77ea45fa625 185 };
Sissors 0:d77ea45fa625 186 #endif