A simple library to access the DMA functionality.

Fork of SimpleDMA by Erik -

Committer:
Sissors
Date:
Thu Dec 26 12:19:29 2013 +0000
Revision:
3:34f5bf8adfa0
Parent:
2:fe2fcaa72434
Child:
4:c3a84c6c432c
Added autochannel

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