Having introduced Direct Memory Access in my previous blog, this blog will focus upon creating a very simple example which demonstrates how to set up and use DMA. To demonstrate this I will transfer one memory location to another using one DMA controller channel.
The starting point for this is one which we have commonly used in this blog series: the inclusion of header files generated as part of the BSP. These header files provide macros and functions we can use to drive the DMA. For this example we will need to include:
Xscugic.h and xil_exceptions.h allow use of the interrupt controller while xdmaps.h configures and allows use of the DMA.
Using parameters provided with xparamters.h, we can define the device identifications for the DMA and interrupt controller, the interrupts that will be used, and the length of the data we will be transferring:
The next stage of the development is to write three functions to configure the DMA, to configure the interrupt controller, and to act as the interrupt service routine at the completion of the DMA transfer.
Within the DMA configuration function we first create a DMA command using the command structure provided by xdmaps.h. A DMA command consists of the channel control, block descriptor, a user-defined program, a pointer to the generated program and the result of the transfer. As this is a simple example we will not be requiring all of these components however we will be configuring the DMA controller as below:
DmaCmd.ChanCtrl.SrcBurstSize = 4;
DmaCmd.ChanCtrl.SrcBurstLen = 4;
DmaCmd.ChanCtrl.SrcInc = 1;
DmaCmd.ChanCtrl.DstBurstSize = 4;
DmaCmd.ChanCtrl.DstBurstLen = 4;
DmaCmd.ChanCtrl.DstInc = 1;
DmaCmd.BD.SrcAddr = (u32) Src;
DmaCmd.BD.DstAddr = (u32) Dst;
DmaCmd.BD.Length = DMA_LENGTH * sizeof(int);
The next step is to initialize and configure the DMA controller before running the interrupt set up function to connect the DMA interrupts to the interrupt controller:
Following this, the source memory location is seeded with data and the destination location is cleared before we connect the done handler and start the transfer, to track progress we also make one call to the DMA progress function: