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 tutorial

    HTTP fw update page

    You 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.

    MQTT fw update page

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 firmware
  • ota.commit - commit current firmware
  • ota.rollback - rollback to a previous firmware
  • device.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.c
  • MG_OTA_FLASH - OTA via an internal flash, requires the flash api described in src/device.h; see below
  • MG_OTA_CUSTOM - Custom implementation, roll your own set of mg_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:

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.c
  • MG_DEVICE_STM32H5 - Support for STM32H5 devices
  • MG_DEVICE_STM32H7 - Support for STM32H7 devices
  • MG_DEVICE_CUSTOM - Custom implementation, roll your own set of mg_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