I have developed a bootloader for STM32F412, the bootloader works perfectly with bare-metal apps, 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.
Hello @Qabudhaim, thanks for your interest in FreeRTOS.
Debugging by settings LED’s can be difficult: you must be sure that the GPIO peripheral has been initialised correctly.
In circuit debugging programs: paid options are: Keil MDK-ARM, IAR Embedded Workbench, CrossWorks for ARM (Rowley Associates), and Atollic TrueSTUDIO.
I am using System Workbench (Eclipse) AC6 (v2.9), which allows me to use a makefile. You can also use STM32CubeIDE.
I wrote bootloaders for STM32F4 and STM32F7, that worked with FreeRTOS.
I changed system_stm32f4xx.c to call my checkBootloader():
#if defined(DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM)
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
+ /* Check if bootloader must become active before enabling the PLL. */
+ checkBootloader();
/* Configure the System clock source, PLL Multiplier and Divider factors,
AHB/APBx prescalers and Flash settings ----------------------------------*/
SetSysClock();
The function checkBootloader() might never return, depending on the situation.
It is implemented both in the bootloader (BL) as well as in the app. It may decide to jump from the BL to the app, or vv.
Here is a link to some sources that I developed : hal_bootlib
Don’t try to compile it, you’d loos a lot of time. But when reading it, it might give you some ideas.
I did, everything looks okay from the bootloader, however, I can’t decide if the jump is done or not.
I did after posting the issue. Still no progress, from my understanding, setting the VTOR in the bootloader makes no sense, since the app will overwrite it anyways, correct me if wrong.
On the app side, I changes the VECT_TAB_OFFSET with no progress as well.
My suspect is that the FreeRTOS is not having a fresh start after the jump comparing to the normal Run.
Is there a way to debug the app code after jumping from the bootloader, that would be really helpful. I heard that GDB can assist with this, but never tried it yet. I am using STM32CubeMx for context.
You should be able to step over the assembly to find that?
You need to ensure that the application vector table is installed correctly and the usual way to do that is to program VTOR in the bootloader. Why does your application change VTOR? Does your FreeRTOS application work without bootloader?
Yes, the the application works without the bootloader.
As far as I know, I have to update the VECT_TAB_OFFSET to match the flash address of my app in system_stm32xxxxx.c in the app directory itself, not the bootloader.
Then when the jump to the vector table occurs, the app will handle everything himself automatically.
I added
SCB->VTOR = 0x08020200
And I check the register before jumping, it is as expected, however, the jump didn’t take place.
The biggest issue with BootLoaders can be that they don’t leave with the processor in a reset like state. One big one is leaving interrupts enabled, which can cause faults if they occur before the loaded application is ready for them
The boot loader may need the interrupts themselves.
It is just a fact that “free-standing” programs are (or should be) designed to be started as if from reset, and will enable the interrupts when they are ready for them.
The problem is that with FreeRTOS, many of the ISRs are going to depend on FreeRTOS primatives having been initialized, and right when you come from the boot loader, that won’t be true. This is especially true for the tick interrupt. Thus FreeRTOS WILL enable the interrupts when it starts the first task.
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.
Is it possible to share your complete project (both bootloader and the application), so that I can give it a try? I do not have the same hardware but I can give it a try on a different ST Nucleo board.
Here is the STM32 implementation, note that you may need to have a chip that supports TRNG generation. https://github.com/Qabudhaim/STM32-Secure-Bootloader
I developed a Python CLI to drive the flashing process: https://github.com/Qabudhaim/STM32-Bootloader-CLI
Regarding the application, I am working with a FreeRTOS blinky (on PB0) that was generated using CMSIS V2 on CubeMX, not sure if it is worth sharing.
Thanks again for taking the time supporting me.
PS: I am attaching links this way as I am not allowed to post links as a new user.
I created a simple bootloader for the NUCLEO-H723ZG board and used your jump_to_application function. I successfully reproduced the HardFault. The root cause turned out to be disabling SysTick too early which was re-enabled by HAL_RCC_DeInit in the same function. This caused the bootloader to jump to the FreeRTOS application with SysTick enabled. As a result, SysTick triggered too early after jumping to the FreeRTOS application, resulting in a HardFault. Below is my working version of the jump_to_application function:
You are doing a lot of things in your bootloader. Can you try creating a simple setup:
Bootloader does nothing but just jumps to the application.
Application just have 1 or 2 tasks periodically blinking LEDs.
For this you do not need any application header. You can take a look at the project I shared for similar setup. This will help us confirm if the problem is in jump_to_application function or not.