This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Getting started on a Secondary Bootloader, Cortex / STM32

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.

Parents
  • 1 Ok

    2 Just sign the image with a CRC (16/32 bit) and stick that at the end when you package the new image. If the entire image was written successfully, then the sum will be correct, so you don't need any list. You could use a simple sum, or a complicated hash, whatever floats your boat.

    3 I'd avoid creating interdepencies, I've done this with mask-roms for complex floating point libraries, but then there's zero chance of you screwing with the boot loader once you've signed it off. If you're just doing tight code with the standard libraries you're not going to win much. If you've got something more complex like an X-Modem protocol built in, or a common encryption block, perhaps the app can use that too, add a vector table entry that points to it rather than having it call some random address inside the loader. Look at the .MAP file and consider what's common, and what's large enough to care about.

    4 Do it as two project, change the IROM scope to match the basis/size of the region in question, create a scatter file if you want to get clever. You could perhaps do it as a multi-project, consider if you, or people coming after you will want to deal with that, or split it later if the app forks into dozens of custom builds.

    5 Check the box to generate .HEX files, if you mean binaries you'll probably want to use fromelf or build a custom packaging/signing tool that's run as a user app post link.

    6 The STM32 can run and flash memory at the same time, it stalls the processor with wait states, but works in a pinch. Yes, don't erase code you're running. Yes, you can copy code to RAM and run it.

    7 The processor doesn't clear RAM, some of Keil's start up can, put magic numbers in areas of SRAM or Backup RAM, check them in the Reset Handler. You can have the app write magic numbers and reset the chip.

Reply
  • 1 Ok

    2 Just sign the image with a CRC (16/32 bit) and stick that at the end when you package the new image. If the entire image was written successfully, then the sum will be correct, so you don't need any list. You could use a simple sum, or a complicated hash, whatever floats your boat.

    3 I'd avoid creating interdepencies, I've done this with mask-roms for complex floating point libraries, but then there's zero chance of you screwing with the boot loader once you've signed it off. If you're just doing tight code with the standard libraries you're not going to win much. If you've got something more complex like an X-Modem protocol built in, or a common encryption block, perhaps the app can use that too, add a vector table entry that points to it rather than having it call some random address inside the loader. Look at the .MAP file and consider what's common, and what's large enough to care about.

    4 Do it as two project, change the IROM scope to match the basis/size of the region in question, create a scatter file if you want to get clever. You could perhaps do it as a multi-project, consider if you, or people coming after you will want to deal with that, or split it later if the app forks into dozens of custom builds.

    5 Check the box to generate .HEX files, if you mean binaries you'll probably want to use fromelf or build a custom packaging/signing tool that's run as a user app post link.

    6 The STM32 can run and flash memory at the same time, it stalls the processor with wait states, but works in a pinch. Yes, don't erase code you're running. Yes, you can copy code to RAM and run it.

    7 The processor doesn't clear RAM, some of Keil's start up can, put magic numbers in areas of SRAM or Backup RAM, check them in the Reset Handler. You can have the app write magic numbers and reset the chip.

Children