0
votes

I am writing a bootloader for an ARM Cortex-M3 that utilizes a relatively complex communications interface; this is the same as the actual application uses. The application uses Keil's RTX as its kernel, and the communications stack relies on that. Using GCC, of course.

The bootloader does the following basic steps:

  1. On startup, checks for a valid app image; if none available, it enters upgrade mode;
  2. It checks for a button press as a request for enter upgrade mode; if it finds that, it enters upgrade mode.
  3. Having found a valid image and there is no request to upgrade, it "boots" the app.

This is rather simplified, but it describes the scenario adequately for our purposes.

The final problem that has surprisingly proved difficult is booting the app. The idea is to disable interrupts, set the vector table, stack pointer, and jump to the app's reset vector in the new vector table. All this works just peachy, except that shortly thereafter, I get a Hard Fault.

Through experiments, if I do this in a trivial bootloader (that does not use RTX or, of course, the comms stack), the boot to the app works fine. So it seems RTX is the problem.

The thing is, the real bootloader doesn't need RTX until it enters its Upgrade mode. So the obvious approach is to not start RTX until we have determined we need it; however, it seems it is hacked into the startup code, and so by the time I get into the bootloader code, it is too late; indeed, the bootloader main() function is a thread already!

The best approach seems to be not starting RTX (too bad I hadn't used FreeRTOS!) until I need it; however, that seems to require some hacking. An alternate approach would be to somehow disable all interrupts and exceptions, but for some reason, I haven't been successful there either. Does anyone have examples of either approach?

1
So both the bootloader and the application are RTX-based? If so, it strikes me that the best option might be a complete change of plan - link everything together into a single program, run the initial check as your startup task, then have that launch either the "upgrade" or "application" task as appropriate. That should also save you flash space by not duplicating the "relatively complex" communication code between separate "bootloader" and "application" images.Notlikethat
Seems that would require running from RAM or some such, and overwriting the bootloader (as it is part of the app that is being uploaded!); this would make the system much too brickable, I am afraid. But interesting idea. Clearly I misled you when I said "relatively complex"; while it is complex, it isn't terribly large - my bootloader is about 20 KB, my app is 80 KB, and the device has 1 MB!Bob

1 Answers

0
votes

In case someone comes across this situation, the solution is actually quite simple. I just customized the SystemInit() function in the system_efm32gg.c file! While the _efm32gg is vendor specific, it does seems the system_X.c is a widely used ARM construct - at least, I've seen it with ST, NXP, and EnergyMicro/SiliconLab - so this is a decent general approach.

I should have known better! sigh