Question
STM32F429 Secondary Bootloader (sboot) Development Difficulties
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:
- Initialize the minimal system (such as basic configurations for clocks, GPIOs, etc.);
- Initialize the external SDRAM via the FMC controller (verified to support normal read/write operations);
- Initialize the SDIO bus and FatFS file system, then mount the SD card;
- Check if boot.bin exists in the root directory of the SD card. If it exists, copy it completely to address 0xC0000000 in SDRAM;
- Jump to address 0xC0000000 in SDRAM to execute boot.bin (the application program).
Core Questions Encountered
- 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? - 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? - 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? - 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!
