I’m trying to get a DMA engine to access main memory on a Xilinx Zynq 7000 (ARM Cortex-A9). I’m setting the source address for the DMA engine to the start address of the array in memory. However, I’m getting bad data passed to the destination.
I understand there is no memory management in FreeRTOS, but the ARM does have a memory management unit and I read some conflicting reports on this.
Do I need to get a physical address for the DMA source address somehow?
If I recall correctly the -Mmap command line option to GCC is used to generate a map, if there isn’t a check box for this in Vitis. You may need to supply a filename too, not sure.
I recommend trying bare metal too as a quick way to know if there is something to do with FreeRTOS’s used of the interrupt controller or not. If it is, I recommend setting up the DMA after starting the FreeRTOS scheduler.
This code snippet does not seem correct to me or am I missing something? Should it not be:
uint32_t * E1vector = (uint32_t *)malloc(2160*sizeof(uint32_t));
cdma0_srcaddr_wr( (uint32_t)E1vector ); /* Added the explicit cast because I assume this function takes a uint32_t. */
It is possible to mark areas of memory as non-cacheable in 1 Meg blocks (aligned on 1 Meg boundaries. The call is Xil_SetTlbAttributes(), declared in xil_mmu.h, that header also defines some of the options; I have used DEVICE_MEMORY successfully to share memory between a cpu & a dma, but there are many other options and what you need depending upon what bus the dma is connected to.
This code is cribbed with minor variations from the Zynq network interface port for FreeRTOS+TCP: #define UNCACHED_MEMORY_SIZE 0x100000ul
static uint8_t uncached_mem[UNCACHED_MEMORY_SIZE] attribute ((aligned (UNCACHED_MEMORY_SIZE)));
Xil_SetTlbAttributes( ( uint32_t )(&uncached_mem[0]), DEVICE_MEMORY);