Working environment: Windows 11, uVision v5.39.0.0 Community Edition, NUCLEO-F429ZI evaluation board, STM32CubeIDE 1.14.0.
I need to have two programs in STM32 board flash memory. The first one (loader) starts from default flash address 0x8000000. The second program (application) is downloaded to another flash memory address 0x8060000 (sector 7), and can start from this place, when properly activated.
This functionality is already implemented using STM32CubeIDE. I have app_stm prototype, built with STM32CubeIDE, which just makes a LED animation, nothing else. By changing some code:
FLASH (rx) : ORIGIN = 0x8060000, LENGTH = 2048K ... SCB->VTOR = 0x08060000 | VECT_TAB_OFFSET;
I can build app_stm.bin file. Using CubeMXProgrammer, I can download this file to the board address 0x8060000. Another STM32CubeIDE program, loader_stm, runs from default address. Immediately upon start, it executes this function:
#define FLASH_APPLICATION_ADDRESS 0x08060000 static void ActivateApplication() { typedef void (*pFunction)(void); pFunction JumpToApplication; uint32_t JumpAddress; SysTick->CTRL = 0x0; // Disables SysTick timer and its related interrupt HAL_DeInit(); JumpAddress = *(__IO uint32_t*) (FLASH_APPLICATION_ADDRESS + 4); JumpToApplication = (pFunction) JumpAddress; __set_MSP(*(__IO uint32_t*) FLASH_APPLICATION_ADDRESS); JumpToApplication(); }
ActivateApplication function is successful, app_stm program starts.
Now I need to implement loader functionality using Keil MDK. So, I make loader_keil application, which executes the same ActivateApplication function (app_stm program is still waiting for activation at 0x8060000). The result is: program stops, app_stm is not activated.
Debugging loader_keil, I see that after JumpToApplication() call it goes to HardFault_Handler.
So, the question is: how to activate another application from Keil MDK program, as it can be done from the program, built in STM32CubeIDE?
0x08060BE5, which looks a bit strange.
Actually, in CubeIDE it has the same value.
Then HardFault actually happens when your application starts executing.
Is the content of the SCB->VTOR same in both cases?
In CubeIDE SCB->VTOR is 0 before JumpToApplication call, and remains 0 after this call. But looking at the board, I see that app_stm is already running, so debugger is actually not connected.
In MDK it shows "cannot evaluate" in the Watch window. I need to investigate this: what is SCB and how can I see it in MDK debugger.
I need to write app_keil program and download it to 0x8060000. But for now I don't know, how to produce executable, that can start from non-default address, using Keil MDK. Currently, Keil loader tries to wake up STMCubeIDE program. Can this be a reason?
You can take a look at .map file and see where your program expects to run.
You definitely have to understand how to position the code correctly.
In MDK it is done with linker script, you can look for file which has .sct extension and inspect the file.
You always need valid code at the default start address of the CPU. I would call such code a bootloader. This bootloader can then start an application at a specific address. This knowledgebase article explains what you need to consider when jumping from the bootloader to the application:
https://developer.arm.com/documentation/ka002218/latest/
The SCB is the System Control Block which is a standard part of a Cortex-M core. In the µVision debugger, you can see the SCB under the 'Peripheral' menu.
@Milorad Cvjetkovic:Thanks. I didn't find .sct script in the project, but linker R/O base parameter in the Target options solved the problem.
@Hans Schneebauer: Thanks. The code from ARM: How to Write a Bootloader is working.