A scatter load file is an essential component when building applications for ARM Cortex-M based microcontrollers. It defines the memory layout of the target application by specifying the memory regions, their addresses, sizes, and access permissions. A properly configured scatter file ensures code and data are placed correctly for optimum performance and efficiency.
What is a Scatter Load File?
A scatter load file provides a description of the target memory map to the linker. It defines one or more memory regions along with their start addresses, sizes, and access permissions (read/write/execute). The linker uses this memory map to allocate sections from the compiled object files into the appropriate memory regions.
For Cortex-M devices, the scatter file typically defines separate regions for flash memory, RAM, and device peripherals. It ensures that code and readonly data are placed in flash, writable data goes into RAM, and that no application code overlaps with reserved peripheral address spaces.
Why is a Scatter File Important?
The scatter file serves several important purposes:
- Defines the memory map and ensures no memory regions overlap.
- Allows placing code, constants and data in appropriate memory regions.
- Enforces memory access permissions (read/write/execute).
- Prevents application code/data interfering with peripheral registers.
- Optimizes memory usage by eliminating unused gaps.
- Improves performance by placing frequently used code and data in faster memory.
Without a scatter file, code and data sections would be linked in arbitrary order, leading to overlaps or wasted memory gaps. The application may also fail to work correctly if code or data is placed in inappropriate memory regions.
How to Create a Scatter File
Here are some guidelines for creating an effective scatter load file for Cortex-M applications:
- List memory regions in ascending order of start address – List flash first, then RAM, and finally device peripherals. This allows the linker to allocate sections in a natural order.
- Define anORIGIN and LENGTH for each region – ORIGIN sets the start address and LENGTH sets the size. Ensure lengths match the microcontroller’s memory sizes.
- Set access permissions – Flash regions should have rx (read-execute) permissions. RAM can be rw (read-write). Peripherals are typically r (read-only).
- Reserve memory for stack and heap – Define a RW_IRAM1 region at end of RAM for stack and heap. Size it appropriately for your application requirements.
- Create sections for code, constants and initialize/uninitialized data – Use *(.text*), *(.rodata*) and *(.data*) to allocate code, constants and initialzed data.
- Place vector table in a dedicated section – Define a vector_table section at the very beginning of flash to hold the interrupt vector table.
- Define empty “FILL” regions between memory areas – FILL regions pad unused address ranges between defined memory regions to avoid gaps.
- Comment extensively – Use comments to document all memory regions, sections and linker options used.
- Export symbols for memory region start/end – Helps catch errors if code/data overflows memory area at runtime.
Scatter File Memory Regions
Here are some of the most common memory regions defined in Cortex-M scatter files:
- FLASH – Holds code and read-only data. Located at start of microcontroller memory map.
- RAM – Used for writable global, static, heap and stack data. Located after flash.
- ITCMRAM – Instruction Tightly Coupled Memory – fast RAM for critical code.
- DTCMRAM – Data Tightly Coupled Memory – fast RAM for performance critical data.
- Peripherals – Memory mapped registers for on-chip peripherals.
- Vector Table – Special section mapped to start of flash for interrupt vectors.
The scatter file also defines logical groupings of code and data within these memory regions, such as .text, .data, .bss and stack/heap sections.
Typical Flash Memory Sections
The following kinds of read-only code and data typically reside in the flash memory region:
- .text – Program code sections.
- .rodata – Readonly global and static data.
- .ARM.exidx – Exception unwinding information used for stack traces.
- .debug – Embedded debug table information.
- .vector_table – Interrupt vector table at start of flash.
- .lib – Code sections from standard libraries.
Typical RAM Memory Sections
Following writable data sections generally go in RAM:
- .data – Initialized global and static variables.
- .bss – Zero initialized global and static variables.
- .heap – Dynamic memory allocated at runtime by malloc etc.
- .stack – Stack to hold thread/task control blocks and stack frames
Scatter File Optimization Tips
Some tips for optimizing placement of code/data in the scatter file:
- Place performance critical code in ITCM/DTCM for faster execution.
- Frequently used variables in DTCM for quickest access.
- Related code/data sections together for locality.
- Main stack/heap at opposite ends of RAM to prevent collisions.
- Vector table closest to bottom of flash for predictable offsets.
Careful scatter file design is key to utilizing the Cortex-M memory architecture effectively for performance and efficiency.
Scatter File for C++ Applications
For C++ applications, the scatter file also ensures correct ordering of static initialization and termination by the runtime. Additional sections like .init_array, .fini_array and .ARM.exidx must be defined.
The C++ compiler may also generate much larger read-only data for type information and virtual tables. So the linker scatter file needs to accommodate the potentially larger read-only data sections.
Scatter File Validation
It is important to validate the scatter file thoroughly before deploying to production. Some ways to validate:
- View the linker map file to ensure sections are assigned appropriate memory areas.
- Size reports to check RAM/flash usage is within limits.
- Load image into target board to test actual runtime behavior.
- Stress test by placing code/data in all regions and at region boundaries.
Catching issues early in development by scatter file validation can prevent painful debugging later.
Linker Control Directives
In addition to the memory map, scatter files provide fine-grained control over placement of sections using directives like:
- FIXED – Fixes a section to a specific address
- ALIGN – Aligns section start on a specified boundary
- AT() – Places an object at a specific address
Directives override default placement rules to cater to specialized needs.
In summary, the scatter load file is a key component in building robust, efficient applications for ARM Cortex-M microcontrollers. It provides fine-grained control over the memory layout to optimize execution performance, memory usage, and prevent errors. Leveraging scatter file features correctly can help developers take full advantage of the Cortex-M architecture.