Dear MPC Users,
I'd like to share a snippet from my linker script with you - a snippet which I really love. Using the proposed construct, you can decide on-the-fly under control of your Makefile or S32 Design Studio Build Configuration, whether to flash the compiled SW or to load, run and debug it from RAM. Most likely, nothing needs to be modified in the built SW, i.e. in source or library file. (We use the MPU and require a preprocessor #if/#else in its configuration; similarly, there's a switch in the MMU configuration of the MPC5775.)
Meanwhile, flashing SW under development became really rare. Most of the time, I build it for RAM and run it via the Eclipse launch button to inspect and debug it. That's significantly faster than flashing the SW and it safes erase-and-flash cycles for the MCU.
The linker script code has been made for the MPC5748G and is modifiable for many or most other MPCs. The only relevant limitation is that it will simply not pay off for those derivatives, which have only little RAM. Moreover, since code and data need to fit into RAM, even the biggest MPCs won't probably be capable to run your complete, elaborated SW this way, but think about development and testing of units/subcomponents of it.
Here's the snippet. The only trick is to set the memory segments not according to the physical memories, but all of them to portions of the RAM:
/* We use the simple conditional operator the linker script syntax
offers for switching from normal build of a flashable binary to an
equivalent binary that can be loaded into RAM by the debugger.
Using RAM can have these advantages:
- We save flash ROM programming cycles, which are limited
- It reduces the turnaround time between code changes. Loading RAM
is faster than erasing and re-flashing
- The risk of bricking the CPU is lower if we work on code, which
is critical in this respect; e.g. self-tests, security, reset
logic, reset escalation
The major drawback is the software size; code and data need to fit
into RAM. We use a hard-coded distribution of both, 67% for code,
33% for data.
Note, the switch ld_linkInRAM is set by the makefile using the
linker command line option --defsym. */
ld_textSegStartAddr = ld_linkInRAM==1? 0x40000000 : 0x00f90000;
ld_textSegSize = ld_linkInRAM==1? 2*256k : 0x01580000 - 0x00f90000;
ld_dataSegStartAddr = ld_linkInRAM==1? ld_textSegStartAddr + ld_textSegSize : 0x40000000;
ld_dataSegSize = ld_linkInRAM==1? 3*256k - ld_textSegSize : 3*256k ;
/* Definition of memory regions using absolute addresses of physical
memories. */
MEMORY
{
/* RM, sec. 3.2: f8c000 is the first inspected boot sector.
However, this area is marked "Small HSM Code Block". According
to RM, 3.3, table 3-2, f90000 is the beginning of the generally
usable flash ROM and it's at the same time the second boot
sector. */
memBoot(rx): org = ld_textSegStartAddr, len = 0x18
memFlash(rx): org = ld_textSegStartAddr + LENGTH(memBoot),
len = ld_textSegSize - LENGTH(memBoot)
memData(rwx): org = ld_dataSegStartAddr, len = ld_dataSegSize
}
You will easily find the block
MEMORY
{
...
}
in your linker script and it'll be structural same. The details will differ a bit. You will see the similarities and understand, how to adapt the code snippet to meet the details of your particular linker script.
After modifying the linker script, you need to do two more things:
At first, copy an existing Build Configuration in Eclipse and modify it in a way that makes the modifications take effect. Several possible ways exist: Using the command line or setting an environment variable for an External Builder, using the linker settings for the Internal Builder, making a copy of the linker script and use original and modified either/or ... In the sketch, a linker symbol is set from outside using the linker command line switch "--defsym ld_linkInRAM".
At the same time, the copied build configuration should be configured to produce the loadable binaries either in another folder or with another name.
Secondary, the Launch Configuration is copied, too. Change the path/filename of the *.elf file to use. The check-box "Load executable" on tab "Startup" needs to be checked. ("Load symbols" anyway.) This makes the debugger put your compiled code and data into RAM so that it can be run there, regardless of what's currently flashed. All other settings stay as usual. Start the SW in RAM by launching the altered configuration.
If built for RAM, the SW can be started only in and with help of the debugger. Once started, you can disconnect the debugger and it'll continue running. Hence, long-running tests are possible this way, too.
After next reset, your board will start up again with the currently flashed SW.