cancel
Showing results for 
Search instead for 
Did you mean: 

GNU linker (arm-none-eabi-gcc 9.2.1): how to reserve 16K flash sector for user data?

timistof
Associate III

I'm working on a custom boot loader for a STM32F429, where I want to reserve the second of the first four 16K flash sectors for user data. Because the vector table has to start at 0x08000000, the memory layout would look like this:

0x08000000 - isr vector table and padding (16K)
0x08004000 - user flash sector (16K)
0x08008000 - bootloader code (224K)
------------------
0x0800C000 - application code with footer containing version and CRC (768K)

This gives me a size constraint of 256K for the boot loader code. That's why I want to use the second flash sector, because this is one of the 16K ones. Nice and small, leaving enough room for the code.

I'm using a modified version of ST's original gnu linker script:

/* Custom bootloader linker script, edited from ST's STM32F429IITx_FLASH.ld. */
 
/* Entry Point */
ENTRY(Reset_Handler)
 
/* Highest address of the user mode stack */
_estack = 0x20030000;    /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;      /* required amount of heap  */
_Min_Stack_Size = 0x400; /* required amount of stack */
 
/* Specify the memory areas */
MEMORY
{
    ISR_VECTOR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* isr_vector in first 16K sector */
    USER_FLASH (rx) : ORIGIN = 0x80004000, LENGTH = 16K /* attempt to put user flash in second 16K sector */
    FLASH (rx)      : ORIGIN = 0x08008000, LENGTH = 224K /* "regular" flash starts from the 3rd sector.Total is 256K maximum.*/
    CCMRAM (rw)     : ORIGIN = 0x10000000, LENGTH = 64K
    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 191K /* deduct 1K for NOINIT data */
    NOINIT (rwx)    : ORIGIN = 0x2002FC00, LENGTH = 1K /* NOINIT data will survive reset */
}
 
/* Define output sections */
SECTIONS
{
    /* The startup code goes first into FLASH */
    .isr_vector :
    {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Vector table */
    . = ALIGN(4);
    } >ISR_VECTOR
 
    /* Then comes user flash sector, make sure to get one of the first 4 that are 16K in size */
    .user_flash :
    {
      . = ALIGN(4);
      KEEP(*(.user_flash))
      . = ALIGN(4);
    } >USER_FLASH
 
  /* The program code and other data goes into FLASH */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)
 
    KEEP (*(.init))
    KEEP (*(.fini))
 
    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH
 
/* ...rest of sections ommitted here. */

In my "user_flash.c" file I declare the user data like this:

__attribute__((__section__(".user_flash"))) const uint32_t user_flash[0x4000 / sizeof(uint32_t)] = {0};

To list where all the sections end up after linking I run:

"arm-none-eabi-objdump -h Bootloader-V0.6"

I then get the following output:

Bootloader-V0.6:     file format elf32-littlearm
 
Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .isr_vector   000001ac  08000000  08000000  00010000  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .text         00019b28  08008000  08008000  00018000  2**6
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .rodata       000017e8  08021b28  08021b28  00031b28  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .user_flash   00004000  08023310  08023310  00033310  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .ARM.extab    00000308  08027310  08027310  00037310  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .ARM          00000360  08027618  08027618  00037618  2**2
 
#rest of output omitted

No matter what I try, I can't seem to fit ".user_flash" in between ".isr_vector" and ".text", even though I specify this in the linker script.

I've also tried to put everything in the FLASH memory region by specifying ".user_flash" like this:

.user_flash :
{
  . = ALIGN(0x4000);
  KEEP(*(.user_flash))
  . = ALIGN(4);
} >FLASH

and

.user_flash :
{
  . = 0x08004000
  KEEP(*(.user_flash))
  . = ALIGN(4);
} >FLASH

to no avail. I don't understand what's I'm doing wrong here. Perhaps a linker bug?

I could try to get ".user_flash" placed at the end of the boot loader binary, but then It will use a 128K sector and severely limit my boot loader code size: I really need the 16K one for that.

1 ACCEPTED SOLUTION

Accepted Solutions
timistof
Associate III

Hmm, I have no idea what I've done, but I managed to get it working! The linker script still is like in the first post, perhaps it was some cache variable that was updated...

View solution in original post

5 REPLIES 5
berendi
Principal

check the ORIGIN= values

I believe they are correct, in the linker script I have:

ISR_VECTOR (rx) : ORIGIN = 0x08000000, LENGTH = 16K
USER_FLASH (rx) : ORIGIN = 0x80004000, LENGTH = 16K
FLASH (rx)      : ORIGIN = 0x08008000, LENGTH = 224K

While the output of "arm-none-eabi-objdump -h Bootloader-V0.6" gives me:

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .isr_vector   000001ac  08000000  08000000  00010000  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .text         00019b28  08008000  08008000  00018000  2**6
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .rodata       000017e8  08021b28  08021b28  00031b28  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .user_flash   00004000  08023310  08023310  00033310  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

check the numbers again carefully

timistof
Associate III

Well... I've created a minimal makefile build with the same linker script, but the issue isn't appearing there. So the issue must have something to do with my IDE, CLion. There's all sorts of stuff happening in the background, so some flags might get passed there that I'm unaware of.

timistof
Associate III

Hmm, I have no idea what I've done, but I managed to get it working! The linker script still is like in the first post, perhaps it was some cache variable that was updated...