DMA Support — Description


    typedef struct hal_edma_channel hal_edma_channel;

    typedef void hal_edma_callback( hal_edma_channel *edma_chan, cyg_uint32 event, CYG_ADDRWORD data );
#include <cyg/hal/hal_io.h>

pin = CYGHWR_HAL_L1XX_EDMA_CHANNEL( controller , event );

void hal_edma_channel_init ( hal_edma_channel *edma_chan , cyg_uint32 channel , hal_edma_callback *callback , CYG_ADDRWORD data );

void hal_edma_channel_delete ( hal_edma_channel *edma_chan );

void hal_edma_channel_source ( hal_edma_channel *edma_chan , void *src , cyg_int16 bidx , cyg_int16 cidx );

void hal_edma_channel_dest ( hal_edma_channel *edma_chan , void *dest , cyg_int16 bidx , cyg_int16 cidx );

void hal_edma_channel_burstsize ( hal_edma_channel *edma_chan , cyg_uint16 aburstsize , cyg_uint16 bburstsize );

void hal_edma_channel_size ( hal_edma_channel *edma_chan , cyg_uint32 size );

void hal_edma_channel_start ( hal_edma_channel *edma_chan , cyg_uint32 opt );

void hal_edma_channel_stop ( hal_edma_channel *edma_chan );

void hal_edma_poll ( void );


The HAL provides support for access to the EDMA3 DMA controllers. This support is not intended to expose the full functionality of these devices and is strictly limited to supporting peripheral DMA, in particular SPI and MMC/SD.

The user is referred to the TI EDMA3 documentation for a full description of the EDMA3 devices, and to the sources of the MMC and SPI drivers for examples of the use of this API. This documentation only gives a brief description of the functions available.

Each device transfer direction is described by a controller number (0 or 1) and an event numbers (0 to 31). These values are usually defined by the peripheral being accessed. The macro CYGHWR_HAL_L1XX_EDMA_CHANNEL( controller, event) combines these into a descriptor that may be used to initialize the channel. A channel is controlled by a hal_edma_channel object that must be allocated by the client. To initialize a channel, hal_edma_channel_init() is called, passing the channel object, the descriptor and an optional callback function and user-defined value. After use the channel can be deleted with hal_edma_channel_delete().

Before starting a transfer, the channel must be initialized with the source, destination and size of the transfer to be done. hal_edma_channel_source() and hal_edma_channel_dest() describe the source and destination buffers. A memory buffer is described by its address plus the increments, or indexes, to step the read or write pointer through it. The sizes of these indexes depend on the size of the transfers that the peripheral is programmed to make, and its synchronisation mode. One of the source or destination will be the peripheral itself; the address should be the address of the peripheral's input or output data register, and the indexes should be zero to prevent the pointer incrementing.

hal_edma_channel_size() supplies the total transfer size in bytes. hal_edma_channel_burstsize() describes the A and B burst sizes for AB synchronized transfers and must be called before hal_edma_channel_size(). If hal_edma_channel_burstsize() is not called then A synchronization is assumed. The values set by hal_edma_channel_burstsize() remain set in the channel, and another call to this function is needed to reset them.

A transfer is started by calling hal_edma_channel_start(). The opt argument contains bits that will be merged with the PaRAM options field. When a transfer is complete, then hal_edma_channel_stop() should be called. This function may also be called to abort a transfer.

If a callback was passed to hal_edma_channel_init() then when the transfer finishes or encounters and error, the callback will be called from DSR context. The callback will be passed a pointer to the channel object, an event code and the user-defined value that was passed to hal_edma_channel_init(). There are two possible event codes: CYGHWR_HAL_L1XX_EDMA_COMPLETE indicates that the transfer finished successfully, and CYGHWR_HAL_L1XX_EDMA_ERROR indicates that an error condition was encountered.

In kernel configurations the DMA system will use interrupts to detect transfer completion or errors. In non-kernel configurations it will use polling. For the polling to happen, client code must call hal_edma_poll() on a regular basis. On DMA completion the callback function will be called, as before.