In this lesson, you will learn how to use ALIGN commands within your linker scripts to ensure that memory sections start on specific byte boundaries required by your hardware.
Why Alignment Matters
Embedded processors often demand strict memory alignment for performance and hardware correctness. For example, a Direct Memory Access (DMA) controller might require a data buffer to start on a 32-byte boundary, or a vector table might need to be aligned to a power of two to satisfy the CPU’s architectural requirements. If a section starts at an arbitrary address, you might experience bus errors or a significant performance penalty.
Controlling Boundaries with ALIGN
When writing a linker script, you manage the location counter—the special symbol .—to dictate where sections are placed. The ALIGN command forces the linker to move the location counter to the next address that is a multiple of your specified value.
Consider this example where we need to place a hardware configuration block on a 16-byte boundary:
SECTIONS
{
.hardware_config :
{
. = ALIGN(16);
KEEP(*(.hw_data))
} > FLASH
}
In this snippet, ALIGN(16) inspects the current value of .. If the previous section ended at address 0x08000005, the linker will automatically insert 11 bytes of "padding" to bump the counter to 0x08000010. This ensures that every time your code accesses this section, it begins exactly where the hardware expects it.
Dealing with Padding
It is important to remember that ALIGN creates invisible padding. While the linker handles the math, you should be mindful of your overall memory footprint. Every byte of padding consumed is a byte of memory that cannot be used for application code or data. In resource-constrained systems, aggressive alignment can lead to fragmentation, so use the minimum alignment power-of-two necessary to satisfy the hardware requirements.
If you don't use ALIGN, the linker will pack sections as tightly as possible, which might cause your code to span across cache line boundaries or misalign critical memory-mapped peripherals.
Key Takeaway: Use the ALIGN(n) command in your linker script to force the location counter to a multiple of n, ensuring hardware-specific boundary requirements are met through the insertion of necessary padding bytes.