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: USBDevice mbed FastAnalogIn FastIO FastPWM SimpleDMA
SimpleDMA/SimpleDMA.h@45:c42166b2878c, 2016-02-15 (annotated)
- Committer:
- mjr
- Date:
- Mon Feb 15 20:30:32 2016 +0000
- Revision:
- 45:c42166b2878c
More work in progress on CCD speedups;
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 | 45:c42166b2878c | 47 | void source(Type* pointer, bool autoinc, int size = sizeof(Type) * 8, int mod = 0) { |
| 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 | source_mod = mod; |
| mjr | 45:c42166b2878c | 52 | } |
| mjr | 45:c42166b2878c | 53 | |
| mjr | 45:c42166b2878c | 54 | /** |
| mjr | 45:c42166b2878c | 55 | * Set the destination of the DMA transfer |
| mjr | 45:c42166b2878c | 56 | * |
| mjr | 45:c42166b2878c | 57 | * Autoincrement increments the pointer after each transfer. If the source |
| mjr | 45:c42166b2878c | 58 | * is an array this should be true, if it is a peripheral or a single memory |
| mjr | 45:c42166b2878c | 59 | * location it should be false. |
| mjr | 45:c42166b2878c | 60 | * |
| mjr | 45:c42166b2878c | 61 | * The destination can be any pointer to any memory location. Automatically |
| mjr | 45:c42166b2878c | 62 | * the wordsize is calculated depending on the type, if required you can |
| mjr | 45:c42166b2878c | 63 | * also override this. |
| mjr | 45:c42166b2878c | 64 | * |
| mjr | 45:c42166b2878c | 65 | * @param pointer - pointer to the memory location |
| mjr | 45:c42166b2878c | 66 | * @param autoinc - should the pointer be incremented by the DMA module |
| mjr | 45:c42166b2878c | 67 | * @param size - wordsize in bits (optional, generally can be omitted) |
| mjr | 45:c42166b2878c | 68 | * @return - 0 on success |
| mjr | 45:c42166b2878c | 69 | */ |
| mjr | 45:c42166b2878c | 70 | template<typename Type> |
| mjr | 45:c42166b2878c | 71 | void destination(Type* pointer, bool autoinc, int size = sizeof(Type) * 8, int mod = 0) { |
| mjr | 45:c42166b2878c | 72 | _destination = (uint32_t)pointer; |
| mjr | 45:c42166b2878c | 73 | destination_inc = autoinc; |
| mjr | 45:c42166b2878c | 74 | destination_size = size; |
| mjr | 45:c42166b2878c | 75 | destination_mod = mod; |
| mjr | 45:c42166b2878c | 76 | } |
| mjr | 45:c42166b2878c | 77 | |
| mjr | 45:c42166b2878c | 78 | /** |
| mjr | 45:c42166b2878c | 79 | * Set cycle-steal mode. In cycle-steal mode, we do one DMA transfer per |
| mjr | 45:c42166b2878c | 80 | * trigger. In continuous mode, we do the entire transfer on a single trigger. |
| mjr | 45:c42166b2878c | 81 | */ |
| mjr | 45:c42166b2878c | 82 | void setCycleSteal(bool f) { cycle_steal = f; } |
| mjr | 45:c42166b2878c | 83 | |
| mjr | 45:c42166b2878c | 84 | /** |
| mjr | 45:c42166b2878c | 85 | * Set the trigger for the DMA operation |
| mjr | 45:c42166b2878c | 86 | * |
| mjr | 45:c42166b2878c | 87 | * In SimpleDMA_[yourdevice].h you can find the names of the different triggers. |
| mjr | 45:c42166b2878c | 88 | * Trigger_ALWAYS is defined for all devices, it will simply move the data |
| mjr | 45:c42166b2878c | 89 | * as fast as possible. Used for memory-memory transfers. If nothing else is set |
| mjr | 45:c42166b2878c | 90 | * that will be used by default. |
| mjr | 45:c42166b2878c | 91 | * |
| mjr | 45:c42166b2878c | 92 | * @param trig - trigger to use |
| mjr | 45:c42166b2878c | 93 | * @param return - 0 on success |
| mjr | 45:c42166b2878c | 94 | */ |
| mjr | 45:c42166b2878c | 95 | void trigger(SimpleDMA_Trigger trig) { |
| mjr | 45:c42166b2878c | 96 | _trigger = trig; |
| mjr | 45:c42166b2878c | 97 | } |
| mjr | 45:c42166b2878c | 98 | |
| mjr | 45:c42166b2878c | 99 | /** |
| mjr | 45:c42166b2878c | 100 | * Set the DMA channel |
| mjr | 45:c42166b2878c | 101 | * |
| mjr | 45:c42166b2878c | 102 | * Generally you will not need to call this function, the constructor does so for you |
| mjr | 45:c42166b2878c | 103 | * |
| mjr | 45:c42166b2878c | 104 | * @param chan - DMA channel to use, -1 = variable channel (highest priority channel which is available) |
| mjr | 45:c42166b2878c | 105 | */ |
| mjr | 45:c42166b2878c | 106 | void channel(int chan); |
| mjr | 45:c42166b2878c | 107 | |
| mjr | 45:c42166b2878c | 108 | /** |
| mjr | 45:c42166b2878c | 109 | * Start the transfer |
| mjr | 45:c42166b2878c | 110 | * |
| mjr | 45:c42166b2878c | 111 | * @param length - number of BYTES to be moved by the DMA |
| mjr | 45:c42166b2878c | 112 | */ |
| mjr | 45:c42166b2878c | 113 | int start(uint32_t length); |
| mjr | 45:c42166b2878c | 114 | |
| mjr | 45:c42166b2878c | 115 | /** |
| mjr | 45:c42166b2878c | 116 | * Start a new transfer with the same parameters as last time |
| mjr | 45:c42166b2878c | 117 | */ |
| mjr | 45:c42166b2878c | 118 | int restart(uint32_t length); |
| mjr | 45:c42166b2878c | 119 | |
| mjr | 45:c42166b2878c | 120 | /** |
| mjr | 45:c42166b2878c | 121 | * Is the DMA channel busy |
| mjr | 45:c42166b2878c | 122 | * |
| mjr | 45:c42166b2878c | 123 | * @param channel - channel to check, -1 = current channel |
| mjr | 45:c42166b2878c | 124 | * @return - true if it is busy |
| mjr | 45:c42166b2878c | 125 | */ |
| mjr | 45:c42166b2878c | 126 | bool isBusy( int channel = -1 ); |
| mjr | 45:c42166b2878c | 127 | |
| mjr | 45:c42166b2878c | 128 | /** |
| mjr | 45:c42166b2878c | 129 | * Number of bytes remaining in running transfer. This reads the controller |
| mjr | 45:c42166b2878c | 130 | * register with the remaining byte count, which the hardware updates each |
| mjr | 45:c42166b2878c | 131 | * time it completes a destination transfer. |
| mjr | 45:c42166b2878c | 132 | */ |
| mjr | 45:c42166b2878c | 133 | uint32_t remaining(int channel = -1); |
| mjr | 45:c42166b2878c | 134 | |
| mjr | 45:c42166b2878c | 135 | /** |
| mjr | 45:c42166b2878c | 136 | * Attach an interrupt upon completion of DMA transfer or error |
| mjr | 45:c42166b2878c | 137 | * |
| mjr | 45:c42166b2878c | 138 | * @param function - function to call upon completion (may be a member function) |
| mjr | 45:c42166b2878c | 139 | */ |
| mjr | 45:c42166b2878c | 140 | void attach(void (*function)(void)) { |
| mjr | 45:c42166b2878c | 141 | _callback.attach(function); |
| mjr | 45:c42166b2878c | 142 | } |
| mjr | 45:c42166b2878c | 143 | |
| mjr | 45:c42166b2878c | 144 | template<typename T> |
| mjr | 45:c42166b2878c | 145 | void attach(T *object, void (T::*member)(void)) { |
| mjr | 45:c42166b2878c | 146 | _callback.attach(object, member); |
| mjr | 45:c42166b2878c | 147 | } |
| mjr | 45:c42166b2878c | 148 | |
| mjr | 45:c42166b2878c | 149 | #ifdef RTOS_H |
| mjr | 45:c42166b2878c | 150 | /** |
| mjr | 45:c42166b2878c | 151 | * Start a DMA transfer similar to start, however block current Thread |
| mjr | 45:c42166b2878c | 152 | * until the transfer is finished |
| mjr | 45:c42166b2878c | 153 | * |
| mjr | 45:c42166b2878c | 154 | * When using this function only the current Thread is halted. |
| mjr | 45:c42166b2878c | 155 | * The Thread is moved to Waiting state: other Threads will continue |
| mjr | 45:c42166b2878c | 156 | * to run normally. |
| mjr | 45:c42166b2878c | 157 | * |
| mjr | 45:c42166b2878c | 158 | * This function is only available if you included rtos.h before |
| mjr | 45:c42166b2878c | 159 | * including SimpleDMA.h. |
| mjr | 45:c42166b2878c | 160 | * |
| mjr | 45:c42166b2878c | 161 | * @param length - number of BYTES to be moved by the DMA |
| mjr | 45:c42166b2878c | 162 | */ |
| mjr | 45:c42166b2878c | 163 | void wait(int length) { |
| mjr | 45:c42166b2878c | 164 | id = Thread::gettid(); |
| mjr | 45:c42166b2878c | 165 | this->attach(this, &SimpleDMA::waitCallback); |
| mjr | 45:c42166b2878c | 166 | this->start(length); |
| mjr | 45:c42166b2878c | 167 | Thread::signal_wait(0x1); |
| mjr | 45:c42166b2878c | 168 | } |
| mjr | 45:c42166b2878c | 169 | #endif |
| mjr | 45:c42166b2878c | 170 | |
| mjr | 45:c42166b2878c | 171 | protected: |
| mjr | 45:c42166b2878c | 172 | int _channel; |
| mjr | 45:c42166b2878c | 173 | SimpleDMA_Trigger _trigger; |
| mjr | 45:c42166b2878c | 174 | uint32_t _source; |
| mjr | 45:c42166b2878c | 175 | uint32_t _destination; |
| mjr | 45:c42166b2878c | 176 | bool source_inc; |
| mjr | 45:c42166b2878c | 177 | bool destination_inc; |
| mjr | 45:c42166b2878c | 178 | uint8_t source_size; |
| mjr | 45:c42166b2878c | 179 | uint8_t destination_size; |
| mjr | 45:c42166b2878c | 180 | uint32_t source_mod; |
| mjr | 45:c42166b2878c | 181 | uint32_t destination_mod; |
| mjr | 45:c42166b2878c | 182 | bool cycle_steal; |
| mjr | 45:c42166b2878c | 183 | |
| mjr | 45:c42166b2878c | 184 | bool auto_channel; |
| mjr | 45:c42166b2878c | 185 | |
| mjr | 45:c42166b2878c | 186 | //IRQ handlers |
| mjr | 45:c42166b2878c | 187 | FunctionPointer _callback; |
| mjr | 45:c42166b2878c | 188 | void irq_handler(void); |
| mjr | 45:c42166b2878c | 189 | |
| mjr | 45:c42166b2878c | 190 | static SimpleDMA *irq_owner[DMA_CHANNELS]; |
| mjr | 45:c42166b2878c | 191 | |
| mjr | 45:c42166b2878c | 192 | static void irq_handler0( void ); |
| mjr | 45:c42166b2878c | 193 | |
| mjr | 45:c42166b2878c | 194 | #if DMA_IRQS > 1 |
| mjr | 45:c42166b2878c | 195 | static void irq_handler1( void ); |
| mjr | 45:c42166b2878c | 196 | static void irq_handler2( void ); |
| mjr | 45:c42166b2878c | 197 | static void irq_handler3( void ); |
| mjr | 45:c42166b2878c | 198 | #endif |
| mjr | 45:c42166b2878c | 199 | |
| mjr | 45:c42166b2878c | 200 | //Keep searching until we find a non-busy channel, start with lowest channel number |
| mjr | 45:c42166b2878c | 201 | int getFreeChannel(void); |
| mjr | 45:c42166b2878c | 202 | |
| mjr | 45:c42166b2878c | 203 | #ifdef RTOS_H |
| mjr | 45:c42166b2878c | 204 | osThreadId id; |
| mjr | 45:c42166b2878c | 205 | void waitCallback(void) { |
| mjr | 45:c42166b2878c | 206 | osSignalSet(id, 0x1); |
| mjr | 45:c42166b2878c | 207 | } |
| mjr | 45:c42166b2878c | 208 | #endif |
| mjr | 45:c42166b2878c | 209 | }; |
| mjr | 45:c42166b2878c | 210 | #endif |