2024-08-16 07:49 AM
Hi everyone, I'm developing a bootloader that works like this. I was inspired by the example: https://github.com/pramodk51/bootloader_for_stm32f4.
I developed this initially on Nucleo F439ZI for the test phase and I managed to implement it with the addition of DFU functionality. The principle was simply to send a program that lights a led per uart that the bootloader would store and then go to this memory location to make it work (2 slots, one for the recent version and the other for the backup).
Note: I didn't develop the whole thing in the same code, I have bootloader code and application code, so 2 linker scripts etc ...
Once the test was functional and robust, I decided to integrate it into my personal project. My application this time is much more complex than turning on a LED, it uses FreeRTOS and is also much larger (but respects the size specified in the slot).
In terms of the application I've reproduced exactly the same operation so that it adapts to the slot automatically with the
SCB->VTOR
. Obviously the code I generate is adapted to the slot in which it will be placed using the linker script.
So when it comes to restarting, everything should work in the same way as when I carried out my tests on nucleo. However, I'm not getting any results from my tests.
My application program won't launch even though the bootloader redirects to the correct slot and updates the reset handler (check against the .map). But after that I have nothing. I have an IWDG function on the bootloader and the application and at the end of each WDG delay I loop back to the bootloader because nothing happens.
My problem is that I'm reproducing exactly the same pattern as during my configuration tests and the result is different.
I suspect a difference in treatment when using FreeRTOS but I haven't found anything on the subject. Are there any parameters that need to be managed to ensure correct operation?
I apologise in advance for my lack of clarity and information. I don't want to confuse you with too many documents, so I'd rather give you the information you find relevant.
I'll leave it to you while I continue my research and thank the ST community in advance for reading me.
All the best.
Solved! Go to Solution.
2024-08-26 10:46 PM
Hello everyone, here's a little feedback on this topic. Following these exchanges I decided to go back to my problem and I finally found that the solution was in the SystemClockConfig(), a flag error already raised for the clock, most probably due to the fact that I was setting the clock first in the bootloader and then in the application. Thanks to those who tried to help me.
2024-08-16 09:41 AM
You should be able to run in debug configuration to figure out what "doing nothing" means. The CPU is executing code somewhere, possibly stuck inside an interrupt, or at the wrong interrupt code address. If you don't have a debug context, you can use the PC register to find out what code is being run and the VECTACTIVE field in the SCB registers somewhere to figure out which interrupt it's in, if any. Probably want to disable the watchdogs during the debug process.
2024-08-16 10:02 AM
Is your header size linker set 1K ? But primary question is how plan you have to load firmwares?
2024-08-16 12:24 PM - edited 2024-08-16 12:25 PM
Thank you for your reply.
I can't debug because it's my bootloader that runs the program and it doesn't show me any Error_Handler() or anything else. I'm still learning, so if there's a way of accessing the debugging of my application code while I'm on my bootloader code, I'm all ears.
If it's not possible, I don't understand how I can access what you call the ‘PC registry’ and how to view the SCB fields. I'm trying to learn about debugging and its functions as I go along, but I'm the only developer in my company, so I'm forced to develop in a hurry - please excuse my lack of knowledge.
2024-08-16 12:32 PM
Yes, my header is 1K. It worked during my tests on nucleo and the ‘blink’ application. As far as the firmware is concerned, the final aim is to download it via UART (sent by an ESP32). This has already been done and is working on the test version.
This is what seems strange to me: everything worked perfectly on a ‘blink’ application but with my FreeRTOS application nothing works any more. Attached is my script linker for more information.
Note: For the integration tests of my RTOS application I put the program myself using ST-Link utility in the right memory location and that's how I realised that it wasn't working and that was to remove any doubt as to the source of the error in the UART update. I'd also like to point out that everything I've mentioned I've already tested with my test application and it worked.
2024-08-17 01:39 AM
Primary when you have ESP32 why not connect next one pin and control BOOT0 pin = use internal systemloader? Here only one app in normal place exist in flash 8000000...
But ok you try make thing complicated, then your script link seems be ok, but isnt only change required for code work on other place... Seems you use cube IDE then in file system_stm32f4xx.c you require make changes. enable and set ...
/* Note: Following vector table addresses must be defined in line with linker
configuration. */
/*!< Uncomment the following line if you need to relocate the vector table
anywhere in Flash or Sram, else the vector table is kept at the automatic
remap of boot address selected */
#define USER_VECT_TAB_ADDRESS
#if defined(USER_VECT_TAB_ADDRESS)
/*!< Uncomment the following line if you need to relocate your vector Table
in Sram else user remap will be done in Flash. */
/* #define VECT_TAB_SRAM */
#if defined(VECT_TAB_SRAM)
#define VECT_TAB_BASE_ADDRESS SRAM_BASE /*!< Vector Table base address field.
This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
#else
#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field.
This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET 0x00020400U /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
#endif /* VECT_TAB_SRAM */
#endif /* USER_VECT_TAB_ADDRESS */
2024-08-17 02:00 AM
Let me clarify if that wasn't clear. I'm using an STM32 and it's the ESP32 that simply sends me the file (the problem occurs on the STM32). And my aim with the bootloader is to have a recent version and a backup version, which is why I'm complicating things (perhaps it was possible using the internal loader, but I wasn't aware of that).
As for the address vector table, I've already configured it in the system_stm32f34xx.c file. I tested this method on my nucleo during the blink test and it worked.
extern uint32_t _estart; // Déclaration externe du symbole défini dans le linker script
void SystemInit(void)
{
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
/* Configure the Vector Table location -------------------------------------*/
#if defined(USER_VECT_TAB_ADDRESS)
SCB->VTOR = (uint32_t)&_estart; /* Vector Table Relocation in Internal SRAM */
#endif /* USER_VECT_TAB_ADDRESS */
}
‘_estart’ being the original address of the flash according to the linker script used.
/* Memories definition */
MEMORY
{
HEADER (rx) : ORIGIN = 0x08020000, LENGTH = 1K
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K
FLASH (rx) : ORIGIN = 0x8020400, LENGTH = 383K
}
/* Sections */
SECTIONS
{
/* Assignation de l'adresse de la table des vecteurs */
_estart = ORIGIN(FLASH);
2024-08-17 02:31 AM
Are you sure that your SB is compiled ...ifdef?? And comment say vector in RAM, but your is in flash.
You test your full code on nucleo? Show your code for jump to app.
Check if your code loaded work alone started with stlink command go 8020400 ?
2024-08-17 02:01 PM
Yes, the #define used to activate the SCB line is active.
#define USER_VECT_TAB_ADDRESS
#if defined(USER_VECT_TAB_ADDRESS)
/*!< Uncomment the following line if you need to relocate your vector Table
in Sram else user remap will be done in Flash. */
/* #define VECT_TAB_SRAM */
#if defined(VECT_TAB_SRAM)
#define VECT_TAB_BASE_ADDRESS SRAM_BASE /*!< Vector Table base address field.
This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
#else
#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field.
This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
#endif /* VECT_TAB_SRAM */
#endif /* USER_VECT_TAB_ADDRESS */
Sorry, the comment is the result of a copy error.
I tested the entire code on Nucleo. I'll explain the tests again:
UT = St Link utility
- Test 1: Programming the bootloader to address 0x08000000 with UT and programming the blink program to address 0x08020000 (1st slot) also with UT. The bootloader returns the blink and works even after reset (nucleo button).
- Test 2: Addition of the blink program at address 0x080a0000 (2nd slot) with a higher version because the bootloader starts the application with the most recent version (version present in the application header). Functional test in slot2, even with the Nucléo button reset.
- Test 3: Using the DFU UART. Using a python script to send the .bin files for the blink programs. (To be precise, I created a linker script adapted to each slot and the bootloader will decide which .bin to use at the time of the DFU. This is the best way I've found to manage this dynamically, even though there may be simpler ways). Functional tests, sending and writing to memory went perfectly and start-ups according to versions worked.
- Test 4 (final nucleo): Using the DFU UART with the ESP32. This time the bin firmwares were communicated via local wifi to the esp, which sent them via UART to the STM32. Same functional result on the 2 slots.
- Test 5 (integration into the project): Implementation of the same general configuration on the application program, use of the same bootloader but no start-up. However, the application program launched at address 0x08000000 launched very well without any bugs. The only difference between the 2 programs? File size -> blink = 13kB | App = 103kB (383kB per SLOT on Linker script | Sector 5.6.7 -> slot1 with 128kB per sector and slot2 -> Sector 9.10.11 with 128kB per sector) and FreeRTOS present on the integration program and not present on the blink program. Does FreeRTOS have any special configurations for this?
When you say ‘Check if your code loaded work alone started with stlink command go 8020400?’ What do you mean? That I'm launching the program in slot 2 directly without a bootloader? Is this possible? If so, do I just need to send the program to the slot2 address where I have to check a few parameters before it can run? Note that I use ST Link utility for programming if I ever need to switch to ST Cube MX.
Thank you for your time. For more information and clarity, I'm going to provide you with the important files that will help you better understand my project and my problem.
Bootloader-App-Tbox being the non-functional project where I have removed the files related to the project for confidentiality reasons but I have left all the files related to the problem encountered.
Bootloader_stm32f439zi is the project created on Nucleo and fully functional.
Thanks again for your help.
2024-08-18 12:33 AM
UT Stlinkutility or better new stprogrammer have cmd line variant. Here you can send command -Run address .
c:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility>ST-LINK_CLI
STM32 ST-LINK CLI v3.3.0.0
STM32 ST-LINK Command Line Interface
Available commands:
===================
-c Connect to the device using JTAG or SWD.
Syntax: -c [ID=<id>/SN=<sn>] [JTAG/SWD SWCLK=<f>] [UR/HOTPLUG] [LPM]
[RM=Hrst/Srst/Crst]
[ID=<id>] : id (Identifier) of ST-LINK [0..9] to use when multiple
probes are connected to the host
[SN=<sn>] : sn (Serial Number) of the chosen ST-LINK probe
[AP=<ap>] : ap (Access Port Number) default value is 0
[UR] : Connect to target under reset
[HOTPLUG] : Connect to target without halt or reset
[LPM] : Activate debug in Low Power mode
[Hrst] : Activate Hardware Reset mode
[Srst] : Activate Software system Reset mode
[Crst] : Activate Core Reset mode
[Freq=<frequency>] : Frequency value in KHz
Example: -c ID=1 SWD SWCLK=5 UR LPM
Example: -c ID=1 JTAG JTAGCLK=6 UR
Example: -c SN=55FF6C064882485358622187 SWD UR LPM
Note: When [ID=<id>] and [SN=<sn>] are not specified, the first
ST-LINK with ID=0 will be selected
Selection of ST-LINK by ID or SN should be used with:
* V1J13Sx or greater ST-LINK firmware version
* V2J20Sx or greater ST-LINK/V2 firmware version
* V2J20Mx or greater ST-LINK/V2-1 firmware version
[UR] available only with ST-LINK/V2 and in SWD mode
For JTAG mode, connect under reset is available since
ST-LINK/V2 firmware Version V2J15Sx
The RESET pin of the JTAG connector(pin 15) should be connected
to the device reset pin
[HOTPLUG] available in SWD mode
For JTAG mode, HotPlug Connect is available since
ST-LINK/V2 firmware Version V2J15Sx
[SWCLK=<f>] available only with ST-LINK/V2 and in SWD mode
-List List the corresponding firmware version and the unique Serial Number
of every ST-LINK probe connected to the computer
Note: To have a correct SN the ST-LINK firmware version should be:
* V1J13Sx or greater for ST-LINK
* V2J20Sx or greater for ST-LINK/V2
* V2J20Mx or greater for ST-LINK/V2-1
-r8 Read memory. Syntax: -r8 <Address> <NumBytes>
-r16 Read memory. Syntax: -r16 <Address> <NumHalfWords>
-r32 Read memory. Syntax: -r32 <Address> <NumWords>
-w8 Write 8-bit data. Syntax: -w8 <Address> <data>
-w32 Write 32-bit data. Syntax: -w32 <Address> <data>
-w64 Write 64-bit data. Syntax: -w64 <Address> <data>
- Core commands --------------------------------------------------------
-Rst System reset
-HardRst Hardware reset
Syntax: -HardRst [<LOW/HIGH>]
[LOW] : Held reset pin low
[HIGH] : Held reset pin high
[PULSE=delay]: Pulse reset pin with a delay (in ms)
-Run Run application. Syntax: -Run [<Address>]
-Halt Halt core
-Step Step core
-SetBP Set breakpoint. Syntax: -SetBP <Address>
-ClrBP Clear all hardware breakpoints
-CoreReg Read Core registers
-SCore Get Core status
- Flash commands -------
Next point your Led blink test code uses HAL_Delay or no interrupt completely? When no IRQ then testing blink not check boot system.