Electronic – Programming ARM Option Bytes using Assembly Directives

armassemblyfuse-bits

So, having a look at the datasheet for a specific ARM controller, we find the address space to be mapped out as follows:

enter image description here

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 the section attribute, like this:

// place flash_key in a section called .ARM.__at_0x8000
long flash_key __attribute__((section(".ARM.__at_0x8000")));

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.