Reputation: 21
I'm working on a project on a cortex-m3 CPU with bare-metal environment. Due to software upgrade needs the executable image on the CPU can be in one of two addresses in the flash memory which presents a problem. The start address of the image is known only at load time and not during static-linkage. I'm not too sure but I think this doesn't really qualify as dynamic loading but I could really be mistaken here as I'm no expert on this. Is there a way to compile and link the image in a way it's base address can be given only at load time given there is no OS and no dynamic loader?
Upvotes: 2
Views: 1115
Reputation: 340208
You need some way for the device to determine when it is reset which of two possible locations it should start executing from. But generally a bare-metal device has only a single starting location it runs from when it's reset (some controllers can select from two or maybe more entry points based on the logic level of some pins on the device).
We had a similar requirement, and worked out the following scheme:
The bootloader examines the fixed, well-known locations to checksum the two possible images.
The key to this is that the bootloader must be simple and stupid. It's not easily upgradeable, so you want it to be stupid enough that it can't have bugs.
Now the device can be upgraded while it's running by flashing the image to the non-running location (the Cortex-M3 device we have allows this - if the LPC1758 doesn't allow this, then you have to have something that runs from RAM perform the flash update). Reset, and the bootloader picks up the newly flashed image.
The system requires a little up-front work to get the bootloader running and rock-solid, but once it's working updates are 100% reliable (if the new flash doesn't complete, the old image is the only one that checksums, so it'll run at next reset - no bricks). The main disadvantage - and it's a big one - is that you essentially lose half your flash address space for the main program since the flash has to be able to hold two compete images.
Upvotes: 0
Reputation: 10393
For bare-metal embedded systems like yours, this is accomplished by compiling/linking your code as relocatable code, also known as Position Independent Code.
How this is accomplished is influenced by the processor, and the actual approach is implemented by your development toolset, so you'll want to consult with the documentation for your cross-development tools. It is usually a set of compiler & linker options (incl. your linker command script, if you have one) that determine how things are laid out & what registers are used to access them.
Things become a little easier when you're working with a platform (processor & OS) that supports an MMU (not on the CM3, sorry) - then the code can be located anywhere in physical memory, but via the MMU, its logical address space can be different. Thus, at link time, addresses for code & data can be fixed, and then at load time, the logical address space is set up via the MMU, and the program is none the wiser.
You might find this other SO question ("Trying to load position independent code on cortex-m3") helpful as well.
Upvotes: 2