A simple library to access the DMA functionality.

Fork of SimpleDMA by Erik -

Committer:
BaderP
Date:
Tue Mar 18 12:44:46 2014 +0000
Revision:
6:e9ab0bb912c8
Parent:
5:d9f46ef80e20
patched SimpleDMA to include additional 32 kb ram

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