A simple library to access the DMA functionality.

Fork of SimpleDMA by Erik -

SimpleDMA.h

Committer:
Sissors
Date:
2013-12-22
Revision:
2:fe2fcaa72434
Parent:
1:0b73b00bcee8
Child:
3:34f5bf8adfa0

File content as of revision 2:fe2fcaa72434:

#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:
SimpleDMA(int channel = 0);

/**
* 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 - size of the transfer (optional, generally can be omitted)
* @return - 0 on success
*/
template<typename Type>
int source(Type* pointer, bool autoinc, int size = sizeof(Type*)) {
    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 - size of the transfer (optional, generally can be omitted)
* @return - 0 on success
*/
template<typename Type>
int destination(Type* pointer, bool autoinc, int size = sizeof(Type*)) {
    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);

/**
* Start the transfer
*
* @param length - number of BYTES to be moved by the DMA
*/
int start(int length);

/**
* Is the DMA channel busy
*
* @return - true if it is busy
*/
bool isBusy( void );

/**
* 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)) {
    irq_en = function;
    _callback.attach(function);
    }
    
template<typename T>
    void attach(T *object, void (T::*member)(void)) {
        irq_en = object;
        _callback.attach(object, member);
    }

#ifdef RTOS_H
void wait(int length) {
    id = Thread::gettid();
    this->attach(this, &SimpleDMA::waitCallback);
    this->start(length);
    Thread::signal_wait(0x1);
}
#endif

protected:
/**
* Set the DMA channel
*
* @param chan - DMA channel to use
*/
void channel(int chan);
int setAddress(uint32_t address, int wordsize, bool source, bool autoinc);

int _channel;
uint32_t SAR, DAR, DSR, DCR;
uint8_t CHCFG;

//IRQ handlers
FunctionPointer _callback;
bool irq_en;
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

};
#endif