DMA, cache and linker script
Move buffers between DDR, OCM and BRAM, maintain cache coherence and place ELF sections in the correct memory.
Why DMA matters
A CPU copy consumes instructions for every word. A Direct Memory Access controller, or DMA, receives a transfer description and becomes a bus master. It moves a block without making the processor copy each word. The processor can then do other work or wait for a completion interrupt.
To make memory and cache effects measurable, this course provides a DMA benchmark. It measures four paths: DDR to DDR, BRAM to BRAM, DDR to BRAM and BRAM to DDR. It repeats 4096-word blocks, measures TTC cycles and checks every destination word. A timing result without data verification can hide an address or cache error.

Preparing a transfer
for (u32 i = 0; i < word_count; i++) {
source[i] = 0x10000000U + i;
destination[i] = 0U;
}
Xil_DCacheFlushRange((UINTPTR)source, word_count * sizeof(u32));
start_dma(source, destination, word_count);
wait_for_dma_done();
Xil_DCacheInvalidateRange((UINTPTR)destination, word_count * sizeof(u32));Zynq-7000 can use the PS PL330 through XDmaPs. Zynq UltraScale+ MPSoC provides other engines, including ZDMA through XZDma. The cache rules remain the same.
Cache maintenance
The processor and DMA can observe different versions of one buffer. A cache flush writes modified source lines back to memory before the DMA reads them. Invalidation discards stale destination lines after a DMA write, forcing the processor to fetch the new data.
| DMA operation | CPU action |
|---|---|
| DMA reads CPU-produced data | Clean or flush the source |
| DMA writes CPU-consumed data | Invalidate the destination after completion |
| Coherent DMA path | Use correct memory attributes and coherent port |
Disabling all caches can isolate a defect. It is rarely an acceptable production solution.
Buffers must meet controller alignment and length requirements. Cache maintenance ranges must cover all touched cache lines.
ELF sections and the linker
The compiler produces sections such as .text, .rodata, .data and .bss. The linker script is the file that maps these sections to physical memory regions. Main code can remain in DDR while a critical ISR is placed in OCM.
MEMORY
{
psu_ddr : ORIGIN = 0x00100000, LENGTH = 0x1FF00000
psu_ocm : ORIGIN = 0xFFFC0000, LENGTH = 0x00040000
}
SECTIONS
{
.text : { *(.text*) } > psu_ddr
.fast_isr : { *(.fast_isr*) } > psu_ocm
}void __attribute__((section(".fast_isr"))) dma_isr(void *ref)
{
dma_done = 1U;
}The selected memory must be initialized and accessible to the target processor. Space must also be reserved for data, heap and stack.
Measuring correctly
A CPU versus DMA comparison should include setup, cache maintenance and completion handling. DMA is valuable for sufficiently large or repeated transfers. Its fixed overhead can exceed a small CPU copy.
Official references
The Zynq-7000 Technical Reference Manual UG585 covers PS memories and DMA. The official AXI DMA driver documentation covers a PL-based DMA.
Key points
DMA moves data but does not automatically make CPU caches coherent. Software prepares buffers, starts the transfer, handles completion and maintains caches. The linker script selects the memory used by each program section.
Test your knowledge - Chapter quiz