So, having a look at the datasheet for a specific ARM controller, we find the address space to be mapped out as follows:
There are number of ways to accomplish this, one of which is through an auto-generated file that has the following (condensed) contents:
; Option byte organization
;-------------------------
; Address [31:24] [23:16] [15:8] [7:0]
; 0x1FF80000 - nRDP - RDP (0xFF5500AA)
; 0x1FF80004 - nUSER - USER (0xFF870078)
; 0x1FF80008 nWRP1 nWRP0 WRP1 WRP0 (0xFFFF0000)
; 0x1FF8000C nWRP3 nWRP2 WRP3 WRP2 (0xFFFF0000)
FLASH_OPT EQU 1
RDP EQU 0xAA
nRDP EQU RDP:EOR:0xFF
WRP00 EQU 0x00
WRP01 EQU 0x00
WRP02 EQU 0x00
WRP03 EQU 0x00
nWRP00 EQU WRP00:EOR:0xFF
nWRP01 EQU WRP01:EOR:0xFF
nWRP02 EQU WRP02:EOR:0xFF
nWRP03 EQU WRP03:EOR:0xFF
USER EQU 0x78
nUSER EQU USER:EOR:0xFF
IF FLASH_OPT <> 0
AREA |.ARM.__AT_0x1FF80000|, CODE, READONLY
DCB RDP, 0x00, nRDP, 0xFF
DCB USER, 0x00, nUSER, 0xFF
DCB WRP00, WRP01, nWRP00, nWRP01
DCB WRP02, WRP03, nWRP02, nWRP03
ENDIF
It appears as if this file is simply giving a nicely configurable way to set these option bytes, but how is it being done? I did a bit of research and it turns out that the AREA
directive tells the assembler to generate a new area, in this case a code area that will be read only.
Further, the DCB
directive allocates memory, in this case 16 bytes, and initializes them with the respective values given.
My question, then, is where is the specification regarding this newly allocated memory block's location? Namely, how does the value of this 16 byte block get written to the appropriate registers (0x1FF80000, etc) ?
The only mention of this address is given by the |.ARM.__AT_0x1FF80000|
argument passed to AREA
. However, this first argument is only the name of this new area according to the documentation.
Or maybe the better question is: How can we specify where an AREA will be stored in memory?
Best Answer
The ARM linker automatically places sections prefixed with
__at
in the specified address. In C code, you would specify the section using thesection
attribute, like this:You can control the behaviour by passing --autoat or --noautoat to the linker.
See Placement of a key in flash memory with an __at section from the ARM Linker User Guide for more details.