A simple library to access the DMA functionality.
Fork of SimpleDMA by
SimpleDMA.h
- Committer:
- Sissors
- Date:
- 2013-12-26
- Revision:
- 4:c3a84c6c432c
- Parent:
- 3:34f5bf8adfa0
- Child:
- 5:d9f46ef80e20
File content as of revision 4:c3a84c6c432c:
#ifndef SIMPLEDMA_H #define SIMPLEDMA_H #ifdef RTOS_H #include "rtos.h" #endif #include "mbed.h" #include "SimpleDMA_KL25.h" /** * SimpleDMA, DMA made simple! (Okay that was bad) * * A class to easily make basic DMA operations happen. Not all features * of the DMA peripherals are used, but the main ones are: From and to memory * and peripherals, either continiously or triggered */ class SimpleDMA { public: /** * Constructor * * @param channel - optional parameter which channel should be used, default is automatic channel selection */ SimpleDMA(int channel = -1); /** * Set the source of the DMA transfer * * Autoincrement increments the pointer after each transfer. If the source * is an array this should be true, if it is a peripheral or a single memory * location it should be false. * * The source can be any pointer to any memory location. Automatically * the wordsize is calculated depending on the type, if required you can * also override this. * * @param pointer - pointer to the memory location * @param autoinc - should the pointer be incremented by the DMA module * @param size - wordsize in bits (optional, generally can be omitted) * @return - 0 on success */ template<typename Type> int source(Type* pointer, bool autoinc, int size = sizeof(Type) * 8) { return setAddress((uint32_t)pointer, size, true, autoinc); } /** * Set the destination of the DMA transfer * * Autoincrement increments the pointer after each transfer. If the source * is an array this should be true, if it is a peripheral or a single memory * location it should be false. * * The destination can be any pointer to any memory location. Automatically * the wordsize is calculated depending on the type, if required you can * also override this. * * @param pointer - pointer to the memory location * @param autoinc - should the pointer be incremented by the DMA module * @param size - wordsize in bits (optional, generally can be omitted) * @return - 0 on success */ template<typename Type> int destination(Type* pointer, bool autoinc, int size = sizeof(Type) * 8) { return setAddress((uint32_t)pointer, size, false, autoinc); } /** * Set the trigger for the DMA operation * * In SimpleDMA_[yourdevice].h you can find the names of the different triggers. * Trigger_ALWAYS is defined for all devices, it will simply move the data * as fast as possible. Used for memory-memory transfers. If nothing else is set * that will be used by default. * * @param trig - trigger to use * @param return - 0 on success */ int trigger(SimpleDMA_Trigger trig); /** * Set the DMA channel * * Generally you will not need to call this function, the constructor does so for you * * @param chan - DMA channel to use, -1 = variable channel (highest priority channel which is available) */ void channel(int chan); /** * Start the transfer * * @param length - number of BYTES to be moved by the DMA */ int start(int length); /** * Is the DMA channel busy * * @param channel - channel to check, -1 = current channel * @return - true if it is busy */ bool isBusy( int channel = -1 ); /** * Attach an interrupt upon completion of DMA transfer or error * * @param function - function to call upon completion (may be a member function) */ void attach(void (*function)(void)) { _callback.attach(function); } template<typename T> void attach(T *object, void (T::*member)(void)) { _callback.attach(object, member); } #ifdef RTOS_H /** * Start a DMA transfer similar to start, however block current Thread * until the transfer is finished * * When using this function only the current Thread is halted. * The Thread is moved to Waiting state: other Threads will continue * to run normally. * * This function is only available if you included rtos.h before * including SimpleDMA.h. * * @param length - number of BYTES to be moved by the DMA */ void wait(int length) { id = Thread::gettid(); this->attach(this, &SimpleDMA::waitCallback); this->start(length); Thread::signal_wait(0x1); } #endif protected: int setAddress(uint32_t address, int wordsize, bool source, bool autoinc); int _channel; bool auto_channel; uint32_t SAR, DAR, DSR, DCR; uint8_t CHCFG; //IRQ handlers FunctionPointer _callback; void irq_handler(void); static SimpleDMA *irq_owner[4]; static void irq_handler0( void ) { if (irq_owner[0]!=NULL) irq_owner[0]->irq_handler(); } static void irq_handler1( void ) { if (irq_owner[1]!=NULL) irq_owner[1]->irq_handler(); } static void irq_handler2( void ) { if (irq_owner[2]!=NULL) irq_owner[2]->irq_handler(); } static void irq_handler3( void ) { if (irq_owner[3]!=NULL) irq_owner[3]->irq_handler(); } #ifdef RTOS_H osThreadId id; void waitCallback(void) { osSignalSet(id, 0x1); } #endif //Keep searching until we find a non-busy channel, start with lowest channel number int getFreeChannel(void) { int retval = 0; while(1) { if (!isBusy(retval)) return retval; retval++; if (retval >= DMA_CHANNELS) retval = 0; } } }; #endif