You copied the Doc URL to your clipboard.

Target hardware and the memory map

It is better to keep all information about the memory map of a target, including the location of target hardware peripherals and the stack and heap limits, in your scatter file, rather than hard-coded in source or header files.

Mapping to a peripheral register

Conventionally, addresses of peripheral registers are hard-coded in project source or header files. You can also declare structures that map on to peripheral registers, and place these structures in the scatter file.

For example, if a target has a timer peripheral with two memory mapped 32-bit registers, a C structure that maps to these registers is:

__attribute__((zero_init)) struct
    volatile unsigned ctrl;           /* timer control */
    volatile unsigned tmr;            /* timer value   */
} timer_regs;

You can also use __attribute__((at(address))) to specify the absolute address of a variable.

Placing the mapped structure

To place this structure at a specific address in the memory map, you can create an execution region containing the module that defines the structure. The following example shows an execution region called TIMER that locates the timer_regs structure at 0x40000000:

ROM_LOAD 0x24000000 0x04000000
; ...
TIMER 0x40000000 UNINIT
        timer_regs.o (+ZI)
    ; ...

It is important that the contents of these registers are not zero-initialized during application startup, because this is likely to change the state of your system. Marking an execution region with the UNINIT attribute prevents ZI data in that region from being zero-initialized by __main.