2020-12-15 08:32 AM
Hello everyone.
I am using ARM Compiler 6 (6.14) in the Keil uVision IDE.
Now I am developing a bootloader for STM32F0. There is little RAM.
The specificity of the bootloader is such that when working with Flash (erase/write operations take ~50ms) there should be no missing events. So I decided to put the bootloader code in RAM.
Since there is little RAM, I decided to execute some of the code from Flash (the initialization code of some peripherals), and some from RAM.
The plan is this:
1) The SysInit() function is called on the reset vector. This function initializes system timing (enables PLL), GPIO for hardware bootloader entry condition, and CRC calculation module. In this case, I need the CRC module to verify the application written in Flash before launching it.
2) I execute the logic of entering or traversing the bootloader: if one of a certain set of conditions is true, I execute __main() to initialize the runtime-library C. It will also copy the necessary functions from the Load Region (Flash) to the Execution Region (RAM).
That is, everything works schematically like this:
ResetHandler()
{
SysInit();
if(BootInReq())
__main();
else SysDestroy(),
GoToUsrApp();
}
As you can see, all functions will be executed from Flash (if asked by the linker through a script). If the condition for entering the bootloader is true, __main() will be executed and all RAM functions will be in their places in RAM. Great, but... In the bootloader code itself (which is already in RAM), I also need to use some of the functions that I used before calling __main(). One such function is the CRC calculation function to support the communication protocol.
It turns out that I need a copy of this function in RAM. But I linked it in Flash and it's there! You cannot call functions in Flash from RAM, as this can cause the processor to freeze (what if there is an erase operation there?).
I could link it to RAM, but it will only appear there after calling __main(), which is contrary to my algorithm (I need to use the CRC calculation before calling __main()).
Can a copy of the same function be placed in different regions of execution via a linker? Or maybe there is a way to call the function from the load region? I would hope that it is possible to place the functions I need in the load region so that they are not compressed and are a binary copy of their generation in RAM. It would be great if the code could specify from which section to execute the function: CalcCRC() is executed from RAM (since the program is linked to execute all functions from RAM that are not explicitly described in the linker script), CalcCRC() __attribute __ ("Flash , please!") :ok_hand: was called from the load region (that is, from Flash).
Or maybe the linker generates special different names for functions? For example, with some postscript to the name of the function a la "function from the load region".CalcCRC ;)? Indeed, in the map file I see the address at which the binary representation of the function is located in Flash, which in the future should be moved to RAM. I think if I transferred control to this address, everything would work correctly. Unless, of course, the function is somehow cleverly packaged there.
I would be glad to receive your comments!