1
votes

I'm creating a bootloader for STM32F429 with the gnu toolchain (9.2.1) and trying to reserve some flash memory for user data, shared by bootloader and application. I want to reserve the second of its first four 16K flash sectors for this, since they're nice and small: all other sectors are 128K. The memory layout should look look like this:

ISR vector table : 0x08000000 (428 bytes)
padding          : 0x080001ac (15956 bytes)
-----------------------------
user data        : 0x08004000 (16K)
-----------------------------
bootloader code  : 0x08008000 (max 224K, for total of max. 256K)

I have modified ST's linker script to look like this:

/* Specify the memory areas */
MEMORY
{
    FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 256K /* max. bootloader binary size */
    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)) /* Startup code */
    . = ALIGN(4);
    } >FLASH

    /* Then comes user flash sector, make sure to get one of the first 4 that are 16K in size
    .user_flash :
    {
      . = ALIGN(0x4000)
      KEEP(*(.user_flash))
      . = ALIGN(0x4000)
    } >FLASH

    /* ... more sections below not shown here */
}

In my bootloader.cpp, I declare the user flash as follows:

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

However, in the debugger, the address of user_flash is not 0x08004000 as expected, but 0x0801b4e8.

Removing the __attribute__((__section__(".user_flash"))) from the declaration yields a different adress, proving the attribute has at least some effect.

Running arm-non-eabi-objdump -h on the .elf file confirms the (incorrect) adress of the user_flash section. I have also tried declaring the section with . = 0x08004000, to no effect.

Another approach I tried is to place .isr_vector in its own 16K section, followed by a 16K section for the user flash and finally a (256-16-16) = 224K FLASH section. This produced a bogus binary that would hardfault.

What am I doing wrong here?

Edit:

I've tried inserting a .padding section after .isr_vector to try to align .user_flash that way, but no matter what I do, .text and .rodata sections seem to always come immediately after .padding, even though they are declared after the .user_flash section.

1
Changed title and clarified desired memory layour.Tim Walther

1 Answers

1
votes
/* move the NVIC because we are running from 08004000 */
SCB->VTOR = (FLASH_BASE | 0x4000);