Firmware Update
Overview
This tutorial shows how to use Mongoose firmware update support functions in the context of a device dashboard. The UI runs on a web browser and interacts with the device via a RESTful API.
The device dashboard UI, including user authentication, is explained in its own tutorial. To build and try the example, please follow it. Selecting
Firmware Update
in the menu on the left, you'll access the corresponding screen for this tutorialYou basically upload a firmware file, reset the device to boot from it, and commit it or rollback to the previous image.
The MQTT dashboard UI is explained in its own tutorial. To build and try the example, please follow it. It works in a pretty similar way to what we previously described.
API
bool mg_ota_begin(size_t new_firmware_size); // Start writing
bool mg_ota_write(const void *buf, size_t len); // Write chunk, aligned to 1k
bool mg_ota_end(void); // Stop writing
bool mg_ota_commit(void); // Commit current firmware
bool mg_ota_rollback(void); // Rollback to the previous firmware
void mg_ota_boot(void); // Bootloader function, must be called at start time
int mg_ota_status(int firmware); // Return firmware status
uint32_t mg_ota_crc32(int firmware); // Return firmware checksum
uint32_t mg_ota_timestamp(int firmware); // Firmware timestamp, UNIX UTC epoch
size_t mg_ota_size(int firmware); // Firmware size
Example RESTful API
For this application, the RESTful server API in the Device Dashboard tutorial provides the following authenticated endpoints:
/api/firmware/upload
- handles the process of uploading a file to the device and saving it as binary data/api/firmware/commit
- marks the current firmware as stable/api/firmware/rollback
- rolls back the a previous firmware version available/api/firmware/status
- returns useful data on the status of the firmware images/api/device/reset
- resets the device/api/device/eraselast
- erases the last sector in order to hold data records
Each endpoint basically calls its respective backend API function for the OTA process. The update process itself requires three function calls: ota_begin()
, ota_write()
for each data chunk received, and ota_end()
to finish the transaction.
Example RPC API
For this application, the RPC API in the MQTT Dashboard tutorial provides the following methods:
ota.upload
- instructs the device to get and save new firmwareota.commit
- commit current firmwareota.rollback
- rollback to a previous firmwaredevice.reset
- restart the device
In this example, devices will publish their status, which includes firmware status
Compile options
The implementation is driven by the build option MG_OTA
:
MG_OTA_NONE
- No OTA support, uses a stub implementation that does nothing: src/ota_dummy.cMG_OTA_FLASH
- OTA via an internal flash, requires the flash api described in src/device.h; see belowMG_OTA_CUSTOM
- Custom implementation, roll your own set ofmg_ota_*
functions.
Basic usage
The device will call mg_ota_boot()
at startup in order to check a recently loaded image.
The other functions are usually called from:
a RESTful API, as used in the Device Dashboard tutorial:
an RPC API, as used in the MQTT Dashboard tutorial:
Flash API
// Flash information
void *mg_flash_start(void); // Return flash start address
size_t mg_flash_size(void); // Return flash size
size_t mg_flash_sector_size(void); // Return flash sector size
size_t mg_flash_write_align(void); // Return flash write align, minimum 4
int mg_flash_bank(void); // 0: not dual bank, 1: bank1, 2: bank2
// Write, erase, swap bank
bool mg_flash_write(void *addr, const void *buf, size_t len);
bool mg_flash_erase(void *sector);
bool mg_flash_swap_bank(void);
// Convenience functions to store data on a flash sector with wear levelling
// If `sector` is NULL, then the last sector of flash is used
bool mg_flash_load(void *sector, uint32_t key, void *buf, size_t len);
bool mg_flash_save(void *sector, uint32_t key, const void *buf, size_t len);
void mg_device_reset(void); // Reboot device immediately
Compile options
The implementation is driven by the build option MG_DEVICE
:
MG_DEVICE_NONE
- No device support, uses a stub implementation that does nothing: src/device_dummy.cMG_DEVICE_STM32H5
- Support for STM32H5 devicesMG_DEVICE_STM32H7
- Support for STM32H7 devicesMG_DEVICE_CUSTOM
- Custom implementation, roll your own set ofmg_flash_*
functions.
Basic usage
The device may call mg_flash_load()
and mg_flash_save()
to get and set persistent data
The other functions are usually called from the OTA API
Supported microcontrollers
This is a list of microcontroller families for which OTA is supported; check the corresponding tutorial for your family for specific configuration options and example code.
Device Family | Tutorial |
---|---|
STM32H | baremetal |