DMA Support — Description
ok = hal_dma_channel_init(hal_dma_channel *chan, cyg_uint8 permap, cyg_bool fast, hal_dma_callback *callback, CYG_ADDRWORD data
hal_dma_channel_set_polled(hal_dma_channel *chan, cyg_bool polled
hal_dma_cb_init(hal_dma_cb *cb, cyg_uint32 ti, void *source, void *dest, cyg_uint32 size
hal_dma_add_cb(hal_dma_channel *chan, hal_dma_cb *cb
The HAL provides support for access to the DMA channels. This support is not intended to expose the full functionality of these devices and is mainly limited to supporting peripheral DMA. The API is therefore mainly oriented for use by device drivers rather than applications. The user is referred to the BCM2835 documentation for full details of the DMA channels, and to the SDHOST driver for an example of this API in use.
The DMA hardware consist of sixteen independent channels. DMA is initiated by attaching a chain of control blocks to a channel and starting it running. Each control block contains source and destination addresses, size, transfer direction and a number of other parameters. Of the sixteen channels available, some are reserved for use by the GPU. Also, the channels are divided into full function channels and lite channels that lack some functionality and have lower bandwidth. Full details are available in the BCM2835 documentation.
A DMA channel is represented by a hal_dma_channel
object that the client must allocate. Control blocks are
similarly represented by a hal_dma_cb object, which
again must be allocated by the client. DMA control blocks must be
aligned on a 32 byte boundary. The type definition in
bcm283x_dma.h has an alignment
attribute so that static allocations should be correctly aligned
by default; however care should be taken to align
A DMA channel is initialized by calling
hal_dma_channel_init, the parameters are as
- A pointer to the channel object to be initialized.
Peripheral map value. This is one of the
CYGHWR_HAL_BCM283X_DMA_DREQ_XXXXvalues defined in
bcm238x.h. It specifies the peripheral to or from which the transfer will be made.
- This specifies whether the DMA channel should be a full featured fast channel or a reduced bandwidth lite channel. If a lite channel is specified and none are available a fast channel will be allocated. However, if a fast channel is specified and none are available then this routine will return 0 to indicate an error.
A pointer to a function that will be called when the DMA
transfer has been completed. This will be called with a
pointer to the channel, an event code, nd a copy of the
dataparameter. The event code will be either
CYGHWR_REG_BCM283X_DMA_CS_ENDto indicate a successful completion of the transfer or
CYGHWR_REG_BCM283X_DMA_CS_ERRORto indicate an error.
- An uninterpreted data value that will be passed to the callback. This would typically be a pointer to a client data structure.
If the initialization is successful the routine will return 1. The current implementation of the DMA API permanently allocates a physical channel when this routine is called. In the future the allocation of physical channels may be more dynamic, so the client should not assume that the channel in use is constant.
deletes the given channel, releasing any resources and making
them available for reuse.
marks a channel for polled operation only. Otherwise the
channel will enable interrupts and wait for an interrupt to
complete. If a channel is marked polled then it will only be
completed and its callback called during calls to
hal_dma_poll. Note that channels
not marked polled may also be completed during this call if
their interrupt has not yet fired.
A transfer control block is initialized by calling
hal_dma_cb_init. The parameters are as
- A pointer to the control block to be initialized.
This is an initial value for the
TIregister field of the control block. This may contain any of the bits and fields specified for this register except the
PERMAPfield, which will be set from the value set in the channel. For simplicity the standard settings for common operations are defined by the DMA API;
HAL_DMA_INFO_DEV2MEMinitializes the control block for a single buffer transfer from a device to memory, and
HAL_DMA_INFO_MEM2DEVfor a transfer in the reverse direction. If a client needs to perform scatter/gather transfers, then it needs to set this argument more explicitly. In particular, the
INTENbit should normally only be set on the last control block of a chain.
- The source address for the transfer, either the start of a memory buffer or the data register of the appropriate device.
- The destination address for the transfer, either the start of a memory buffer or the data register of the appropriate device.
- Transfer size in bytes.
Once initialized a control block may be added to a channel by
hal_dma_cb_add. Control blocks
will be chained together on the channel in the order in which
they are added. The DMA engines operate on addresses in the
GPU address space, not the physical address space visible the
the ARM CPUs or the virtual address space set up by the
MMU. During initialization the source and destination
addresses will be translated into GPU addresses, and after it
is added, the
dma_next field of the control
block will be translated to a GPU address. So, care should be
taken when inspecting an active control block and it should
not be changed.
Once a channel had been initialized and any control blocks have
been added the transfers may be started by calling
hal_dma_channel_start. For channels not
marked polled, interrupts will fire and the callback will be
called from a DSR when the control block chain has been
completed. For polled channel, it will be necessary to call
hal_dma_poll until all channels have
An ongoing transfer may be halted by calling
hal_dma_channel_stop. This function
should also be called as a matter of course when a transfer
has completed normally.
|eCosPro Non-Commercial Public License