Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement firmware update over LPUART1 #71

Open
janakj opened this issue Jun 5, 2022 · 6 comments
Open

Implement firmware update over LPUART1 #71

janakj opened this issue Jun 5, 2022 · 6 comments
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@janakj
Copy link
Collaborator

janakj commented Jun 5, 2022

Add a small separate bootloader to the firmware with support for firmware update over the ATCI (LPUART1). There are a number of existing bootloaders for STM32 platforms on Github, so perhaps one of those could be simply integrated. When activated, the bootloader would provide a small set of AT commands that could be used to replace the contents of flash to update the firmware.

This would make it possible to update the LoRa modem firmware in a Tower device using existing tools such as bcf without the need to take the LoRa modem out in order to connect it to a USB-UART converter.

@janakj janakj added the enhancement New feature or request label Jun 5, 2022
@janakj janakj added this to the Release 1.5.0 milestone Jun 5, 2022
@janakj janakj self-assigned this Jun 5, 2022
@hubmartin
Copy link
Member

I wrote few a bootloaders years ago, but today there is really a lot of good ones.
I did not tested any of them but from projects I use or follow the MCUBoot is used quite a lot.
https://github.com/mcu-tools/mcuboot
It is used in CHESTER/ZephyrOS and InfiniTime (in PineTime OSS smart watches I use).
From what I learned is that this bootloader depends on application which handles the new firmware upload and CRC to some memory, second half of flash. Then application flips some bit in MCUBoot config section, does reboot and bootloader checks CRC and does the rewrite/swap of the old/new firmware. IIRC it also has fallback functionality in case the new firmware does not start properly and did not call function that confirms in MCUBoot config section that the new FW is healthly.
I just wanted to give my 5 cents. Choose whatever bootloader you find the best.

@janakj
Copy link
Collaborator Author

janakj commented Jun 8, 2022

I am not familiar with MCU bootloaders at all and I am happy to take recommendations!

My main motivation is to enable LoRa firmware upgrade in deployed devices over the main USB port on the Core module, even if the process is slow. I am looking for a bootloader that:

  1. Is fairly minimal and simple to integrate;
  2. Can be extended with a custom AT command interface;
  3. Does not require a spare flash memory section.

There is plenty of flash memory left so far, but not enough to store both the old and new firmware versions at the same time. Thus, we will need to overwrite the running application. But I think that's okay. If the upgrade fails, one can always fall back to the built-in STM bootloader.

@hubpav
Copy link

hubpav commented Jun 8, 2022

@janakj I would not bother with overwriting the FLASH area from a function running in RAM. It is technically possible, but implementing such a thing is too much of an effort (and debugging nightmare :)) Probably you think the same, but since you said overwrite the running application, I would better clarify it :)

Ideally, it will be a simple bootloader that will do the integrity check of the application in the beginning. If it fails, it just waits in the bootloader mode for the new firmware. If it does not, it will boot it. I would not mind marking the application area flag that the update is enforced. So this solves the problem that the bootloader does not have to time out. Once the update request is sent, the bootloader will not continue unless it receives a new image. No matter what.

As @hubmartin said, pick whichever strategy you like the best, we will be grateful for anything and even more, if it is simple :)

@hubmartin
Copy link
Member

If the flash cannot be split in half because of the size of the app, then simplier bootloaders could be used.
The MCUboot has also some serial recovery mode if neither of two slots contains valid app. Needs to be investigated if this could be the way.
https://devzone.nordicsemi.com/f/nordic-q-a/83055/mcuboot-serial-recovery-mode-with-mcumgr
https://review.trustedfirmware.org/plugins/gitiles/mirror/mcuboot/+/HEAD/boot/zephyr/Kconfig#464
Maybe the MCUBoot might be an overkill with all the keys and security. Not sure if it is possible to disable that.

I tried to search for serial bootloaders on github (STM32 bootloader). This uses XMODEM protocol. The Core Module then could use the passthrough firmware or later there could be specific AT command to switch to passthrough mode directly in firmware?
https://github.com/ferenc-nemeth/stm32-bootloader

Some reading:
Here is a curated list of bootloader articles
https://github.com/nhivp/Awesome-Embedded#bootloader
Also Memfault has article on some overview how bootloaders work to get the basic concepts.
https://interrupt.memfault.com/blog/how-to-write-a-bootloader-from-scratch

@janakj
Copy link
Collaborator Author

janakj commented Jun 9, 2022

@janakj I would not bother with overwriting the FLASH area from a function running in RAM. It is technically possible, but implementing such a thing is too much of an effort (and debugging nightmare :)) Probably you think the same, but since you said overwrite the running application, I would better clarify it :)

My bad! I wasn't suggesting to run the boot loader from RAM. Just that it overwrites the original application in flash since there isn't enough space left for two copies of the same application.

Ideally, it will be a simple bootloader that will do the integrity check of the application in the beginning. If it fails, it just waits in the bootloader mode for the new firmware. If it does not, it will boot it. I would not mind marking the application area flag that the update is enforced. So this solves the problem that the bootloader does not have to time out. Once the update request is sent, the bootloader will not continue unless it receives a new image. No matter what.

Yep, that sounds like a good approach to me, thanks for the suggestion.

As @hubmartin said, pick whichever strategy you like the best, we will be grateful for anything and even more, if it is simple :)

I will look for something minimalistic based on Martin's suggestions. I don't wish to spend more time than what's necessary on this.

@janakj
Copy link
Collaborator Author

janakj commented Jun 12, 2022

It also appears that the pin PA0/WKUP1 is dedicated to activating the boot loader embedded in the application (as opposed to the boot loader in the system memory). When pulled down during power on, the application boot loader will be activated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants