Over The Air Updates (OTA)¶
OTA Process Overview¶
The OTA update mechanism allows a device to update itself based on data received while the normal firmware is running (for example, over WiFi or Bluetooth.)
OTA requires configuring the Partition Table of the device with at least two “OTA app slot” partitions (ie ota_0 and ota_1) and an “OTA Data Partition”.
The OTA operation functions write a new app firmware image to whichever OTA app slot is not currently being used for booting. Once the image is verified, the OTA Data partition is updated to specify that this image should be used for the next boot.
OTA Data Partition¶
An OTA data partition (type
ota) must be included in the Partition Table
of any project which uses the OTA functions.
For factory boot settings, the OTA data partition should contain no data (all bytes erased to 0xFF). In this case the
esp-idf software bootloader will boot the factory app if it is present in the the partition table. If no factory app is
included in the partition table, the first available OTA slot (usually
ota_0) is booted.
After the first OTA update, the OTA data partition is updated to specify which OTA app slot partition should be booted next.
The OTA data partition is two flash sectors (0x2000 bytes) in size, to prevent problems if there is a power failure while it is being written. Sectors are independently erased and written with matching data, and if they disagree a counter field is used to determine which sector was written more recently.
The main purpose of the application rollback is to keep the device working after the update. This feature allows you to roll back to the previous working application in case a new application has critical errors. When the rollback process is enabled and an OTA update provides a new version of the app, one of three things can happen:
- The application works fine,
esp_ota_mark_app_valid_cancel_rollback()marks the running application with the state
ESP_OTA_IMG_VALID. There are no restrictions on booting this application.
- The application has critical errors and further work is not possible, a rollback to the previous application is required,
esp_ota_mark_app_invalid_rollback_and_reboot()marks the running application with the state
ESP_OTA_IMG_INVALIDand reset. This application will not be selected by the bootloader for boot and will boot the previously working application.
- If the CONFIG_APP_ROLLBACK_ENABLE option is set, and occur a reset without calling either function then happend and is rolled back.
Note: The state is not written to the binary image of the application it is written to the
otadata partition. The partition contains a
ota_seq counter which is a pointer to the slot (ota_0, ota_1, …) from which the application will be selected for boot.
App OTA State¶
States control the process of selecting a boot app:
|States||Restriction of selecting a boot app in bootloader|
|ESP_OTA_IMG_VALID||None restriction. Will be selected.|
|ESP_OTA_IMG_UNDEFINED||None restriction. Will be selected.|
|ESP_OTA_IMG_INVALID||Will not be selected.|
|ESP_OTA_IMG_ABORTED||Will not be selected.|
|ESP_OTA_IMG_NEW||If CONFIG_APP_ROLLBACK_ENABLE option is set
it will be selected only once. In bootloader the state
immediately changes to
|ESP_OTA_IMG_PENDING_VERIFY||If CONFIG_APP_ROLLBACK_ENABLE option is set
it will not be selected and the state will change to
If CONFIG_APP_ROLLBACK_ENABLE option is not enabled (by default), then the use of the following functions
esp_ota_mark_app_invalid_rollback_and_reboot() are optional, and
ESP_OTA_IMG_PENDING_VERIFY states are not used.
An option in Kconfig CONFIG_APP_ROLLBACK_ENABLE allows you to track the first boot of a new application. In this case, the application must confirm its operability by calling
esp_ota_mark_app_valid_cancel_rollback() function, otherwise the application will be rolled back upon reboot. It allows you to control the operability of the application during the boot phase. Thus, a new application has only one attempt to boot successfully.
The description of the rollback process when CONFIG_APP_ROLLBACK_ENABLE option is enabled:
- The new application successfully downloaded and
esp_ota_set_boot_partition()function makes this partition bootable and sets the state
ESP_OTA_IMG_NEW. This state means that the application is new and should be monitored for its first boot.
- The bootloader checks for the
ESP_OTA_IMG_PENDING_VERIFYstate if it is set, then it will be written to
- The bootloader selects a new application to boot so that the state is not set as
- The bootloader checks the selected application for
ESP_OTA_IMG_NEWstate if it is set, then it will be written to
ESP_OTA_IMG_PENDING_VERIFY. This state means that the application requires confirmation of its operability, if this does not happen and a reboot occurs, this state will be overwritten to
ESP_OTA_IMG_ABORTED(see above) and this application will no longer be able to start, i.e. there will be a rollback to the previous work application.
- A new application has started and should make a self-test.
- If the self-test has completed successfully, then you must call the function
esp_ota_mark_app_valid_cancel_rollback()because the application is awaiting confirmation of operability (
- If the self-test fails then call
esp_ota_mark_app_invalid_rollback_and_reboot()function to roll back to the previous working application, while the invalid application is set
- If the application has not been confirmed, the state remains
ESP_OTA_IMG_PENDING_VERIFY, and the next boot it will be changed to
ESP_OTA_IMG_ABORTED. That will prevent re-boot of this application. There will be a rollback to the previous working application.
If a power loss or an unexpected crash occurs at the time of the first boot of a new application, it will roll back the application.
Recommendation: Perform the self-test procedure as quickly as possible, to prevent rollback due to power loss.
OTA partitions can be rolled back. Factory partition is not rolled back.
Booting invalid/aborted apps¶
Booting an application which was previously set to
ESP_OTA_IMG_ABORTED is possible:
- Get the last invalid application partition
- Pass the received partition to
esp_ota_set_boot_partition(), this will update the
esp_restart(). The bootloader will boot the specified application.
To determine if self-tests should be run during startup of an application, call the
esp_ota_get_state_partition() function. If result is
ESP_OTA_IMG_PENDING_VERIFY then self-testing and subsequent confirmation of operability is required.
Where the states are set¶
A brief description of where the states are set:
ESP_OTA_IMG_VALIDstate is set by
ESP_OTA_IMG_UNDEFINEDstate is set by
esp_ota_set_boot_partition()function if CONFIG_APP_ROLLBACK_ENABLE option is not enabled.
ESP_OTA_IMG_NEWstate is set by
esp_ota_set_boot_partition()function if CONFIG_APP_ROLLBACK_ENABLE option is enabled.
ESP_OTA_IMG_INVALIDstate is set by
ESP_OTA_IMG_ABORTEDstate is set if there was no confirmation of the application operability and occurs reboots (if CONFIG_APP_ROLLBACK_ENABLE option is enabled).
ESP_OTA_IMG_PENDING_VERIFYstate is set in a bootloader if CONFIG_APP_ROLLBACK_ENABLE option is enabled and selected app has
Secure OTA Updates Without Secure boot¶
The verification of signed OTA updates can be performed even without enabling hardware secure boot. For doing so, refer Signed App Verification Without Hardware Secure Boot
const esp_app_desc_t *
Return esp_app_desc structure. This structure includes app version.
Return description for running app.
- Pointer to esp_app_desc structure.
esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp_ota_handle_t *out_handle)¶
Commence an OTA update writing to the specified partition.
The specified partition is erased to the specified image size.
If image size is not yet known, pass OTA_SIZE_UNKNOWN which will cause the entire partition to be erased.
On success, this function allocates memory that remains in use until esp_ota_end() is called with the returned handle.
- ESP_OK: OTA operation commenced successfully.
- ESP_ERR_INVALID_ARG: partition or out_handle arguments were NULL, or partition doesn’t point to an OTA app partition.
- ESP_ERR_NO_MEM: Cannot allocate memory for OTA operation.
- ESP_ERR_OTA_PARTITION_CONFLICT: Partition holds the currently running firmware, cannot update in place.
- ESP_ERR_NOT_FOUND: Partition argument not found in partition table.
- ESP_ERR_OTA_SELECT_INFO_INVALID: The OTA data partition contains invalid data.
- ESP_ERR_INVALID_SIZE: Partition doesn’t fit in configured flash size.
- ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash write failed.
partition: Pointer to info for partition which will receive the OTA update. Required.
image_size: Size of new OTA app image. Partition will be erased in order to receive this size of image. If 0 or OTA_SIZE_UNKNOWN, the entire partition is erased.
out_handle: On success, returns a handle which should be used for subsequent esp_ota_write() and esp_ota_end() calls.
esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)¶
Write OTA update data to partition.
This function can be called multiple times as data is received during the OTA operation. Data is written sequentially to the partition.
- ESP_OK: Data was written to flash successfully.
- ESP_ERR_INVALID_ARG: handle is invalid.
- ESP_ERR_OTA_VALIDATE_FAILED: First byte of image contains invalid app image magic byte.
- ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash write failed.
- ESP_ERR_OTA_SELECT_INFO_INVALID: OTA data partition has invalid contents
handle: Handle obtained from esp_ota_begin
data: Data buffer to write
size: Size of data buffer in bytes.
Finish OTA update and validate newly written app image.
- After calling esp_ota_end(), the handle is no longer valid and any memory associated with it is freed (regardless of result).
- ESP_OK: Newly written OTA app image is valid.
- ESP_ERR_NOT_FOUND: OTA handle was not found.
- ESP_ERR_INVALID_ARG: Handle was never written to.
- ESP_ERR_OTA_VALIDATE_FAILED: OTA image is invalid (either not a valid app image, or - if secure boot is enabled - signature failed to verify.)
- ESP_ERR_INVALID_STATE: If flash encryption is enabled, this result indicates an internal error writing the final encrypted bytes to flash.
handle: Handle obtained from esp_ota_begin().
esp_ota_set_boot_partition(const esp_partition_t *partition)¶
Configure OTA data for a new boot partition.
- If this function returns ESP_OK, calling esp_restart() will boot the newly configured app partition.
- ESP_OK: OTA data updated, next reboot will use specified partition.
- ESP_ERR_INVALID_ARG: partition argument was NULL or didn’t point to a valid OTA partition of type “app”.
- ESP_ERR_OTA_VALIDATE_FAILED: Partition contained invalid app image. Also returned if secure boot is enabled and signature validation failed.
- ESP_ERR_NOT_FOUND: OTA data partition not found.
- ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash erase or write failed.
partition: Pointer to info for partition containing app image to boot.
const esp_partition_t *
Get partition info of currently configured boot app.
If esp_ota_set_boot_partition() has been called, the partition which was set by that function will be returned.
If esp_ota_set_boot_partition() has not been called, the result is usually the same as esp_ota_get_running_partition(). The two results are not equal if the configured boot partition does not contain a valid app (meaning that the running partition will be an app that the bootloader chose via fallback).
If the OTA data partition is not present or not valid then the result is the first app partition found in the partition table. In priority order, this means: the factory app, the first OTA app slot, or the test app partition.
Note that there is no guarantee the returned partition is a valid app. Use esp_image_verify(ESP_IMAGE_VERIFY, …) to verify if the returned partition contains a bootable image.
- Pointer to info for partition structure, or NULL if partition table is invalid or a flash read operation failed. Any returned pointer is valid for the lifetime of the application.
const esp_partition_t *
Get partition info of currently running app.
This function is different to esp_ota_get_boot_partition() in that it ignores any change of selected boot partition caused by esp_ota_set_boot_partition(). Only the app whose code is currently running will have its partition information returned.
The partition returned by this function may also differ from esp_ota_get_boot_partition() if the configured boot partition is somehow invalid, and the bootloader fell back to a different app partition at boot.
- Pointer to info for partition structure, or NULL if no partition is found or flash read operation failed. Returned pointer is valid for the lifetime of the application.
const esp_partition_t *
esp_ota_get_next_update_partition(const esp_partition_t *start_from)¶
Return the next OTA app partition which should be written with a new firmware.
Call this function to find an OTA app partition which can be passed to esp_ota_begin().
Finds next partition round-robin, starting from the current running partition.
- Pointer to info for partition which should be updated next. NULL result indicates invalid OTA data partition, or that no eligible OTA app slot partition was found.
start_from: If set, treat this partition info as describing the current running partition. Can be NULL, in which case esp_ota_get_running_partition() is used to find the currently running partition. The result of this function is never the same as this argument.
esp_ota_get_partition_description(const esp_partition_t *partition, esp_app_desc_t *app_desc)¶
Returns esp_app_desc structure for app partition. This structure includes app version.
Returns a description for the requested app partition.
- ESP_OK Successful.
- ESP_ERR_NOT_FOUND app_desc structure is not found. Magic word is incorrect.
- ESP_ERR_NOT_SUPPORTED Partition is not application.
- ESP_ERR_INVALID_ARG Arguments is NULL or if partition’s offset exceeds partition size.
- ESP_ERR_INVALID_SIZE Read would go out of bounds of the partition.
- or one of error codes from lower-level flash driver.
partition: Pointer to app partition. (only app partition)
app_desc: Structure of info about app.
This function is called to indicate that the running app is working well.
- ESP_OK: if successful.
This function is called to roll back to the previously workable app with reboot.
If rollback is successful then device will reset else API will return with error code.
- ESP_FAIL: if not successful.
const esp_partition_t *
Returns last partition with invalid state (ESP_OTA_IMG_INVALID or ESP_OTA_IMG_ABORTED).
esp_ota_get_state_partition(const esp_partition_t *partition, esp_ota_img_states_t *ota_state)¶
Returns state for given partition.
- ESP_OK: Successful.
- ESP_ERR_INVALID_ARG: partition or ota_state arguments were NULL.
- ESP_ERR_NOT_SUPPORTED: partition is not ota.
- ESP_ERR_NOT_FOUND: Partition table does not have otadata or state was not found for given partition.
partition: Pointer to partition.
ota_state: state of partition (if this partition has a record in otadata).
Used for esp_ota_begin() if new image size is unknown
Base error code for ota_ops api
Error if request was to write or erase the current running partition
Error if OTA data partition contains invalid content
Error if OTA app image is invalid