cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F429 Secondary Bootloader (sboot) Development Difficulties

RaidenMEI
Associate II
Hello everyone, I'm developing a secondary bootloader (sboot) based on the STM32F429 chip, aiming to achieve "program updates without a programmer" — simply placing the compiled application file on an SD card allows the microcontroller to automatically load and run it upon power-up, greatly simplifying debugging and update processes. Currently, I'm using Cube IDE for development, with the following hardware configuration:

 

  • Main controller: STM32F429 (internal Flash stores sboot; internal SRAM starts at 0x20000000 with a capacity of 256KB)
  • External storage: Kioxia 64GB SD card (connected via the SDIO bus, used to store the application program boot.bin)
  • External memory: 32MB SDRAM (starts at address 0xC0000000, driven by the FSMC controller, used to load and run boot.bin)

Functional Process Description

The sboot is 固化 (burned) in the STM32's internal Flash. Upon power-up, it executes the following steps:

 

  1. Initialize the minimal system (such as basic configurations for clocks, GPIOs, etc.);
  2. Initialize the external SDRAM via the FMC controller (verified to support normal read/write operations);
  3. Initialize the SDIO bus and FatFS file system, then mount the SD card;
  4. Check if boot.bin exists in the root directory of the SD card. If it exists, copy it completely to address 0xC0000000 in SDRAM;
  5. Jump to address 0xC0000000 in SDRAM to execute boot.bin (the application program).

Core Questions Encountered

  1. Selection and modification of linker scripts (LD files)
    Cube IDE generates two default linker scripts: flash.ld (for scenarios where the program is stored and runs in internal Flash) and ram.ld (for scenarios where the program runs in internal RAM). However, my application needs to be stored on the SD card and ultimately loaded to run in external SDRAM (0xC0000000). In this case, which script should I base my modifications on?
    What key configurations need to be adjusted (such as the start address and size of the FLASH/RAM segments, the _estack top-of-stack address, the mapping relationships of segments like _sidata/_sdata, etc.) to ensure the program loads correctly into SDRAM and runs properly?
  2. Location selection for Heap and Stack
    Should the application's heap and stack be placed in internal SRAM (starting at 0x20000000) or external SDRAM (starting at 0xC0000000)?
    A comparison of the pros and cons of the two options: Internal SRAM is fast but has limited capacity (256KB), which may restrict applications with large heap/stack requirements; external SDRAM has large capacity (32MB) but depends on FMC stability and has slightly slower access speeds. From the perspective of compatibility and stability, which option is more recommended?
  3. Configuration of the NVIC interrupt vector table
    When sboot is running, the interrupt vector table points to internal Flash by default (0x08000000); while the application runs in SDRAM (0xC0000000), and its vector table is also located in SDRAM.
    How to ensure that the application's interrupts respond correctly? Do I need to modify the SCB->VTOR register to point to the vector table in SDRAM before sboot jumps, or should the application modify it during its own initialization? Additionally, does the STM32F429 have alignment requirements for the vector table address (such as 0x200 alignment) that need special attention?
  4. Necessity of modifying the application's startup.s
    I'm concerned that the application's startup file (startup_stm32f429xx.s) may re-initialize hardware already configured by sboot, causing conflicts:
    • sboot has already initialized the external SDRAM via FMC. If the application's startup.s or SystemInit function re-initializes FMC, it may overwrite timing parameters, leading to SDRAM access failures (the application itself runs in SDRAM and will crash directly);
    • sboot has configured the system clock (e.g., PLL enabled, HCLK=180MHz). If the application re-initializes the clock tree, it may cause timing errors in peripherals such as SDIO and FMC;
    • Other potential conflict points: such as GPIO multiplexing configurations, NVIC priority grouping, etc.
    Therefore, must the application's startup.s be modified? Specifically, which initialization steps need to be deleted (such as FMC configuration, clock initialization), and which can be retained (such as basic core initialization)? Are there safer modification methods (e.g., masking specific initializations via macros)?

 

Thank you for your help!
1 REPLY 1
gbm
Principal

1. No big difference but probably RAM configuration is closer to what you want to achieve because of data section handling. You need to define your DRAM memory area and then assign some (almost all) sections to it. It may be a good idea to use internal RAM for .data section.

2. In a properly written program stack should be relatively small, no more than few KiB, so put in in on-chip RAM for faster access. If the heap is used, then it's probably big, so put it in DRAM. After you get the basic setup working, you should think about moving some critical parts of code, esp. ISRs to on-chip RAM. If you don't modify the linker scrip too heavily, the vector table will be correctly placed at the start of memory, so no alignment problems here.

3. VTOR may be set by the bootloader or the app - no big difference. In my code I always initialize it in the bootloader.

4. If the memory interface is initialized by the bootloader, replace the app's SystemInit with you own, empty implementation. Also, remove any CubeMX-generated clock initialization functions from the app code. startup.s should only be modified if you want to use both internal RAM and external DRAM, which is probably the case in any reasonable project. You don't need to modify it if you use only DRAM, so maybe start with this configuration and upgrade later.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice