空中升级(OTA)

OTA 过程概述

OTA 升级机制允许常规固件在运行时基于它所接收的数据对设备进行升级(通过 WiFI 或者蓝牙)。

OTA 需要配置设备的 Partition Table,且至少需要两个 “OTA app” 分区(即 ota_0ota_1)和一个 “OTA 数据分区”。

OTA 会将新的 app 固件镜像写到当前未用于启动程序的那个 OTA app 分区。当镜像校验完成后,OTA 数据分区会被更新,表示下一次启动时将使用该镜像。

OTA 数据分区

使用 OTA 功能的产品必须在 Partition Table 中包含一个 OTA 数据分区。

对于工厂启动设置,OTA 数据分区应当不包含数据(所有的字节被擦除为 0xFF)。在这种情况下,如果分区表中存在工厂 app,esp-idf 软件的 bootloader 会启动工厂 app。如果分区表中不存在工厂 app,则会启动第一个有效的 OTA 分区(通常是 ota_0)。

当第一次 OTA 更新后,OTA 数据分区将会被更新,表示表示下一次启动时将使用哪个 OTA app 分区。

OTA 数据分期是两个 flash 扇区(0x2000 字节),以消除正在写时供电失败的问题。如果没有计数字段表明哪个扇区在最近被写过,则两个扇区会被独立擦除并写入匹配的数据。

应用程序示例

端到端的 OTA 固件升级流程请你参考: system/ota

API 参考手册

ESP_ERR_OTA_BASE

Base error code for ota_ops api

ESP_ERR_OTA_PARTITION_CONFLICT

Error if request was to write or erase the current running partition

ESP_ERR_OTA_SELECT_INFO_INVALID

Error if OTA data partition contains invalid content

ESP_ERR_OTA_VALIDATE_FAILED

Error if OTA app image is invalid

OTA_SIZE_UNKNOWN

Used for esp_ota_begin() if new image size is unknown

类型定义

typedef uint32_t esp_ota_handle_t

Opaque handle for an application OTA update.

esp_ota_begin() returns a handle which is then used for subsequent calls to esp_ota_write() and esp_ota_end().

函数

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

Return
  • 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.
Parameters
  • 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_err_t 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.

Return
  • 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
Parameters
  • handle: Handle obtained from esp_ota_begin
  • data: Data buffer to write
  • size: Size of data buffer in bytes.

esp_err_t esp_ota_end(esp_ota_handle_t handle)

Finish OTA update and validate newly written app image.

Note
After calling esp_ota_end(), the handle is no longer valid and any memory associated with it is freed (regardless of result).
Return
  • 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.
Parameters
  • handle: Handle obtained from esp_ota_begin().

const esp_partition_t *esp_ota_get_running_partition(void)

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.

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

esp_err_t esp_ota_set_boot_partition(const esp_partition_t *partition)

Configure OTA data for a new boot partition.

Note
If this function returns ESP_OK, calling esp_restart() will boot the newly configured app partition.
Return
  • 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.
Parameters
  • partition: Pointer to info for partition containing app image to boot.

const esp_partition_t *esp_ota_get_boot_partition(void)

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 equivalent to esp_ota_get_running_partition().

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

Return
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.
Parameters
  • 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.