OTA Upgrade module¶
|Since||Origin / Contributor||Maintainer||Source|
|2019-06-24||DiUS, Johny Mattsson||Johny Mattsson||otaupgrade.c|
The OTA Upgrade module provides access to the IDF Over-The-Air Upgrade support, enabling new application firmware to be applied and booted into.
This module is not concerned with where the new application comes from. The choice of download source and method (e.g. https, tftp) is left to the user, as is the trigger to start an upgrade. A common approach is to have the device periodically check in with a central server and compare a provided version number with the currently running version, and if necessary kick off an upgrade.
In order to use the
otaupgrade module, there must exist at least two
OTA partitions (type
ota_1), as well as the
"otadata" partition (type
ota). The IDF implements
the typical "flip-flop" approach to upgrades, in that one of the
partitions hosts the running application, and the upgrade is downloaded
into the inactive partition and only when fully downloaded and verified
is it marked as bootable. This makes the system resilient to incomplete
upgrades, be it due to power-loss, interrupted downloads, or other such
An example partition table for OTA might look like:
# Name, Type, SubType, Offset, Size nvs, data, nvs, 0x9000, 0x5000 otadata, data, ota, 0xe000, 0x2000 ota_0, app, ota_0, 0x10000,0x130000 ota_1, app, ota_1, 0x140000,0x130000
Depending on whether the installed boot loader has been built with or without rollback support, the upgrade process itself has four or three steps. Without rollback support, the steps are:
- feed the new application image into
otaupgrade.complete(1)to finalise and reboot into the new application
If the boot loader is built with rollback support, an extra step is needed after the new application has booted (and been tested to be "good", by whatever metric(s) the user chooses):
otaupgrade.accept()to mark this image as valid, and allow it to be booted into again.
If a new firmware is not
accept()ed before the device reboots, the
boot loader will switch back to the previous firmware version (provided
said boot loader is built with rollback support). A common test before
marking a new firmware as valid is to ensure the upgrade server can be
reached, on the basis that as long as the firmware can be remotely
upgraded, it's "good enough" to accept.
The boot info and application state and version info can be queried with this function. Typically it will be used to check the version of the running application, to compare against a "desired" version in order to decide whether an upgrade is required.
A list of three values:
- the name of the partition of the running application
- the name of the partition currently marked for boot next (typically the
same as the running application, but after
may point to a new application partition.
- a table whose keys are the names of OTA partitions and corresponding
values are tables containing:
state one of
undefined. The values
mean the same things. See the IDF documentation for specifics.
A partition in
testing state needs to call
if it wishes to become
name the application name, typically "NodeMCU"
date the build date
time the build time
version the build version, as set by the PROJECT_VER variable
secure_version the secure version number, if secure boot is enabled
idf_version the IDF version
boot_part, next_part, info = otaupgrade.info() print("Booted: "..boot_part) print(" Next: "..next_part) for p,t in pairs(info) do print("@ "..p..":") for k,v in pairs(t) do print(" "..k..": "..v) end end print("Running version: "..info[boot_part].version)
Wipes the spare application partition and prepares to receive the new application firmware.
If rollback support is enabled, note that the running application must first be marked valid/accepted before it is possible to commence a new OTA upgrade.
A Lua error may be raised if the OTA upgrade cannot be commenced for some reason (such as due to incorrect partition setup).
Write a chunk of application firmware data to the correct partition and location. Data must be streamed sequentially, the IDF does not support out-of-order data as would be the case from e.g. bittorrent.
dataa string of binary data
A Lua error may be raised if the data can not be written, e.g. due to the data not being a valid OTA image (the IDF performs some checks in this regard).
Finalises the upgrade, and optionally reboots into the new application firmware right away.
reboot1 to reboot into the new firmware immediately, nil to keep running
A Lua error may be raised if the image does not pass validation, or no data has been written to the image at all.
-- Quick, dirty and totally insecure "push upgrade" for development use. -- Use netcat to push a new firmware to a device: -- nc -q 1 your-device-ip 9999 < build/NodeMCU.bin -- osv = net.createServer() osv:listen(9999, function(conn) print('Commencing OTA upgrade') local status, err = pcall(otaupgrade.commence) if err then print(err) conn:send(err) conn:close() end conn:on('receive', function(sck, data) status, err = pcall(function() otaupgrade.write(data) end) if err then print(err) conn:send(err) conn:close() end end) conn:on('disconnection', function() print('EOF, completing OTA') status, err = pcall(function() otaupgrade.complete(1) end) if err then print(err) end end) end)
When the installed boot loader is built with rollback support, a new application image is by default only booted once. During this "test run" it can perform whatever checks is appropriate (like testing whether it can still reach the update server), and if satisfied can mark itself as valid. Without being marked valid, upon the next reboot the system would "roll back" to the previous version instead.
A new firmware may decide that it is not performing as expected, and request an explicit rollback to the previous version. If the call to this function succeeds, the system will reboot without returning from the call.
Note that it is also possible to roll back to a previous firmware
version even after the new version has called
Never. Either the system is rebooted, or a Lua error is raised (e.g. due to there being no other firmware to roll back to).