2025-07-26 3:55 PM
Hi all,
I have developed a bootloader for STM32F412, the bootloader works perfectly, however, when I change the user app to be FreeRTOS based, it ceases to work.
I added a blink led in the Hard Fault in both the bootloader and app, but both were not triggered.
Any idea what is going on?
void jump_to_application(void) {
void (*app_reset_handler)(void);
uint32_t msp_value = *(volatile uint32_t*)(APP_START_ADDRESS + APP_HEADER_SIZE);
uint32_t reset_handler_address = *(volatile uint32_t*)(APP_START_ADDRESS + APP_HEADER_SIZE + 4);
__disable_irq();
HAL_RCC_DeInit();
HAL_DeInit();
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
for (uint32_t i = 0; i < 8; i++)
{
NVIC->ICER[i] = 0xFFFFFFFF;
NVIC->ICPR[i] = 0xFFFFFFFF;
}
__enable_irq();
__set_MSP(msp_value);
__set_PSP(msp_value);
__set_CONTROL(0);
app_reset_handler = (void*)reset_handler_address;
app_reset_handler();
}
Thanks in advance.
Regards,
Solved! Go to Solution.
2025-07-27 2:26 PM
Yes. The bootloader is setting the MSP to the app.
Moreover, I have changed the VECT_TAB_OFFSET on the application side. Still not working.
I suspect, cleaning and de-initialization is the problem here. But not able to figure out where exactly is the problem.
Looks like FreeRTOS is not having a fresh start.
2025-07-30 12:42 PM
Hi all,
Few updates:
I did many experiments, unfortunetly none of them worked.
1- Now the FreeRTOS applications start at 0x08040000
2- I use GDB to debug the application, and it shows that the jump was done, but stuck in the hard fault.
3- These are my registers
(gdb) info registers
r0 0x1 1
r1 0xe000e100 -536813312
r2 0x8041e04 134487556
r3 0xbe1fc 778748
r4 0xbe1fd 778749
r5 0x0 0
r6 0x0 0
r7 0x2003ffe0 537133024
r8 0x0 0
r9 0x0 0
r10 0x0 0
r11 0x0 0
r12 0x80000000 -2147483648
sp 0x2003ffe0 0x2003ffe0
lr 0xfffffff9 -7
pc 0x804075c 0x804075c <HardFault_Handler+4>
xPSR 0x1000003 16777219
fpscr 0x0 0
msp 0x2003ffe0 0x2003ffe0
--Type <RET> for more, q to quit, c to continue without paging--
psp 0x0 0x0
primask 0x1 1
basepri 0x0 0
faultmask 0x0 0
control 0x0 0
(gdb) x/x $pc
0x804075c <HardFault_Handler+4>: 0xb480e7fd
(gdb) 4- The final version of my jump function
void jump_to_application(void) {
void (*app_reset_handler)(void);
uint32_t app_msp = *(volatile uint32_t*)(APP_START_ADDRESS + APP_HEADER_SIZE);
uint32_t reset_handler = *(volatile uint32_t*)(APP_START_ADDRESS + APP_HEADER_SIZE + 4);
__disable_irq();
// Stop SysTick
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
HAL_RCC_DeInit();
HAL_DeInit();
for (uint32_t i = 0; i < 8; i++) {
NVIC->ICER[i] = 0xFFFFFFFF;
NVIC->ICPR[i] = 0xFFFFFFFF;
}
// Optionally clear DMA/USB specific IRQs
__HAL_RCC_USB_OTG_FS_CLK_DISABLE();
HAL_NVIC_DisableIRQ(OTG_FS_IRQn);
__HAL_RCC_DMA1_FORCE_RESET();
__HAL_RCC_DMA1_RELEASE_RESET();
// Set vector table to application
SCB->VTOR = APP_START_ADDRESS + APP_HEADER_SIZE;
__DSB();
__ISB();
__set_MSP(app_msp);
__set_CONTROL(0); // Privileged + use MSP
__DSB();
__ISB();
app_reset_handler = (void (*)(void))reset_handler;
app_reset_handler();
}5- VTOR value is 0x08040000
6- My linker script is
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K
FLASH (rx) : ORIGIN = 0x8040000, LENGTH = 128K
}
2025-07-30 10:18 PM
> the jump was done, but stuck in the hard fault
in the next step or somewhere later? Can you find our where? Call stack?
Segger has a nice kb article about fault analysis and a diagnostic fault handler: https://kb.segger.com/Cortex-M_Fault
hth
KnarfB
2025-11-12 11:51 PM - edited 2025-11-12 11:52 PM
After investigating the binaries of both the bare-metal and FreeRTOS applications, I discovered the following: although both apps use the same linker script and startup code, FreeRTOS enforces a stricter alignment on memory sections. This caused the .text section to shift by three words, leaving a gap of three words filled with 0x00 after the .isr_vector section, which ultimately led to the PRECISERR fault.
Adding the linker option --gap-fill=0xFF in the post-build steps resolved the issue. By default, .bin and .hex files do not include gap-filling, whereas flashing the memory via the debugger automatically fills these gaps. This explains why the application worked when flashed through the debugger but not when loaded by my bootloader.
Additionally, in the bare-metal build, the .text section starts immediately after the .isr_vector section, whereas in the FreeRTOS build, a 16-byte alignment is enforced instead of the 4-byte alignment used in bare metal.
I haven’t yet identified exactly where does this alignment requirement come from, but the issue is now resolved, and the bootloader is running smoothly.
For context, I am using FreeRTOS CMSIS V2, and the files are generated using STM32CubeMX.
2025-11-13 2:01 PM
> SCB->VTOR = APP_START_ADDRESS + APP_HEADER_SIZE
> 5- VTOR value is 0x08040000
So APP_START_ADDRESS is 0x08040000... Then what is the value of APP_HEADER_SIZE?
2025-11-14 12:02 AM
I was doing a few experiments, so the addresses were not finalized yet. The current configuration is as follows:
The header has a size of 0x200 bytes starting at 0x08020000, followed by the application binary starting at 0x08020200.