1
\$\begingroup\$

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?

\$\endgroup\$
  • \$\begingroup\$ Linker scripts, usually. In gcc based compilers these are text files with a .ld extension. \$\endgroup\$ – Brian Drummond Dec 11 '15 at 22:08
  • \$\begingroup\$ @BrianDrummond, This example came from an assembly file named STM32xxxx_MD_OPT.s \$\endgroup\$ – sherrellbc Dec 11 '15 at 22:13
2
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Thank you! Is the prefix .ARM. necessary or convention in this case? \$\endgroup\$ – sherrellbc Dec 14 '15 at 15:13
  • \$\begingroup\$ .ARM. is necessary when specifying the section name, but you could also place the data at the address using the at attribute. See Placement of __at sections at a specific address. Of course this only applies to ARM's own compiler, not GCC or any other. \$\endgroup\$ – Tony K Dec 15 '15 at 19:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.