Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

Committer:
arnoz
Date:
Fri Oct 01 08:19:46 2021 +0000
Revision:
116:7a67265d7c19
Parent:
100:1ff35c07217c
- Correct information regarding your last merge

Who changed what in which revision?

UserRevisionLine numberNew 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 54:fd77a6b2f76c 107 int start(uint32_t length, bool wait);
mjr 45:c42166b2878c 108
mjr 45:c42166b2878c 109 /**
mjr 100:1ff35c07217c 110 * Prepare a transfer. This sets everything up for a transfer, but leaves it up
mjr 100:1ff35c07217c 111 * to the caller to trigger the start of the transfer. This gives the caller
mjr 100:1ff35c07217c 112 * precise control over the timing of the transfer, for transfers that must be
mjr 100:1ff35c07217c 113 * synchronized with other functions. To start the DMA transfer, the caller
mjr 100:1ff35c07217c 114 * must simply "OR" DMAMUX_CHCFG_ENBL_MASK into the byte at the returned
mjr 100:1ff35c07217c 115 * address.
mjr 100:1ff35c07217c 116 */
mjr 100:1ff35c07217c 117 volatile uint8_t *prepare(uint32_t length, bool wait);
mjr 100:1ff35c07217c 118
mjr 100:1ff35c07217c 119 /**
mjr 45:c42166b2878c 120 * Is the DMA channel busy
mjr 45:c42166b2878c 121 *
mjr 45:c42166b2878c 122 * @param channel - channel to check, -1 = current channel
mjr 45:c42166b2878c 123 * @return - true if it is busy
mjr 45:c42166b2878c 124 */
mjr 45:c42166b2878c 125 bool isBusy( int channel = -1 );
mjr 45:c42166b2878c 126
mjr 45:c42166b2878c 127 /**
mjr 45:c42166b2878c 128 * Number of bytes remaining in running transfer. This reads the controller
mjr 45:c42166b2878c 129 * register with the remaining byte count, which the hardware updates each
mjr 45:c42166b2878c 130 * time it completes a destination transfer.
mjr 45:c42166b2878c 131 */
mjr 45:c42166b2878c 132 uint32_t remaining(int channel = -1);
mjr 45:c42166b2878c 133
mjr 45:c42166b2878c 134 /**
mjr 45:c42166b2878c 135 * Attach an interrupt upon completion of DMA transfer or error
mjr 45:c42166b2878c 136 *
mjr 45:c42166b2878c 137 * @param function - function to call upon completion (may be a member function)
mjr 45:c42166b2878c 138 */
mjr 45:c42166b2878c 139 void attach(void (*function)(void)) {
mjr 45:c42166b2878c 140 _callback.attach(function);
mjr 45:c42166b2878c 141 }
mjr 45:c42166b2878c 142
mjr 45:c42166b2878c 143 template<typename T>
mjr 45:c42166b2878c 144 void attach(T *object, void (T::*member)(void)) {
mjr 45:c42166b2878c 145 _callback.attach(object, member);
mjr 45:c42166b2878c 146 }
mjr 47:df7a88cd249c 147
mjr 47:df7a88cd249c 148 /**
mjr 47:df7a88cd249c 149 * Link to another channel. This triggers the given destination
mjr 47:df7a88cd249c 150 * channel when a transfer on this channel is completed. If 'all'
mjr 47:df7a88cd249c 151 * is true, the link occurs after the entire transfer is complete
mjr 47:df7a88cd249c 152 * (i.e., the byte count register in this channel reaches zero).
mjr 47:df7a88cd249c 153 * Otherwise, the link is triggered once for each transfer on this
mjr 47:df7a88cd249c 154 * channel.
mjr 47:df7a88cd249c 155 */
mjr 47:df7a88cd249c 156 void link(SimpleDMA &dest, bool all = false);
mjr 47:df7a88cd249c 157
mjr 47:df7a88cd249c 158 /**
mjr 47:df7a88cd249c 159 * Link to two other channels. This triggers the 'dest1' channel
mjr 47:df7a88cd249c 160 * once for each transfer on this channel, and then triggers the
mjr 47:df7a88cd249c 161 * 'dest2' channel once when the entire transfer has been completed
mjr 47:df7a88cd249c 162 * (i.e., the byte count register on this channel reaches zero).
mjr 47:df7a88cd249c 163 */
mjr 47:df7a88cd249c 164 void link(SimpleDMA &dest1, SimpleDMA &dest2);
mjr 47:df7a88cd249c 165
mjr 45:c42166b2878c 166
mjr 45:c42166b2878c 167 #ifdef RTOS_H
mjr 45:c42166b2878c 168 /**
mjr 45:c42166b2878c 169 * Start a DMA transfer similar to start, however block current Thread
mjr 45:c42166b2878c 170 * until the transfer is finished
mjr 45:c42166b2878c 171 *
mjr 45:c42166b2878c 172 * When using this function only the current Thread is halted.
mjr 45:c42166b2878c 173 * The Thread is moved to Waiting state: other Threads will continue
mjr 45:c42166b2878c 174 * to run normally.
mjr 45:c42166b2878c 175 *
mjr 45:c42166b2878c 176 * This function is only available if you included rtos.h before
mjr 45:c42166b2878c 177 * including SimpleDMA.h.
mjr 45:c42166b2878c 178 *
mjr 45:c42166b2878c 179 * @param length - number of BYTES to be moved by the DMA
mjr 45:c42166b2878c 180 */
mjr 45:c42166b2878c 181 void wait(int length) {
mjr 45:c42166b2878c 182 id = Thread::gettid();
mjr 45:c42166b2878c 183 this->attach(this, &SimpleDMA::waitCallback);
mjr 45:c42166b2878c 184 this->start(length);
mjr 45:c42166b2878c 185 Thread::signal_wait(0x1);
mjr 45:c42166b2878c 186 }
mjr 45:c42166b2878c 187 #endif
mjr 45:c42166b2878c 188
mjr 45:c42166b2878c 189 protected:
mjr 48:058ace2aed1d 190 uint8_t _channel;
mjr 45:c42166b2878c 191 SimpleDMA_Trigger _trigger;
mjr 45:c42166b2878c 192 uint32_t _source;
mjr 45:c42166b2878c 193 uint32_t _destination;
mjr 45:c42166b2878c 194 uint8_t source_size;
mjr 45:c42166b2878c 195 uint8_t destination_size;
mjr 48:058ace2aed1d 196 uint8_t linkChannel1;
mjr 48:058ace2aed1d 197 uint8_t linkChannel2;
mjr 48:058ace2aed1d 198 bool source_inc : 1;
mjr 48:058ace2aed1d 199 bool destination_inc : 1;
mjr 48:058ace2aed1d 200 bool auto_channel : 1;
mjr 48:058ace2aed1d 201 uint8_t linkMode : 2;
mjr 45:c42166b2878c 202
mjr 45:c42166b2878c 203
mjr 45:c42166b2878c 204 //IRQ handlers
mjr 45:c42166b2878c 205 FunctionPointer _callback;
mjr 45:c42166b2878c 206 void irq_handler(void);
mjr 45:c42166b2878c 207
mjr 45:c42166b2878c 208 static SimpleDMA *irq_owner[DMA_CHANNELS];
mjr 45:c42166b2878c 209
mjr 48:058ace2aed1d 210 static void class_init();
mjr 45:c42166b2878c 211 static void irq_handler0( void );
mjr 45:c42166b2878c 212
mjr 45:c42166b2878c 213 #if DMA_IRQS > 1
mjr 45:c42166b2878c 214 static void irq_handler1( void );
mjr 45:c42166b2878c 215 static void irq_handler2( void );
mjr 45:c42166b2878c 216 static void irq_handler3( void );
mjr 45:c42166b2878c 217 #endif
mjr 45:c42166b2878c 218
mjr 45:c42166b2878c 219 //Keep searching until we find a non-busy channel, start with lowest channel number
mjr 45:c42166b2878c 220 int getFreeChannel(void);
mjr 45:c42166b2878c 221
mjr 45:c42166b2878c 222 #ifdef RTOS_H
mjr 45:c42166b2878c 223 osThreadId id;
mjr 45:c42166b2878c 224 void waitCallback(void) {
mjr 45:c42166b2878c 225 osSignalSet(id, 0x1);
mjr 45:c42166b2878c 226 }
mjr 45:c42166b2878c 227 #endif
mjr 45:c42166b2878c 228 };
mjr 45:c42166b2878c 229 #endif