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.
Most everything makes sense. I'm not entirely clear on the IROM1/2 and etc. How to set the Jlink up to program the secific sectors while also using code NoRead protection eventually. Or what happens when I switch context. Nor specifically how I'll make sure this is "safe" for the field (I'll be panicking if I ever push out a bootloader update! I'll have to look at the rom and see if I can have a backup-bootloader just in case)
I see on the separate projects. I'm not sure which code I'll re-use and which I won't.
Not being able to debug both in context is going to make designing the bootloader slightly difficult :\ Like I'm really not thrilled about that. There is no way to import all of the symbols to have out-of-project contextual debugging? Seems very limiting.
Thanks again!