Open matthiasbock opened 6 years ago
So this is also something that we wanted to do at CVRA. What we planned to do was to write a bootloader update application that contains the new bootloader code. You would flash it through the existing bootloader, then jump to it. It will then write the new binary to the bootloader section, then erase itself to invalidate the application CRC.
The major downside of this solution is of course that you do not have a redundancy: if the update progress gets aborted you end up with a botched bootloader.
Yes, it would indeed be a nice to have feature! We have already encountered situations, in which we could have saved ourselves a lot of hassle if we could have updated (patched) an existing bootloader inside an enclosed device ;-)
To prevent a device brick, one could do the following:
What do you think?
Hmm, what do you mean by startup script? Not the crt0 of the device, yes? Because I think the STM32 can only boot from a fixed address.
By startup script I mean the reset handler, i.e. the first code to be executed at power-up. In case of your bootloader that would be the tiny assembler script in boot.s, which evaluates the first bytes in the RAM and accordingly facilitates an execution jump to bootloader, ST bootloader or app.
It could be modified to evaluate a "Whatever happens, start from app section!" switch not only in RAM but also in a dedicated page of flash memory. The switch should be in flash, in order to be retained, if the app-section bootloader writing to the bootloader-section procedure is interrupted by a power-loss, because in that case the app-section bootloader should start over in it's attempt to copy itself to the bootloader-section.
Hmm so you would never update the startup script, correct? Because otherwise that leaves a window open for catastrophic failure if the script is already erased but not reprogrammed yet.
It wouldn't be necessary to update the startup script itself during the procedure, yes. It just needs to be adjusted once, so it won't attempt to jump to the bootloader-section after an interrupted and therefore incomplete flash copy procedure.
This, however, still leaves one critical moment: the vector table update. New bootloader usually means new interrupt vectors. In order to rewrite them, they must be erased first. If the system is interrupted inbetween vector table erasure and re-write, it won't be able to start up again afterwards. I'm not sure how to tackle this, maybe the vectors could be kept constant across bootloader firmware versions using the linker script or a separate startup bootloader could be implemented, doing nothing more than selecting the section to jump to and relocating the vector table accordingly. Do you have any good ideas about this?
I think the easiest way would be to have the startup script detect which version it should boot and change the Vector Offset Table Register accordingly. Therefore the bootloader could bundle its interrupt vector table.
Are all microcontrollers, you are using, capable of vector table relocation?
Yes, our RTOS requires VTOR to operate properly with the bootloader. I think it is quite common in ARM parts, perhaps even mandatory:
Many, but not all ARM cores, I think. The Cortex M0 doesn't seem to have a VTOR register. So Cortex M0-based devices wouldn't be able to update the bootloader via CAN (but could theoretically still use it).
If we start working on this, it would probably be good, if we did so on the same or similar code base, also when it comes to testing. This brings me back to the tons of unmerged changes I have made in my fork...
Well if M0 cannot use VTOR, then they cannot also use interrupts when running with bootloader enabled, so I don't think we should expect much use from M0s.
This brings me back to the tons of unmerged changes I have made in my fork
True there is also that :grinning: Don't feel too pressured to do it though, the bootloader is "finished" for us, it has all features we need.
The bootloader can currently only update the firmware in the corresponding "app" section of the internal flash memory and forbids writing to the section, in which the bootloader itself is installed. For good reason: The bootloader runs from flash - attempting to erase and rewrite flash blocks while executing code from them is doomed to fail and brick or even damage the device.
However, the bootloader could be enhanced or a flash helper could be added, running from RAM. Those, in combination with more mechanisms preventing non-functional bootloader flash content, could enable updating the bootloader via CAN.