I am using an STM32F439VGTx, which hasflash starting at 0x08000000, length 0x00100000and CCM RAM starting at 0x10000000, length 0x00010000and normal RAM starting at 0x20000000, length 0x00030000I want some of my code and constant data to be in flash,and some code to be executed out of RAM. How can Itell the compiler to compile some functions or modulesto execute in RAM, but place the compiled code in flashso I can copy it to RAM for execution? For example,I might have a function called RamFunc(), which I would likeplaced in RAM at some address, (say 0x20000800 or maybe 0x100000800),but I need the image of it in flash at a known address, say 0x08001000,and a known length so I can copy it to RAM for execution.I have tried many variations of settings in a .sct file, and also triedvarious versions using a Debug_RAM.ini file, as in the CMSIS-RTOS Blinky (MCBSTM32E)example. Nothing has worked for me.Any help would be greatly appreciated.
I suspect you're trying too hard.I'm pretty sure you don't have to do the copying from flash to RAM yourself. The linker and startup code should be quite capable of doing that for you, once you've set up the specific code section and linker script correctly. As a benefit of that, you also won't have to insist on fixed addresses, either, because the start-up machinery gets all the information it needs for that job from the linker, already. All you have to do is let the tools do their job.
I have not found any way to do it, either with the startup code automatically copying it or manually. I'm happy to let the tools do the job, but I don't know how. I am hoping someone here does. Also, my main goal to to understand clearly how to use the tools to do what I want to facilitate a custom boot loader.
This is the functionality that Scatterloading provides.
In your example, the Flash would be the load address, and RAM the execution address.
Do you need the Flash address to be a specific address, or are you happy to let the tools decide that?
Something similar to the following should work:
FLASH 0x08000000 0x00100000 { FLASH_EXEC 0x08000000 0x00010000 { Vectors.o (+RO +FIRST) * (+RO) } ARM_LIB_STACKHEAP 0x10000000 EMPTY 0x00010000 { } NORMAL_RAM 0x20000000 0x00030000 { ramcode.o (+RO) * (+RW +ZI) } }
This stores everything in the Flash at 0x08000000.
Most of the code executes from Flash, but it relocates ramcode.o code (+RO) into NORMAL_RAM.
Stack and heap reside in CCM RAM (using the special region name ARM_LIB_STACKHEAP).
Other data (+RW +ZI) is also located in NORMAL_RAM.
For more information, see:
https://developer.arm.com/documentation/101754/0622/armlink-Reference/Scatter-loading-Features/The-scatter-loading-mechanism
https://developer.arm.com/documentation/101754/0622/armlink-Reference/Scatter-loading-Features/The-scatter-loading-mechanism/Placing-the-stack-and-heap-with-a-scatter-file
There are also many examples available to compare against.
You don't need to execute out of SRAM to burn flash, you just need to execute from a different block. That's my (limited) understanding anyway.
You can locate memory in Flash if you still want to. For instance:
const APPINFOBLK_T AppInfoBlock __attribute__ ((at(FLASH_AIB))) = // Compiler v5
:
Thank you for this reply. I tried many different variations of the .sct file, and looked at the .mp file generated. Some attempts did not compile because it appears that the order of the sections in the .sct file makes a difference. With the FLASH_EXEC section first, it works, but with it placed later in the file, I get these errors:
RxModule\RxModule.axf: Error: L6788E: Scatter-loading of execution region FLASH_EXEC to execution address [0x08000000,0x0805aac4) will cause the contents of execution region FLASH_EXEC at load-address [0x08001fdc,0x0805caa0) to be corrupted at run-time.RxModule\RxModule.axf: Error: L6202E: __main.o(!!!main) cannot be assigned to non-root region 'FLASH_EXEC'RxModule\RxModule.axf: Error: L6202E: __scatter.o(!!!scatter) cannot be assigned to non-root region 'FLASH_EXEC'RxModule\RxModule.axf: Error: L6202E: __scatter_copy.o(!!handler_copy) cannot be assigned to non-root region 'FLASH_EXEC'RxModule\RxModule.axf: Error: L6202E: __scatter_zi.o(!!handler_zi) cannot be assigned to non-root region 'FLASH_EXEC'RxModule\RxModule.axf: Error: L6202E: anon$$obj.o(Region$$Table) cannot be assigned to non-root region 'FLASH_EXEC'RxModule\RxModule.axf: Error: L6203E: Entry point (0x080001ad) lies within non-root region FLASH_EXEC.
This is the .sct file that worked for me:
FLASH 0x08000000 0x000C0000{ ;It appears this must be first to make it the root region FLASH_EXEC 0x08000000 0x000C0000 { *.o (RESET, +First) * (+RO) } ;This code will be loaded into RAM from flash by library c_w.l NORMAL_RAM 0x20000000 0x00030000 { main.o (+RO) Boot.o (+RO) Flash.o (+RO) AddPrintf.o (+RO) stm32f4xx_hal_msp.o (+RO) * (+RW +ZI) } ARM_LIB_STACKHEAP 0x10000000 EMPTY 0x00010000 { }}
Note that I am reserving flash after 0x000C0000 for other purposes.
I still have a few of questions:
1. In my .sct file, I have *.o and explicit lines line main.o. It looks like main.o will be assigned before *.o, but I am not sure. It would be a pain if I had to list every .o file explicitly. Is there a syntax for *.o except main.o, ... ?
2. If I include main.o, for example, in NORMAL_RAM and main calls printf, will the compiler include the C library code for printf in RAM as well?
3. When I added the linker switch "--datacompressor=off", the resulting flash size was slightly smaller. I would have expected it to be larger without compression. Any idea why?
4. It looks like all the work of moving code from flash to RAM, including decompression if needed, is performed by c_w.l. Is the source code for this library available anywhere? Or, is there documentation for this library indicating the format of the data in flash that it references, including the compression method?
My goal is a very detailed understanding of how the startup code works.
Thank you again to everyone who replied.
0) The errors make sense - the scatter loading code must itself execute from a non-moved address (known as a ROOT region). In the above, FLASH_EXEC is a ROOT region, as load address (from the outer braces FLASH) and execution address are the same.There are ordering rules within regions that go beyond the order listed in the scatter file, hence the +FIRST qualifier to force the vector table to be exactly the first thing in that region.
Also, regarding the size of FLASH_EXEC, don't forget that FLASH (load region) also needs space to store the code (and data) that will be relocated to NORMAL_RAM.
1) The * (+RO) will catch all code from objects that are not explicitly referenced elsewhere in the scatter file. You can also use .ANY if you wish to share them in multiple regions.
2) No. It will be amongst "* (+RO)" unless explicitly placed therein.
3) Compare code size - if no data compression, then no need for the code to decompress. I suspect you are referring to just a few bytes.
4) Source is not available. The init sequence is described here:
https://developer.arm.com/documentation/100748/0623/Embedded-Software-Development/Application-startup
Also, some docs on the compression below:
https://developer.arm.com/documentation/101754/0623/armlink-Reference/Linker-Optimization-Features/Optimization-with-RW-data-compression/How-compression-is-applied
Regards, Ronan