Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed FastIO FastPWM USBDevice
SimpleDMA/SimpleDMA.h@48:058ace2aed1d, 2016-02-26 (annotated)
- Committer:
- mjr
- Date:
- Fri Feb 26 18:42:03 2016 +0000
- Revision:
- 48:058ace2aed1d
- Parent:
- 47:df7a88cd249c
- Child:
- 54:fd77a6b2f76c
New plunger processing 1
Who changed what in which revision?
| User | Revision | Line number | New contents of line | 
|---|---|---|---|
| mjr | 45:c42166b2878c | 1 | #ifndef SIMPLEDMA_H | 
| mjr | 45:c42166b2878c | 2 | #define SIMPLEDMA_H | 
| mjr | 45:c42166b2878c | 3 | |
| mjr | 45:c42166b2878c | 4 | #ifdef RTOS_H | 
| mjr | 45:c42166b2878c | 5 | #include "rtos.h" | 
| mjr | 45:c42166b2878c | 6 | #endif | 
| mjr | 45:c42166b2878c | 7 | |
| mjr | 45:c42166b2878c | 8 | #include "mbed.h" | 
| mjr | 45:c42166b2878c | 9 | #include "SimpleDMA_KL25.h" | 
| mjr | 45:c42166b2878c | 10 | #include "SimpleDMA_KL46.h" | 
| mjr | 45:c42166b2878c | 11 | #include "SimpleDMA_LPC1768.h" | 
| mjr | 45:c42166b2878c | 12 | |
| mjr | 45:c42166b2878c | 13 | |
| mjr | 45:c42166b2878c | 14 | /** | 
| mjr | 45:c42166b2878c | 15 | * SimpleDMA, DMA made simple! (Okay that was bad) | 
| mjr | 45:c42166b2878c | 16 | * | 
| mjr | 45:c42166b2878c | 17 | * A class to easily make basic DMA operations happen. Not all features | 
| mjr | 45:c42166b2878c | 18 | * of the DMA peripherals are used, but the main ones are: From and to memory | 
| mjr | 45:c42166b2878c | 19 | * and peripherals, either continiously or triggered | 
| mjr | 45:c42166b2878c | 20 | */ | 
| mjr | 45:c42166b2878c | 21 | class SimpleDMA { | 
| mjr | 45:c42166b2878c | 22 | public: | 
| mjr | 45:c42166b2878c | 23 | /** | 
| mjr | 45:c42166b2878c | 24 | * Constructor | 
| mjr | 45:c42166b2878c | 25 | * | 
| mjr | 45:c42166b2878c | 26 | * @param channel - optional parameter which channel should be used, default is automatic channel selection | 
| mjr | 45:c42166b2878c | 27 | */ | 
| mjr | 45:c42166b2878c | 28 | SimpleDMA(int channel = -1); | 
| mjr | 45:c42166b2878c | 29 | |
| mjr | 45:c42166b2878c | 30 | /** | 
| mjr | 45:c42166b2878c | 31 | * Set the source of the DMA transfer | 
| mjr | 45:c42166b2878c | 32 | * | 
| mjr | 45:c42166b2878c | 33 | * Autoincrement increments the pointer after each transfer. If the source | 
| mjr | 45:c42166b2878c | 34 | * is an array this should be true, if it is a peripheral or a single memory | 
| mjr | 45:c42166b2878c | 35 | * location it should be false. | 
| mjr | 45:c42166b2878c | 36 | * | 
| mjr | 45:c42166b2878c | 37 | * The source can be any pointer to any memory location. Automatically | 
| mjr | 45:c42166b2878c | 38 | * the wordsize is calculated depending on the type, if required you can | 
| mjr | 45:c42166b2878c | 39 | * also override this. | 
| mjr | 45:c42166b2878c | 40 | * | 
| mjr | 45:c42166b2878c | 41 | * @param pointer - pointer to the memory location | 
| mjr | 45:c42166b2878c | 42 | * @param autoinc - should the pointer be incremented by the DMA module | 
| mjr | 45:c42166b2878c | 43 | * @param size - wordsize in bits (optional, generally can be omitted) | 
| mjr | 45:c42166b2878c | 44 | * @return - 0 on success | 
| mjr | 45:c42166b2878c | 45 | */ | 
| mjr | 45:c42166b2878c | 46 | template<typename Type> | 
| mjr | 48:058ace2aed1d | 47 | void source(Type* pointer, bool autoinc, int size = sizeof(Type) * 8) { | 
| mjr | 45:c42166b2878c | 48 | _source = (uint32_t)pointer; | 
| mjr | 45:c42166b2878c | 49 | source_inc = autoinc; | 
| mjr | 45:c42166b2878c | 50 | source_size = size; | 
| mjr | 45:c42166b2878c | 51 | } | 
| mjr | 45:c42166b2878c | 52 | |
| mjr | 45:c42166b2878c | 53 | /** | 
| mjr | 45:c42166b2878c | 54 | * Set the destination of the DMA transfer | 
| mjr | 45:c42166b2878c | 55 | * | 
| mjr | 45:c42166b2878c | 56 | * Autoincrement increments the pointer after each transfer. If the source | 
| mjr | 45:c42166b2878c | 57 | * is an array this should be true, if it is a peripheral or a single memory | 
| mjr | 45:c42166b2878c | 58 | * location it should be false. | 
| mjr | 45:c42166b2878c | 59 | * | 
| mjr | 45:c42166b2878c | 60 | * The destination can be any pointer to any memory location. Automatically | 
| mjr | 45:c42166b2878c | 61 | * the wordsize is calculated depending on the type, if required you can | 
| mjr | 45:c42166b2878c | 62 | * also override this. | 
| mjr | 45:c42166b2878c | 63 | * | 
| mjr | 45:c42166b2878c | 64 | * @param pointer - pointer to the memory location | 
| mjr | 45:c42166b2878c | 65 | * @param autoinc - should the pointer be incremented by the DMA module | 
| mjr | 45:c42166b2878c | 66 | * @param size - wordsize in bits (optional, generally can be omitted) | 
| mjr | 45:c42166b2878c | 67 | * @return - 0 on success | 
| mjr | 45:c42166b2878c | 68 | */ | 
| mjr | 45:c42166b2878c | 69 | template<typename Type> | 
| mjr | 48:058ace2aed1d | 70 | void destination(Type* pointer, bool autoinc, int size = sizeof(Type) * 8) { | 
| mjr | 45:c42166b2878c | 71 | _destination = (uint32_t)pointer; | 
| mjr | 45:c42166b2878c | 72 | destination_inc = autoinc; | 
| mjr | 45:c42166b2878c | 73 | destination_size = size; | 
| mjr | 45:c42166b2878c | 74 | } | 
| mjr | 45:c42166b2878c | 75 | |
| mjr | 45:c42166b2878c | 76 | |
| mjr | 45:c42166b2878c | 77 | /** | 
| mjr | 45:c42166b2878c | 78 | * Set the trigger for the DMA operation | 
| mjr | 45:c42166b2878c | 79 | * | 
| mjr | 45:c42166b2878c | 80 | * In SimpleDMA_[yourdevice].h you can find the names of the different triggers. | 
| mjr | 45:c42166b2878c | 81 | * Trigger_ALWAYS is defined for all devices, it will simply move the data | 
| mjr | 45:c42166b2878c | 82 | * as fast as possible. Used for memory-memory transfers. If nothing else is set | 
| mjr | 45:c42166b2878c | 83 | * that will be used by default. | 
| mjr | 45:c42166b2878c | 84 | * | 
| mjr | 45:c42166b2878c | 85 | * @param trig - trigger to use | 
| mjr | 45:c42166b2878c | 86 | * @param return - 0 on success | 
| mjr | 45:c42166b2878c | 87 | */ | 
| mjr | 45:c42166b2878c | 88 | void trigger(SimpleDMA_Trigger trig) { | 
| mjr | 45:c42166b2878c | 89 | _trigger = trig; | 
| mjr | 45:c42166b2878c | 90 | } | 
| mjr | 45:c42166b2878c | 91 | |
| mjr | 45:c42166b2878c | 92 | /** | 
| mjr | 45:c42166b2878c | 93 | * Set the DMA channel | 
| mjr | 45:c42166b2878c | 94 | * | 
| mjr | 45:c42166b2878c | 95 | * Generally you will not need to call this function, the constructor does so for you | 
| mjr | 45:c42166b2878c | 96 | * | 
| mjr | 45:c42166b2878c | 97 | * @param chan - DMA channel to use, -1 = variable channel (highest priority channel which is available) | 
| mjr | 45:c42166b2878c | 98 | */ | 
| mjr | 45:c42166b2878c | 99 | void channel(int chan); | 
| mjr | 47:df7a88cd249c | 100 | int getChannel() { return _channel; } | 
| mjr | 45:c42166b2878c | 101 | |
| mjr | 45:c42166b2878c | 102 | /** | 
| mjr | 45:c42166b2878c | 103 | * Start the transfer | 
| mjr | 45:c42166b2878c | 104 | * | 
| mjr | 45:c42166b2878c | 105 | * @param length - number of BYTES to be moved by the DMA | 
| mjr | 45:c42166b2878c | 106 | */ | 
| mjr | 45:c42166b2878c | 107 | int start(uint32_t length); | 
| mjr | 45:c42166b2878c | 108 | |
| mjr | 45:c42166b2878c | 109 | /** | 
| mjr | 45:c42166b2878c | 110 | * Start a new transfer with the same parameters as last time | 
| mjr | 45:c42166b2878c | 111 | */ | 
| mjr | 45:c42166b2878c | 112 | int restart(uint32_t length); | 
| mjr | 45:c42166b2878c | 113 | |
| mjr | 45:c42166b2878c | 114 | /** | 
| mjr | 45:c42166b2878c | 115 | * Is the DMA channel busy | 
| mjr | 45:c42166b2878c | 116 | * | 
| mjr | 45:c42166b2878c | 117 | * @param channel - channel to check, -1 = current channel | 
| mjr | 45:c42166b2878c | 118 | * @return - true if it is busy | 
| mjr | 45:c42166b2878c | 119 | */ | 
| mjr | 45:c42166b2878c | 120 | bool isBusy( int channel = -1 ); | 
| mjr | 45:c42166b2878c | 121 | |
| mjr | 45:c42166b2878c | 122 | /** | 
| mjr | 45:c42166b2878c | 123 | * Number of bytes remaining in running transfer. This reads the controller | 
| mjr | 45:c42166b2878c | 124 | * register with the remaining byte count, which the hardware updates each | 
| mjr | 45:c42166b2878c | 125 | * time it completes a destination transfer. | 
| mjr | 45:c42166b2878c | 126 | */ | 
| mjr | 45:c42166b2878c | 127 | uint32_t remaining(int channel = -1); | 
| mjr | 45:c42166b2878c | 128 | |
| mjr | 45:c42166b2878c | 129 | /** | 
| mjr | 45:c42166b2878c | 130 | * Attach an interrupt upon completion of DMA transfer or error | 
| mjr | 45:c42166b2878c | 131 | * | 
| mjr | 45:c42166b2878c | 132 | * @param function - function to call upon completion (may be a member function) | 
| mjr | 45:c42166b2878c | 133 | */ | 
| mjr | 45:c42166b2878c | 134 | void attach(void (*function)(void)) { | 
| mjr | 45:c42166b2878c | 135 | _callback.attach(function); | 
| mjr | 45:c42166b2878c | 136 | } | 
| mjr | 45:c42166b2878c | 137 | |
| mjr | 45:c42166b2878c | 138 | template<typename T> | 
| mjr | 45:c42166b2878c | 139 | void attach(T *object, void (T::*member)(void)) { | 
| mjr | 45:c42166b2878c | 140 | _callback.attach(object, member); | 
| mjr | 45:c42166b2878c | 141 | } | 
| mjr | 47:df7a88cd249c | 142 | |
| mjr | 47:df7a88cd249c | 143 | /** | 
| mjr | 47:df7a88cd249c | 144 | * Link to another channel. This triggers the given destination | 
| mjr | 47:df7a88cd249c | 145 | * channel when a transfer on this channel is completed. If 'all' | 
| mjr | 47:df7a88cd249c | 146 | * is true, the link occurs after the entire transfer is complete | 
| mjr | 47:df7a88cd249c | 147 | * (i.e., the byte count register in this channel reaches zero). | 
| mjr | 47:df7a88cd249c | 148 | * Otherwise, the link is triggered once for each transfer on this | 
| mjr | 47:df7a88cd249c | 149 | * channel. | 
| mjr | 47:df7a88cd249c | 150 | */ | 
| mjr | 47:df7a88cd249c | 151 | void link(SimpleDMA &dest, bool all = false); | 
| mjr | 47:df7a88cd249c | 152 | |
| mjr | 47:df7a88cd249c | 153 | /** | 
| mjr | 47:df7a88cd249c | 154 | * Link to two other channels. This triggers the 'dest1' channel | 
| mjr | 47:df7a88cd249c | 155 | * once for each transfer on this channel, and then triggers the | 
| mjr | 47:df7a88cd249c | 156 | * 'dest2' channel once when the entire transfer has been completed | 
| mjr | 47:df7a88cd249c | 157 | * (i.e., the byte count register on this channel reaches zero). | 
| mjr | 47:df7a88cd249c | 158 | */ | 
| mjr | 47:df7a88cd249c | 159 | void link(SimpleDMA &dest1, SimpleDMA &dest2); | 
| mjr | 47:df7a88cd249c | 160 | |
| mjr | 45:c42166b2878c | 161 | |
| mjr | 45:c42166b2878c | 162 | #ifdef RTOS_H | 
| mjr | 45:c42166b2878c | 163 | /** | 
| mjr | 45:c42166b2878c | 164 | * Start a DMA transfer similar to start, however block current Thread | 
| mjr | 45:c42166b2878c | 165 | * until the transfer is finished | 
| mjr | 45:c42166b2878c | 166 | * | 
| mjr | 45:c42166b2878c | 167 | * When using this function only the current Thread is halted. | 
| mjr | 45:c42166b2878c | 168 | * The Thread is moved to Waiting state: other Threads will continue | 
| mjr | 45:c42166b2878c | 169 | * to run normally. | 
| mjr | 45:c42166b2878c | 170 | * | 
| mjr | 45:c42166b2878c | 171 | * This function is only available if you included rtos.h before | 
| mjr | 45:c42166b2878c | 172 | * including SimpleDMA.h. | 
| mjr | 45:c42166b2878c | 173 | * | 
| mjr | 45:c42166b2878c | 174 | * @param length - number of BYTES to be moved by the DMA | 
| mjr | 45:c42166b2878c | 175 | */ | 
| mjr | 45:c42166b2878c | 176 | void wait(int length) { | 
| mjr | 45:c42166b2878c | 177 | id = Thread::gettid(); | 
| mjr | 45:c42166b2878c | 178 | this->attach(this, &SimpleDMA::waitCallback); | 
| mjr | 45:c42166b2878c | 179 | this->start(length); | 
| mjr | 45:c42166b2878c | 180 | Thread::signal_wait(0x1); | 
| mjr | 45:c42166b2878c | 181 | } | 
| mjr | 45:c42166b2878c | 182 | #endif | 
| mjr | 45:c42166b2878c | 183 | |
| mjr | 45:c42166b2878c | 184 | protected: | 
| mjr | 48:058ace2aed1d | 185 | uint8_t _channel; | 
| mjr | 45:c42166b2878c | 186 | SimpleDMA_Trigger _trigger; | 
| mjr | 45:c42166b2878c | 187 | uint32_t _source; | 
| mjr | 45:c42166b2878c | 188 | uint32_t _destination; | 
| mjr | 45:c42166b2878c | 189 | uint8_t source_size; | 
| mjr | 45:c42166b2878c | 190 | uint8_t destination_size; | 
| mjr | 48:058ace2aed1d | 191 | uint8_t linkChannel1; | 
| mjr | 48:058ace2aed1d | 192 | uint8_t linkChannel2; | 
| mjr | 48:058ace2aed1d | 193 | bool source_inc : 1; | 
| mjr | 48:058ace2aed1d | 194 | bool destination_inc : 1; | 
| mjr | 48:058ace2aed1d | 195 | bool auto_channel : 1; | 
| mjr | 48:058ace2aed1d | 196 | uint8_t linkMode : 2; | 
| mjr | 45:c42166b2878c | 197 | |
| mjr | 45:c42166b2878c | 198 | |
| mjr | 45:c42166b2878c | 199 | //IRQ handlers | 
| mjr | 45:c42166b2878c | 200 | FunctionPointer _callback; | 
| mjr | 45:c42166b2878c | 201 | void irq_handler(void); | 
| mjr | 45:c42166b2878c | 202 | |
| mjr | 45:c42166b2878c | 203 | static SimpleDMA *irq_owner[DMA_CHANNELS]; | 
| mjr | 45:c42166b2878c | 204 | |
| mjr | 48:058ace2aed1d | 205 | static void class_init(); | 
| mjr | 45:c42166b2878c | 206 | static void irq_handler0( void ); | 
| mjr | 45:c42166b2878c | 207 | |
| mjr | 45:c42166b2878c | 208 | #if DMA_IRQS > 1 | 
| mjr | 45:c42166b2878c | 209 | static void irq_handler1( void ); | 
| mjr | 45:c42166b2878c | 210 | static void irq_handler2( void ); | 
| mjr | 45:c42166b2878c | 211 | static void irq_handler3( void ); | 
| mjr | 45:c42166b2878c | 212 | #endif | 
| mjr | 45:c42166b2878c | 213 | |
| mjr | 45:c42166b2878c | 214 | //Keep searching until we find a non-busy channel, start with lowest channel number | 
| mjr | 45:c42166b2878c | 215 | int getFreeChannel(void); | 
| mjr | 45:c42166b2878c | 216 | |
| mjr | 45:c42166b2878c | 217 | #ifdef RTOS_H | 
| mjr | 45:c42166b2878c | 218 | osThreadId id; | 
| mjr | 45:c42166b2878c | 219 | void waitCallback(void) { | 
| mjr | 45:c42166b2878c | 220 | osSignalSet(id, 0x1); | 
| mjr | 45:c42166b2878c | 221 | } | 
| mjr | 45:c42166b2878c | 222 | #endif | 
| mjr | 45:c42166b2878c | 223 | }; | 
| mjr | 45:c42166b2878c | 224 | #endif |