I've never programmed a bootloader before, but need have one that does firmware reflashing over UART. Shouldn't be that bad, but I do need some pointers...
There are 7 questions below, but they all should be very easy...
1. I want to start the code at 0, have a 4k bootloader and the real code past that. This is about all I know for sure. I do not PLAN on using interrupts in my bootloader and instead will make a simple polling machine for what it's going to do.
2. - The bootloader should check the a hash of userflash, if something is wrong with a previous update, I want to stay in the bootloader and wait for another firmware update over UART. This means I need a table somewhere with the correct hash of the user flash, the bootloader hash, and maybe some settings hash to make sure nothing was altered somehow. Is there a common way to lay this out? My plan was to just make the bootloader a hundred bytes short of 4k in size, then use that remaining size to store the hashes as a fixed location and format. Will be a pain for debugging I'm sure!!! But it's something I think I want to see for production. Issues with this?
3. I'm using UART for the physical connection. But since I won't be running RTX during the bootloader, I'll need a separate library for this low level communication and not the RTX UART code. I'll also need anything else the bootloader will use - BUT - Can I reuse these functions and libs in my user code? I saw an NXP AppNote that said you want to keep anything your user code needs outside of the bootloader because it'll span sectors otherwise, not sure if this is really an issue - or why they said that.
4. How do I lay this out in Keil!?! My thought was to do a multi-project one called Bootloader and another call Application, but I'm not sure how to get my Segger unit to flash the bootloader to 0x00 everytime and the flash project to 0x4000 or wherever. Is there a way I can have both open, flash both at the same time? Because...
5. I want to distribute the bootloader and userflash and maybe another package separately. I want the application to be able to update any of these separately. So I THINK I want the raw hex to be generated separately. Not sure how to do this in Keil.
6. On that note... It's obviously risky to update the bootloader. And I clearly don't want to run code while I'm also overwriting it. So... Is there a method where I'd take my WriteNewBootloader() and move it in to ram and execute there? Is it popular to have a bootloader backup in place that never gets overwritten, that way I know if bootloader hash fails I have a fully functioning backup in place I can switch over to?
7. On the ARM parts, Can I set my own Reset Reason/Code? My reasoning is that I see no reason to put an UpdateFlash() in the bootloader and again in the user flash while it's running normally. Instead, my idea was to reboot back to the bootloader - but I need some way of knowing the context. So that I know I just rebooted from normal mode back into bootloader to do a reflash - verus - this is a new boot or power cut out or whatever other reason I had to do a reset.
When debugging the application, a debugger script can perform the same "hand-over" as the boot loader would do. This works well as long as the boot loader doesn't have errors where it leaves interrupts etc still active after the handover. In that case, the processor can jump to a random address after the boot loader or application switches interrupt vector table.
Any comments about how this looks in Keil? How to set this up?
Have a look at the commands supported by the debugger.
You can write own ini files to run when you start the debugging. These allows you to read/write memory addresses or to set register content.
This is a bit similar to how some sample projects has a RAM target, where the application isn't stored in flash but is instead stored in RAM - the processor itself doesn't know how to start a program in RAM.