2023-08-03 01:48 AM
Hello all,
this is my first post in this forum.
I am in the process of developing my own bootloader for a firmware upgrade via SD card with the Eval board STMH757I.
So far so good, with the help of the FirmwareUpgradeStandalone example, I was able to get the whole thing working so far that I can flash a bin file and also find it at the appropriate
place in the flash (0x08020000) checked with CubeProgrammer.
If I run through the whole process with the bin file from the supplied FirmwareUpgradeStandalone example, everything works perfectly.
It can be flashed with my bootloader and after flashing is done i perform a reset and the flashed application (firmware upgrade sample) runs as expected.
However, if I now write my own Application and build a bin-File, which does not do much more than make 3 LEDs flash one after the other, the procedure no longer works.
I create the bin file as post build output in CubdeIDE.
With my own bin-File i can see that the bin file has been installed in the memory via SD-Card. But when i press the Resetbutton after flashing is done, the flashed programme doesn't start.
But if I do a relaunch in debug mode, the Application runs as desired. When I press the reset button (while in debug mode), it also starts the application (3 LEDS blinky) again.
So I would say that jumping into the app and flashing it works in some way.
The whole thing is very confusing because the procedure works fine with the bin file from STM and not with my bin file. A main difference in the bin-Files is the value at the start
stm bin-File starts with 0x2000000
my bin-File starts with 0x24080000
for this reason i also had to adjust the if-query so that my bootloader jumps to the desired address at all.
if ((((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000) == 0x24080000) || ((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000) == 0x20000000)
I have set the vector table offset (0x20000) and the FLASH origin (0x08020000) in the linker file and in the system file. I tried to switch off the interrupts before the jump without success.
This is the jump code (taken form FirmwareUpgradeStandalone-Example)
if(HAL_GPIO_ReadPin(BUTTON_TAMPER_GPIO_Port, BUTTON_TAMPER_Pin) == GPIO_PIN_SET)
{
/* Check Vector Table: Test if user code is programmed starting from address
"APPLICATION_ADDRESS" */
if ((((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000) == 0x24080000) || ((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000) == 0x20000000)
{
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
// Tried to set Vecortable here, no effect
//SCB->VTOR = APPLICATION_ADDRESS;
Jump_To_Application();
}
}
My question is: what else can I do? What is the difference between a reset (RSTN button on the EVAL board) and a relaunch in debug mode?
What else do I have to consider in my application so that the programme runs after flashing? Do the problems occur because it is a dual-core? Do I have to change anything in the startup file?
I have spent 2 days trying to find a solution to this problem, unfortunately I have not found a similar problem in this forum or anywhere else.
Thanks a lot
2023-08-04 05:18 AM
if ((((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000) == 0x24080000) || ((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000) == 0x20000000)
For a start the mask value 0x2FFE0000 is a nonsense. The digit 2 looks 0b0010 in binary, which contains a zero to the right of 1. And why are upper two bits ignored? Why isn't it 0xFFFE0000 or similar? Also a volatile (__IO) is completely unnecessary there.
2023-08-07 12:38 AM
Hi Piranha,
thanks for your reply. This start mask is what I extracted from the example FWUpgrade_Standalone from the CubeMX Repositoty from STM.
Here is the original code:
/* Test if User button is pressed */
if (BSP_PB_GetState(BUTTON_TAMPER) == GPIO_PIN_SET)
{
/* Check Vector Table: Test if user code is programmed starting from address
"APPLICATION_ADDRESS" */
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000) == 0x20000000)
{
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
Jump_To_Application();
}
}
how can i do better? I mean the mask and code seems to work as it actually jumps into the application, at least when I use the supplied bin file from the repository.
But the solution for this problem is not quite clear to me, especially because the supplied file is only available as a bin file and I have no insight into the source code.
It would be nice if there were some hints I could read in order to better understand the problem of the different bin files.
2023-08-07
09:41 AM
- last edited on
2023-09-04
06:34 AM
by
Lina_DABASINSKA
the supplied file is only available as a bin file and I have no insight into the source code.
Why would you need it? For BIN file you only have to know the address, where it must be written.
And the forum and internet is full of discussions about this topic. But for a decent solution toss it out and implement a simpler design:
2023-08-07 12:15 PM - edited 2023-08-07 12:15 PM
Check what initial value for SP actually is.
Perhaps print to a serial terminal. Consider serial output on both sides for the loader / application transfer to understand what's actually happening.
You could change the test, or remove it. It was basically there to stop you jumping to an address in a blank FLASH memory, so could check if 0xFFFFFFFF pattern, or checksum / secure the application image so you're not calling jump.
I'd personally prefer for the startup.s code to explicitly set the SP to the desired address rather than trying to modify the stack pointer in the middle of a function with it's own stack context.
2023-08-08 06:55 AM
Hi Tesla DeLorean,
thank you for your answer. As it turned out, my main problem was that I generated the codes with CubeMX and it generates a query each time waiting for the CM4 core to wake up from stop mode. This query was in my bootloader as well as in my blinky-app which I wanted to flash as a bin-file.
I have now switched off the CM4 in CubeProgrammer my bootloader, commented out the code and, lo and behold, the flashed application starts up :)
Since my application should also use the CM4 later, I would start it explicitly in the flashed app (bin file). Is there anything wrong with this procedure?
I would start the CM4 with this:
RCC->GCR |= (1<<3);
My next problem is now how do I also flash the CM4 from my bootloader?
I'm new to this dual core thing and don't know how best to go about it. Thank you for your help
2023-08-08 02:56 PM
RCC->GCR |= (1<<3);
Why are you using the CMSIS definitions for the register, but not for bit fields? From where does this mass insanity comes? Even ST's broken bloatware uses normal bit field definitions!
2023-08-09 12:52 AM
Hi Piranha,
sorry mate, I'm fairly new to this STM32 area, I'm just trying to get things running, the deeper understanding of things below the surface I hope to acquire over the course of this project.
I found this way of starting the CM4 in my research, if I can do better or know how best to approach it then I'm happy. Thanks for your help.