A simple library to access the DMA functionality.

Fork of SimpleDMA by Erik -

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SimpleDMA.h Source File

SimpleDMA.h

00001 #ifndef SIMPLEDMA_H
00002 #define SIMPLEDMA_H
00003 
00004 #ifdef RTOS_H
00005 #include "rtos.h"
00006 #endif
00007 
00008 #include "mbed.h"
00009 #include "SimpleDMA_KL25.h"
00010 #include "SimpleDMA_LPC1768.h"
00011 
00012 
00013 /**
00014 * SimpleDMA, DMA made simple! (Okay that was bad)
00015 *
00016 * A class to easily make basic DMA operations happen. Not all features
00017 * of the DMA peripherals are used, but the main ones are: From and to memory
00018 * and peripherals, either continiously or triggered
00019 */
00020 class SimpleDMA {
00021 public:
00022 /**
00023 * Constructor
00024 *
00025 * @param channel - optional parameter which channel should be used, default is automatic channel selection
00026 */
00027 SimpleDMA(int channel = -1);
00028 
00029 /**
00030 * Set the source of the DMA transfer
00031 *
00032 * Autoincrement increments the pointer after each transfer. If the source
00033 * is an array this should be true, if it is a peripheral or a single memory
00034 * location it should be false.
00035 *
00036 * The source can be any pointer to any memory location. Automatically
00037 * the wordsize is calculated depending on the type, if required you can
00038 * also override this.
00039 *
00040 * @param pointer - pointer to the memory location
00041 * @param autoinc - should the pointer be incremented by the DMA module
00042 * @param size - wordsize in bits (optional, generally can be omitted)
00043 * @return - 0 on success
00044 */
00045 template<typename Type>
00046 void source(Type* pointer, bool autoinc, int size = sizeof(Type) * 8) {
00047     _source = (uint32_t)pointer;
00048     source_inc = autoinc;
00049     source_size = size;
00050 }
00051 
00052 /**
00053 * Set the destination of the DMA transfer
00054 *
00055 * Autoincrement increments the pointer after each transfer. If the source
00056 * is an array this should be true, if it is a peripheral or a single memory
00057 * location it should be false.
00058 *
00059 * The destination can be any pointer to any memory location. Automatically
00060 * the wordsize is calculated depending on the type, if required you can
00061 * also override this.
00062 *
00063 * @param pointer - pointer to the memory location
00064 * @param autoinc - should the pointer be incremented by the DMA module
00065 * @param size - wordsize in bits (optional, generally can be omitted)
00066 * @return - 0 on success
00067 */
00068 template<typename Type>
00069 void destination(Type* pointer, bool autoinc, int size = sizeof(Type) * 8) {
00070     _destination = (uint32_t)pointer;
00071     destination_inc = autoinc;
00072     destination_size = size;
00073 }
00074 
00075 /**
00076 * Set the trigger for the DMA operation
00077 *
00078 * In SimpleDMA_[yourdevice].h you can find the names of the different triggers.
00079 * Trigger_ALWAYS is defined for all devices, it will simply move the data
00080 * as fast as possible. Used for memory-memory transfers. If nothing else is set
00081 * that will be used by default.
00082 *
00083 * @param trig - trigger to use
00084 * @param return - 0 on success
00085 */
00086 void trigger(SimpleDMA_Trigger trig) {
00087     _trigger = trig;
00088 }
00089 
00090 /**
00091 * Set the DMA channel
00092 *
00093 * Generally you will not need to call this function, the constructor does so for you
00094 *
00095 * @param chan - DMA channel to use, -1 = variable channel (highest priority channel which is available)
00096 */
00097 void channel(int chan);
00098 
00099 /**
00100 * Start the transfer
00101 *
00102 * @param length - number of BYTES to be moved by the DMA
00103 */
00104 int start(int length);
00105 
00106 /**
00107 * Is the DMA channel busy
00108 *
00109 * @param channel - channel to check, -1 = current channel
00110 * @return - true if it is busy
00111 */
00112 bool isBusy( int channel = -1 );
00113 
00114 /**
00115 * Attach an interrupt upon completion of DMA transfer or error
00116 *
00117 * @param function - function to call upon completion (may be a member function)
00118 */
00119 void attach(void (*function)(void)) {
00120     _callback.attach(function);
00121     }
00122     
00123 template<typename T>
00124     void attach(T *object, void (T::*member)(void)) {
00125         _callback.attach(object, member);
00126     }
00127 
00128 #ifdef RTOS_H
00129 /**
00130 * Start a DMA transfer similar to start, however block current Thread
00131 * until the transfer is finished
00132 *
00133 * When using this function only the current Thread is halted.
00134 * The Thread is moved to Waiting state: other Threads will continue
00135 * to run normally. 
00136 *
00137 * This function is only available if you included rtos.h before 
00138 * including SimpleDMA.h.
00139 *
00140 * @param length - number of BYTES to be moved by the DMA
00141 */
00142 void wait(int length) {
00143     id = Thread::gettid();
00144     this->attach(this, &SimpleDMA::waitCallback);
00145     this->start(length);
00146     Thread::signal_wait(0x1);
00147 }
00148 #endif
00149 
00150 protected:
00151 int _channel;
00152 SimpleDMA_Trigger _trigger;
00153 uint32_t _source;
00154 uint32_t _destination;
00155 bool source_inc;
00156 bool destination_inc;
00157 uint8_t source_size;
00158 uint8_t destination_size;
00159 
00160 bool auto_channel;
00161 
00162 //IRQ handlers
00163 FunctionPointer _callback;
00164 void irq_handler(void);
00165 
00166 static SimpleDMA *irq_owner[DMA_CHANNELS];
00167 
00168 static void irq_handler0( void ); 
00169 
00170 #if DMA_IRQS > 1
00171 static void irq_handler1( void );
00172 static void irq_handler2( void );
00173 static void irq_handler3( void );
00174 #endif
00175 
00176 //Keep searching until we find a non-busy channel, start with lowest channel number
00177 int getFreeChannel(void);
00178 
00179 #ifdef RTOS_H
00180 osThreadId id;
00181 void waitCallback(void) {
00182     osSignalSet(id, 0x1);    
00183 }
00184 #endif
00185 };
00186 #endif