Why does memory alignment matter for DMA transfers?
DMA transfers data in units of the configured transfer width — byte (8-bit), half-word (16-bit), or word (32-bit). Both the source and destination addresses must be naturally aligned to the transfer width: half-word transfers require 2-byte aligned addresses, and word transfers require 4-byte aligned addresses. This alignment requirement exists because the bus infrastructure (AHB/APB) and the memory controller expect aligned accesses for efficient operation.
Misaligned DMA transfers cause different problems depending on the Cortex-M core. On Cortex-M0, M3, and M4, an unaligned access from the DMA controller generates a HardFault — the transfer aborts and the system crashes if the fault handler does not recover gracefully. On Cortex-M7, the CPU handles unaligned accesses transparently (with a performance penalty), but the DMA controller typically does not share this capability and will either fault or silently transfer incorrect data by accessing the wrong aligned address. Additionally, when peripheral and memory transfer widths differ (e.g., packing two 16-bit ADC readings into a 32-bit memory word), the DMA's FIFO and packing/unpacking logic must be configured correctly, and the buffer alignment must satisfy the wider of the two widths.
Best practice: always declare DMA buffers with explicit alignment attributes — __attribute__((aligned(4))) for word transfers, __attribute__((aligned(32))) for Cortex-M7 cache-line alignment. When transferring arrays of structs, verify that the struct size is a multiple of the transfer width and that padding does not introduce gaps. A common bug: defining a DMA buffer inside a function as a local variable on the stack — stack alignment is compiler-dependent and may not satisfy DMA requirements, plus the buffer is invalid after the function returns while DMA may still be writing to it.
Source: DMA Q&A
