ES32中OTA空中升级

news2024/9/22 7:39:13

打开SDK可视化配置,检查flash大小设定和“partition table”分区表设定。

左下角,点击SDK可视化配置按钮,进入配置。flash大小为4MB,Partition Table选择Factory app, two OTA definitions,分区表烧写偏移地址0x8000,如果默认是这样,则不用修改,直接关闭窗口即可

从 AWS S3 等服务获取映像时,此选项非常有用,其中 mbedTLS Rx 缓冲区大小 (CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN) 可以设置为较低的值,如果不启用此配置,这是不可能的。

http服务器:

1、HFS的http服务器地址 把XXX.bin 固件拖进服务器。

2、在终端bin目录执行:python -m http.server 8070 通过url访问

应用程序版本

应用程序版本存储在 esp_app_desc_t 结构体中。 该结构体位于 DROM 扇区,有一个从二进制文件头部计算的固定偏移值。 该结构体位于 esp_image_header_t 和 esp_image_segment_header_t 结构体之后。 字段 Version 类型为字符串,最大长度为 32 字节。

若需手动设置版本,需要在项目的 文件中设置 变量,即在 文件中,在包含 之前添加 。CMakeLists.txtPROJECT_VERCMakeLists.txtproject.cmakeset(PROJECT_VER "0.1.0.1")

如果设置了 CONFIG_APP_PROJECT_VER_FROM_CONFIG 选项,则将使用 CONFIG_APP_PROJECT_VER 的值。 否则,如果在项目中未设置 变量,则该变量将从 文件(若有)中检索,或使用 git 命令 检索。 如果两者都不可用,则 将被设置为 “1”。 应用程序可通过调用 esp_app_get_description() 或 esp_ota_get_partition_description() 函数来获取应用程序的版本信息。PROJECT_VER$(PROJECT_PATH)/version.txtgit describePROJECT_VER

一、API函数

esp_ota_begin    //开始写入指定分区的 OTA 更新,指定的分区被擦除到指定的图像大小。
esp_ota_write    //将 OTA 更新数据写入分区。数据按顺序写入分区。
esp_ota_write_with_offset    //将 OTA 更新数据写入分区。可以以非连续方式写入数据。
esp_ota_end    //完成 OTA 更新并验证新编写的应用映像。
esp_ota_abort    //中止 OTA 更新,释放与之关联的句柄和内存。
esp_ota_set_boot_partition    //为新的引导分区配置 OTA 数据。
esp_ota_get_boot_partition    //获取当前配置的启动应用程序的分区信息。
esp_ota_get_running_partition    //获取当前运行的应用程序的分区信息。
esp_ota_get_next_update_partition    //返回下一个应使用新固件写入的 OTA 应用程序分区。
esp_ota_get_partition_description    //返回应用分区的 esp_app_desc 结构。此结构包括应用程序版本。
esp_ota_mark_app_valid_cancel_rollback    //调用此函数以指示正在运行的应用程序运行良好。
esp_ota_mark_app_invalid_rollback_and_reboot    //调用此函数以通过重启回滚到以前可用的应用程序。
esp_ota_get_last_invalid_partition    //返回最后一个状态无效的分区(ESP_OTA_IMG_INVALID 或 ESP_OTA_IMG_ABORTED)
esp_ota_get_state_partition    //返回给定分区的状态。
esp_ota_erase_last_boot_app_partition    //擦除以前的启动应用程序分区和此分区的相应 otadata 选择。
esp_ota_check_rollback_is_possible    //检查可以在回滚的情况下启动的插槽上的应用程序。

详细介绍:

const esp_app_desc_t*esp_ota_get_app_description(void)

返回esp_app_desc结构。此结构包括应用版本。正在运行的应用的返回说明。备注此 API 的存在是出于向后兼容性的原因。具有相同功能的替代功能是esp_app_get_description

返回指向esp_app_desc结构的指针。

int esp_ota_get_app_elf_sha256(char*dst,size_t size)

用 ELF 文件的 SHA256 填充提供的缓冲区,格式为十六进制,以 null 结尾。如果缓冲区大小不足以容纳十六进制加上空终止符的整个 SHA256,则将写入最大可能的字节数,后跟一个空。备注此 API 的存在是出于向后兼容性的原因。具有相同功能的替代功能是esp_app_get_elf_sha256

参数 dst – 目标缓冲区大小 size– 缓冲区的大小

返回写入 dst 的字节数(包括空终止符)

esp_err_t esp_ota_begin(常量esp_partition_t*分区,size_t image_size,esp_ota_handle_t* out_处理)

开始写入指定分区的 OTA 更新。指定的分区将擦除为指定的映像大小。如果图像大小尚未知,请传递OTA_SIZE_UNKNOWN这将导致整个分区被擦除。成功后,此函数将分配仍在使用的内存,直到使用返回的句柄调用 esp_ota_end()。注意:如果启用了回滚选项,并且正在运行的应用程序具有ESP_OTA_IMG_PENDING_VERIFY状态,则会导致ESP_ERR_OTA_ROLLBACK_INVALID_STATE错误。在运行下载新应用程序之前确认正在运行的应用程序,请使用 esp_ota_mark_app_valid_cancel_rollback() 函数(这应该在您首次下载新应用程序时尽早完成)。

参数分区 – 指向将接收 OTA 更新的分区信息的指针。必填。

image_size– 新 OTA 应用程序图像的大小。分区将被擦除以接收此大小的图像。如果为 0 或 OTA_SIZE_UNKNOWN,则擦除整个分区。

out_handle– 成功后,返回一个句柄,该句柄应用于后续的 esp_ota_write() 和 esp_ota_end() 调用。

返回ESP_OK:OTA运营成功。ESP_ERR_INVALID_ARG:分区或out_handle参数为 NULL,或者分区不指向 OTA 应用分区。ESP_ERR_NO_MEM:无法为 OTA 操作分配内存。ESP_ERR_OTA_PARTITION_CONFLICT:分区保存当前正在运行的固件,无法就地更新。ESP_ERR_NOT_FOUND:在分区表中找不到分区参数。ESP_ERR_OTA_SELECT_INFO_INVALID:OTA数据分区包含无效数据。ESP_ERR_INVALID_SIZE:分区不适合配置的闪存大小。ESP_ERR_FLASH_OP_TIMEOUT或ESP_ERR_FLASH_OP_FAIL:闪存写入失败。ESP_ERR_OTA_ROLLBACK_INVALID_STATE:如果正在运行的应用尚未确认状态。在执行更新之前,应用程序必须有效。

esp_err_t esp_ota_write(esp_ota_handle_t 句柄,常量空* 数据,size_t 大小)

将 OTA 更新数据写入分区。在 OTA 操作期间接收数据时,可以多次调用此函数。数据按顺序写入分区。

参数句柄 – 从esp_ota_begin获取的句柄

data– 要写入的数据缓冲区

size– 数据缓冲区的大小(以字节为单位)。

返回ESP_OK:数据已成功写入刷机。ESP_ERR_INVALID_ARG:句柄无效。ESP_ERR_OTA_VALIDATE_FAILED:图像的第一个字节包含无效的应用图像魔术字节。ESP_ERR_FLASH_OP_TIMEOUT或ESP_ERR_FLASH_OP_FAIL:闪存写入失败。ESP_ERR_OTA_SELECT_INFO_INVALID:OTA数据分区包含无效内容

esp_err_t esp_ota_write_with_offset(esp_ota_handle_t句柄,常量空*数据,size_t大小,uint32_t抵消)

将 OTA 更新数据写入偏移分区。此函数可以以非连续的方式写入数据。如果启用了 Flash 加密,则数据应对齐 16 个字节。备注在执行 OTA 时,如果数据包无序到达,可以使用 esp_ota_write_with_offset() 以非连续方式写入数据。不建议将 esp_ota_write_with_offset() 与 esp_ota_write() 结合使用。

参数句柄 – 从esp_ota_begin获取的句柄

data– 要写入的数据缓冲区

size– 数据缓冲区的大小(以字节为单位)

偏移 – 闪存分区中的偏移

返回ESP_OK:数据已成功写入刷机。ESP_ERR_INVALID_ARG:句柄无效。ESP_ERR_OTA_VALIDATE_FAILED:图像的第一个字节包含无效的应用图像魔术字节。ESP_ERR_FLASH_OP_TIMEOUT或ESP_ERR_FLASH_OP_FAIL:闪存写入失败。ESP_ERR_OTA_SELECT_INFO_INVALID:OTA数据分区包含无效内容

esp_err_t esp_ota_end(esp_ota_handle_t 手柄)

完成 OTA 更新并验证新编写的应用映像。备注调用 esp_ota_end() 后,句柄不再有效,并且释放与其关联的任何内存(无论结果如何)。参数handle– 从 esp_ota_begin() 获取的句柄。返回ESP_OK:新写入的 OTA 应用镜像有效。ESP_ERR_NOT_FOUND:找不到 OTA 句柄。ESP_ERR_INVALID_ARG:句柄从未被写过。ESP_ERR_OTA_VALIDATE_FAILED:OTA 映像无效(不是有效的应用映像,或者 - 如果启用了安全启动 - 签名验证失败。ESP_ERR_INVALID_STATE:如果启用了 flash 加密,则此结果表示将最终加密字节写入闪存时出现内部错误。

esp_err_t esp_ota_abort(esp_ota_handle_t 手柄))

中止 OTA 更新,释放与其关联的句柄和内存。参数句柄 – 从 esp_ota_begin() 获得。返回ESP_OK:句柄及其关联的内存已成功释放。ESP_ERR_NOT_FOUND:找不到 OTA 句柄。

esp_err_t esp_ota_set_boot_partition(常量esp_partition_t*分区))

为新的引导分区配置 OTA 数据。备注如果此函数返回 ESP_OK,则调用 esp_restart() 将引导新配置的应用程序分区。参数分区 – 指向包含要启动的应用映像的分区信息的指针。返回ESP_OK:OTA数据已更新,下次重启将使用指定的分区。ESP_ERR_INVALID_ARG:分区参数为 NULL 或未指向类型为“app”的有效 OTA 分区。ESP_ERR_OTA_VALIDATE_FAILED:分区包含无效的应用映像。如果启用了安全启动且签名验证失败,则也会返回。ESP_ERR_NOT_FOUND:找不到 OTA 数据分区。ESP_ERR_FLASH_OP_TIMEOUT或ESP_ERR_FLASH_OP_FAIL:闪存擦除或写入失败。

常量 esp_partition_t*esp_ota_get_boot_partition(void)

获取当前配置的启动应用的分区信息。如果调用了 esp_ota_set_boot_partition(),则将返回该函数设置的分区。如果未调用 esp_ota_set_boot_partition(),则结果通常与 esp_ota_get_running_partition() 相同。如果配置的引导分区不包含有效的应用(这意味着正在运行的分区将是引导加载程序通过回退选择的应用),则这两个结果不相等。如果 OTA 数据分区不存在或无效,则结果是在分区表中找到的第一个应用分区。按优先级顺序,这意味着:工厂应用、第一个 OTA 应用槽或测试应用分区。请注意,不能保证返回的分区是有效的应用。使用 esp_image_verify(ESP_IMAGE_VERIFY, ...) 验证返回的分区是否包含可引导映像。返回指向分区结构信息的指针,如果分区表无效或闪存读取操作失败,则为 NULL。任何返回的指针在应用程序的生存期内都有效。

常量 esp_partition_t*esp_ota_get_running_partition(无效)

获取当前正在运行的应用程序的分区信息。此函数与 esp_ota_get_boot_partition() 的不同之处在于它忽略由 esp_ota_set_boot_partition() 引起的所选引导分区的任何更改。只有代码当前正在运行的应用才会返回其分区信息。如果配置的引导分区以某种方式无效,并且引导加载程序在引导时回退到不同的应用分区,则此函数返回的分区也可能与 esp_ota_get_boot_partition() 不同。返回指向分区结构信息的指针,如果未找到分区或闪存读取操作失败,则为 NULL。返回的指针在应用程序的生存期内有效。

const esp_partition_t*esp_ota_get_next_update_partition(constesp_partition_t*start_from)

返回应使用新固件写入的下一个 OTA 应用程序分区。调用此函数以查找可以传递给 esp_ota_begin() 的 OTA 应用分区。查找下一个分区轮循机制,从当前正在运行的分区开始。参数start_from– 如果设置,请将此分区信息视为描述当前正在运行的分区。可以为 NULL,在这种情况下,esp_ota_get_running_partition() 用于查找当前正在运行的分区。此函数的结果永远不会与此参数相同。返回指向接下来应更新的分区信息的指针。NULL 结果表示 OTA 数据分区无效,或者未找到符合条件的 OTA 应用槽分区。

esp_err_t esp_ota_get_partition_description(常量esp_partition_t*分区,esp_app_desc_t*app_desc)

返回应用分区esp_app_desc结构。此结构包括应用版本。返回所请求的应用程序分区的说明。

参数分区–

[输入]指向应用分区的指针。(仅限应用分区)

app_desc–[输出]有关应用的信息结构。

返回ESP_OK成功。找不到ESP_ERR_NOT_FOUND app_desc结构。魔术词不正确。ESP_ERR_NOT_SUPPORTED分区不是应用程序。ESP_ERR_INVALID_ARG 参数为 NULL 或分区的偏移量超过分区大小。ESP_ERR_INVALID_SIZE读取将超出分区的范围。或来自较低级别的闪存驱动程序的错误代码之一。

uint8_t esp_ota_get_app_partition_count(无效)

返回分区表中提供的 ota 分区数。

返回OTA 分区数

esp_err_t esp_ota_mark_app_valid_cancel_rollback(无效)

调用此函数以指示正在运行的应用运行良好。

返回ESP_OK:如果成功。

esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot(无效)

调用此函数以在重新启动时回滚到以前可用的应用程序。如果回滚成功,则设备将重置,否则 API 将返回错误代码。检查闪存驱动器上的应用程序,以便在回滚时启动。如果闪存没有至少一个应用程序(正在运行的应用程序除外),则无法回滚。

返回ESP_FAIL:如果不成功。ESP_ERR_OTA_ROLLBACK_FAILED:由于闪存没有任何应用程序,因此无法回滚。

常量 esp_partition_t*esp_ota_get_last_invalid_partition(void)

返回状态无效的最后一个分区(ESP_OTA_IMG_INVALID 或 ESP_OTA_IMG_ABORTED)。

返回分区。

esp_err_t esp_ota_get_state_partition(constesp_partition_t*partition,esp_ota_img_states_t*ota_state)

返回给定分区的状态。

参数分区–

[输入]指向分区的指针。

分区的ota_state–[out]状态(如果此分区在 OTADATA 中有记录)。

返回ESP_OK:成功。ESP_ERR_INVALID_ARG:分区或ota_state参数为 NULL。ESP_ERR_NOT_SUPPORTED:分区不是太田。ESP_ERR_NOT_FOUND:分区表没有 otadata,或者找不到给定分区的状态。

esp_err_t esp_ota_erase_last_boot_app_partition(无效)

擦除以前的启动应用程序分区以及为此分区选择的相应 otadata。当当前应用程序标记为有效时,您可以擦除以前的应用程序分区。

返回ESP_OK:成功,否则ESP_ERR。

布尔 esp_ota_check_rollback_is_possible(无效)

检查插槽上的应用程序,以便在回滚时引导。这些应用程序应该是有效的(在 otadata 中标记为未定义、无效或中止且 crc 良好)并且能够启动,并且应用程序> = secure_version 的 efuse(如果启用了反回滚)secure_version。

返回True:如果槽至少有一个应用(正在运行的应用除外),则返回 true。错误:无法回滚。

二、ESP HTTPS OTA

esp_err_t esp_https_ota(const esp_https_ota_config_t *ota_config)

HTTPS OTA 固件升级。该函数分配HTTPS OTA固件升级上下文,建立HTTPS连接,从HTTP流中读取镜像数据并将其写入OTA分区,完成HTTPS OTA固件升级操作。此 API 支持 URL 重定向,但如果 URL 的 CA 证书不同,则应将其追加到成员。cert_pemota_config->http_config备注此 API 处理整个 OTA 操作,因此如果使用此 API,则不应调用来自组件的其他 API。如果在HTTPS OTA过程中需要更多信息和控制,则可以使用后续API。如果此 API 成功返回,则必须调用 esp_restart() 才能从新固件映像启动。esp_https_otaesp_https_ota_begin

参数ota_config – 指向esp_https_ota_config_t结构的指针。

返回ESP_OK:OTA数据已更新,下次重启将使用指定的分区。ESP_FAIL:用于一般故障。ESP_ERR_INVALID_ARG:参数无效ESP_ERR_OTA_VALIDATE_FAILED:应用图像无效ESP_ERR_NO_MEM:无法为 OTA 操作分配内存。ESP_ERR_FLASH_OP_TIMEOUT或ESP_ERR_FLASH_OP_FAIL:闪存写入失败。有关其他返回码,请参阅 esp-idf app_update组件中的 OTA 文档。

esp_err_t esp_https_ota_begin(const esp_https_ota_config_t *ota_config, esp_https_ota_handle_t *handle)

启动 HTTPS OTA 固件升级。此函数初始化 ESP HTTPS OTA 上下文并建立 HTTPS 连接。必须先调用此函数。如果此函数成功返回,则应调用该函数以继续执行 OTA 进程,并且应该调用 toon 完成 OTA 操作或后续操作失败。此 API 支持 URL 重定向,但如果 URL 的 CA 证书不同,则应将其附加到成员,这是其中的一部分。如果出现错误,此 API 显式设置为 NULL。esp_https_ota_performesp_https_ota_finishcert_pemhttp_configota_confighandle备注此 API 正在阻塞,因此设置结构成员将导致错误。is_asynchttp_config

参数ota_config 指向esp_https_ota_config_t结构的指针handle–[out]指向已分配数据类型的指针将在此函数中初始化esp_https_ota_handle_t

返回ESP_OK:初始化 HTTPS OTA 固件升级上下文并建立 HTTPS 连接ESP_FAIL:用于一般故障。ESP_ERR_INVALID_ARG:参数无效(缺少/不正确的配置、证书等)有关其他返回码,请参阅 esp-idf 中app_update组件和esp_http_client组件中的文档。

esp_err_t esp_https_ota_perform(esp_https_ota_handle_t https_ota_handle)

从HTTP流中读取图像数据并将其写入OTA分区。此函数从 HTTP 流中读取图像数据并将其写入 OTA 分区。仅当 esp_https_ota_begin() 成功返回时,才必须调用此函数。此函数必须在循环中调用,因为它在每个 HTTP 读取操作后返回,从而使您能够灵活地在中途停止 OTA 操作。参数https_ota_handle [in]指向esp_https_ota_handle_t结构的指针返回ESP_ERR_HTTPS_OTA_IN_PROGRESS:正在进行OTA更新,请再次调用此接口继续。ESP_OK:OTA更新成功ESP_FAIL:OTA 更新失败ESP_ERR_INVALID_ARG:参数无效ESP_ERR_INVALID_VERSION:映像标头中的芯片修订无效ESP_ERR_OTA_VALIDATE_FAILED:应用图像无效ESP_ERR_NO_MEM:无法为 OTA 操作分配内存。ESP_ERR_FLASH_OP_TIMEOUT或ESP_ERR_FLASH_OP_FAIL:闪存写入失败。有关其他返回码,请参阅 esp-idf app_update组件中的 OTA 文档。

bool esp_https_ota_is_complete_data_received(esp_https_ota_handle_t https_ota_handle)

检查是否收到完整的数据。备注可以在 esp_https_ota_finish() 之前调用此 API,以验证是否确实收到了完整的映像。

参数https_ota_handle [in]指向esp_https_ota_handle_t结构的指针

返回假真

esp_err_t esp_https_ota_finish(esp_https_ota_handle_t https_ota_handle)

清理 HTTPS OTA 固件升级并关闭 HTTPS 连接。此函数关闭 HTTP 连接并释放 ESP HTTPS OTA 上下文。此函数将引导分区切换到包含新固件映像的 OTA 分区。备注如果此 API 成功返回,则必须调用 esp_restart() 才能从新固件映像启动,esp_https_ota_finish调用后不应调用esp_https_ota_abort

参数https_ota_handle [in]指向esp_https_ota_handle_t结构的指针

返回ESP_OK:清理成功ESP_ERR_INVALID_STATEESP_ERR_INVALID_ARG:参数无效ESP_ERR_OTA_VALIDATE_FAILED:应用图像无效

esp_err_t esp_https_ota_abort(esp_https_ota_handle_t https_ota_handle)

清理 HTTPS OTA 固件升级并关闭 HTTPS 连接。此函数关闭 HTTP 连接并释放 ESP HTTPS OTA 上下文。备注esp_https_ota_abort不应在调用esp_https_ota_finish后调用

参数https_ota_handle [in]指向esp_https_ota_handle_t结构的指针

返回ESP_OK:清理成功ESP_ERR_INVALID_STATE:无效的 ESP HTTPS OTA 状态ESP_FAIL:OTA 未启动ESP_ERR_NOT_FOUND:找不到 OTA 句柄ESP_ERR_INVALID_ARG:参数无效

esp_err_t esp_https_ota_get_img_desc(esp_https_ota_handle_t https_ota_handle, esp_app_desc_t *new_app_info)

从图像标头读取应用说明。应用说明提供了映像的“固件版本”等信息。备注只能在 esp_https_ota_begin() 之后和 esp_https_ota_perform() 之前调用此 API。调用此 API 不是强制性的。

参数https_ota_handle [in]指向esp_https_ota_handle_t结构的指针new_app_info–[out]指向已分配esp_app_desc_t结构的指针

返回ESP_ERR_INVALID_ARG:参数无效ESP_ERR_INVALID_STATE:调用此 API 的状态无效。esp_https_ota_begin() 尚未调用。ESP_FAIL:无法读取图像描述符ESP_OK:成功读取图像描述符

int esp_https_ota_get_image_len_read(esp_https_ota_handle_t https_ota_handle)

此函数返回到目前为止读取的 OTA 图像数据。备注仅当至少调用过一次或之前调用过 if 时,才应调用此 API。esp_https_ota_perform()esp_https_ota_get_img_desc

参数https_ota_handle [in]指向esp_https_ota_handle_t结构的指针

返回-1 失败时到目前为止读取的总字节数

int esp_https_ota_get_image_size(esp_https_ota_handle_t https_ota_handle)

此函数返回 OTA 图像总大小。备注此 API 应在调用 esp_https_ota_begin() 后调用。这可用于创建某种进度指示(与 esp_https_ota_get_image_len_read()结合使用)

参数https_ota_handle [in]指向esp_https_ota_handle_t结构的指针

返回-1 失败或分块编码时图像的总字节数

const esp_partition_t *esp_ota_get_next_update_partition(const esp_partition_t *start_from)

返回应使用新固件写入的下一个 OTA 应用程序分区。调用此函数以查找可以传递给 esp_ota_begin() 的 OTA 应用分区。查找下一个分区轮循机制,从当前正在运行的分区开始。

参数:start_from – 如果设置,请将此分区信息视为描述当前正在运行的分区。可以为 NULL,在这种情况下,esp_ota_get_running_partition() 用于查找当前正在运行的分区。此函数的结果永远不会与此参数相同。

返回:指向接下来应更新的分区信息的指针。NULL 结果表示 OTA 数据分区无效,或者未找到符合条件的 OTA 应用槽分区。

应用实测(采用HTTP OTA)

使用示例:

#include "sit_lib_ota_internal.h"

static const char *TAG = "https_ota";
extern const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start");
extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end");


#define OTA_URL_SIZE 256

static esp_err_t validate_image_header(esp_app_desc_t *new_app_info)
{
    if (new_app_info == NULL) {
        return ESP_ERR_INVALID_ARG;
    }

    const esp_partition_t *running = esp_ota_get_running_partition(); //获取当前运行的分区
    esp_app_desc_t running_app_info;
    if (esp_ota_get_partition_description(running, &running_app_info) == ESP_OK) {
        ESP_LOGI(TAG, "Running firmware version: %s", running_app_info.version);
        vTaskDelay(20 / portTICK_PERIOD_MS);//加延时 防止出现socket通讯错误问题 
    }

    //  检测是否为同一版本 
    if (memcmp(new_app_info->version, running_app_info.version, sizeof(new_app_info->version)) == 0) {
        ESP_LOGW(TAG, "Current running version is the same as a new. We will not continue the update.");
        return ESP_FAIL;
    }

    /**
     * 从固件映像头进行安全版本检查,防止后续下载和flash写入整个固件映像。(版本检测)
     * 然而,这是可选的,因为它也在OTA更新过程末尾的API esp_https_ota_finish中被注意到了。
     */
    const uint32_t hw_sec_version = esp_efuse_read_secure_version();
    if (new_app_info->secure_version < hw_sec_version) {
        ESP_LOGW(TAG, "New firmware security version is less than eFuse programmed, %lu < %lu", new_app_info->secure_version, hw_sec_version);
        return ESP_FAIL;
    }

    return ESP_OK;
}

static esp_err_t _http_client_init_cb(esp_http_client_handle_t http_client)
{
    esp_err_t err = ESP_OK;
    return err;
}

void advanced_ota_example_task(void *pvParameter)
{
    ESP_LOGI(TAG, "Starting Advanced OTA example");
    vTaskDelay(20 / portTICK_PERIOD_MS);
    esp_err_t ota_finish_err = ESP_OK;
    if(strlen(G_UpdateInfo.OtaUrl) == 0)
    {
        // ESP_LOGI(TAG, "Get Url is null OTA Failed");
    }
    esp_http_client_config_t config = {
        .url = G_UpdateInfo.OtaUrl,//CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL, //G_UpdateInfo.OtaUrl, 
        .cert_pem = (char *)server_cert_pem_start,
        .timeout_ms = CONFIG_EXAMPLE_OTA_RECV_TIMEOUT, //设置网络超时时间为毫秒
        .keep_alive_enable = true,
        // .buffer_size = 1024,
    };

    esp_https_ota_config_t ota_config = {
        .http_config = &config,
        .http_client_init_cb = _http_client_init_cb, // Register a callback to be invoked after esp_http_client is initialized
    };

    esp_https_ota_handle_t https_ota_handle = NULL;
    esp_err_t err = esp_https_ota_begin(&ota_config, &https_ota_handle); //启动 HTTPS OTA 固件升级
    if (err != ESP_OK) {
        if (GET_BIT(G_Device_Data.RuningFlag, 0) == 1)
        {
            CLEAR_BIT(G_Device_Data.RuningFlag, 0); // 清除bit0
            SET_BIT(G_Device_Data.RuningFlag, 1);   // 正在升级 则设置为升级失败:2
        }
        ESP_LOGE(TAG, "ESP HTTPS OTA Begin failed");
        // vTaskDelete(NULL);
        save_flash_restart();
    }

    esp_app_desc_t app_desc;
    err = esp_https_ota_get_img_desc(https_ota_handle, &app_desc);//从图像标头读取应用说明,应用说明提供了映像的“固件版本”等信息
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "esp_https_ota_read_img_desc failed");
        goto ota_end;
    }
    err = validate_image_header(&app_desc); //根据固件头信息 确定是否可以升级
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "image header verification failed");
        goto ota_end;
    }

    while (1) {
        err = esp_https_ota_perform(https_ota_handle); //从HTTP流中读取图像数据并将其写入OTA分区
        if (err != ESP_ERR_HTTPS_OTA_IN_PROGRESS) {
            break;
        }
        // Esp_https_ota_perform在每次读取操作之后返回,这使用户能够通过调用esp_https_ota_get_image_len_read来监视OTA升级的状态,它给出了到目前为止读取的图像数据的长度。
        ESP_LOGD(TAG, "Image bytes read: %d", esp_https_ota_get_image_len_read(https_ota_handle));
        // mqtt获取到下载固件大小 计算出下载进度上报
    }

    if (esp_https_ota_is_complete_data_received(https_ota_handle) != true) { //完整获取bin数据
        // the OTA image was not completely received and user can customise the response to this situation.
        ESP_LOGE(TAG, "Complete data was not received.");
    } else {
        ota_finish_err = esp_https_ota_finish(https_ota_handle);    //引导分区切换到包含新固件映像的 OTA 分区。
        if ((err == ESP_OK) && (ota_finish_err == ESP_OK)) { //远程升级完成 开始重启
            ESP_LOGI(TAG, "ESP_HTTPS_OTA upgrade successful. Rebooting ...");

            if(GET_BIT(G_Device_Data.RuningFlag,0) == 1) 
            {
                
                SET_BIT(G_Device_Data.RuningFlag,1);//正在升级 则设置为升级完成:3
            }

            vTaskDelay(1000 / portTICK_PERIOD_MS);
            save_flash_restart();
        } else {
            if (ota_finish_err == ESP_ERR_OTA_VALIDATE_FAILED) {
                ESP_LOGE(TAG, "Image validation failed, image is corrupted");
            }
            ESP_LOGE(TAG, "ESP_HTTPS_OTA upgrade failed 0x%x", ota_finish_err);
            if (GET_BIT(G_Device_Data.RuningFlag, 0) == 1)
            {
                CLEAR_BIT(G_Device_Data.RuningFlag, 0); // 清除bit0
                SET_BIT(G_Device_Data.RuningFlag, 1);   // 正在升级 则设置为升级失败:2
            }
            // vTaskDelete(NULL);
            save_flash_restart();
        }
    }

ota_end:
    if (GET_BIT(G_Device_Data.RuningFlag, 0) == 1)
    {
        CLEAR_BIT(G_Device_Data.RuningFlag,0); //清除bit0
        SET_BIT(G_Device_Data.RuningFlag, 1); // 正在升级 则设置为升级失败:2
    }
    esp_https_ota_abort(https_ota_handle); // 清理 HTTPS OTA 固件升级并关闭 HTTPS 连接
    ESP_LOGE(TAG, "ESP_HTTPS_OTA upgrade failed");
    // vTaskDelete(NULL);
    save_flash_restart();
}

void Ota_TaskStart(void)
{
    printf("-- OTA example  start --\r\n");
    vTaskDelay(20 / portTICK_PERIOD_MS);
    /**
     * 我们将把成功的WiFi连接作为一个检查点来取消回滚过程,并将最新更新的固件映像标记为活动的。
     * 对于生产案例,请根据终端应用程序需求调优检查点行为。
     */
    const esp_partition_t *running = esp_ota_get_running_partition();
    esp_ota_img_states_t ota_state;
    if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) {
        if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) {
            if (esp_ota_mark_app_valid_cancel_rollback() == ESP_OK) {
                ESP_LOGI(TAG, "App is valid, rollback cancelled successfully");
            } else {
                ESP_LOGE(TAG, "Failed to cancel rollback");
            }
        }
    }
    
    /* *
     * 确保禁用任何WiFi省电模式,这样可以实现最佳吞吐量,从而为整体OTA操作计时。
     */
    esp_wifi_set_ps(WIFI_PS_NONE);

    xTaskCreate(&advanced_ota_example_task, "advanced_ota_task", 4096 , NULL, 5, NULL);
}

menuconfig 配置:

分区设置表(根据自己需要设计)

Name

Type

SubType

offset

Size

flag

nvs

,data

,nvs

,

0x4000

,

otadata

,data

,ota

,

0x2000

,

pth_init

,data

,phy

,

0x1000

,

my_data

,data

,nvs

,

12K

,

ota_1

,app

,ota_1

,

1500K

,

ota_2

,app

,ota_2

,

1500K

,

错误记录:

1、因为http服务被中断 无法连接,使用上面服务器2的方法进行固件下载。或换端口重新尝试。

2、固件不完整。

3、连接超时,http连接未完成下载。

4、http服务器验证出错。结构体添加参数并添加验证文件。

5、https证书添加

EMBED_TXTFILES ${project_dir}/server_certs/ca_cert.pem //cmakelists.txt中添加 证书路径

组件添加:

REQUIRES "bt"
#"nvs_flash" "driver" "esp_timer" "esp_event" "app_update" "esp_http_client" "esp_https_ota" "esp_wifi" "efuse"
#"bt" "esp_wifi" "freertos" "json" "esp_http_client"  "lwip" "esp_netif" "mbedtls" "esp_https_ota"

6、如何支持HTTPS连接,但不做证书校验?参数开始时候,请把 cert_set 设置为 OTA_CERT_SSL_VERIFY_OPTIONAL ,把

.cert_set = OTA_CERT_SSL_VERIFY_OPTIONAL,
.skip_ssl_cert_set = false,

填坑

ESP32做为客户端进行HTTPS请求时,如果不需要验证服务器证书也就是想跳过证书验证,

改constesp_http_client_config_t结构体中skip_cert_common_name_check成员是没有效果的。

他只会跳过检查证书的CN而不是CA,不会跳过整个证书验证。

所以如果想跳过证书则需要在menuconfig里面修改ESP-TLS选项,改为默认跳过服务器证书如下图

华为IOT升级 SSL握手失败

7、启动mqtt后开始OTA报错(建议关闭aws相关服务,但依然内存不足)

单纯删除线程并不能释放内存。需要单独调用mqtt断开连接的函数。

I (16116) advanced_https_ota_example: Connected to server
I (16116) esp_https_ota: Starting OTA...
I (16116) esp_https_ota: Writing to partition subtype 17 at offset 0x1a0000
I (16126) advanced_https_ota_example: Reading Image Description
E (16136) Dynamic Impl: alloc(16749 bytes) failed
E (16136) esp-tls-mbedtls: read error :-0x7F00:
E (16146) transport_base: esp_tls_conn_read error, errno=Success
E (16156) HTTP_CLIENT: transport_read: error - -1 | ESP_FAIL
E (16166) esp_https_ota: Connection closed, errno = 0
E (16176) esp_https_ota: Complete headers were not received
E (16186) advanced_https_ota_example: esp_https_ota_read_img_desc failed
I (16196) advanced_https_ota_example: OTA abort
E (16206) advanced_https_ota_example: ESP_HTTPS_OTA upgrade failed

8、连接WiFi后单独运行OTA功能报错如下:

E (22295) esp-tls-mbedtls: read error :-0x004C:
E (22305) transport_base: esp_tls_conn_read error, errno=Software caused connection abort
W (22325) HTTP_CLIENT: esp_transport_read returned:-76 and errno:113 
E (22335) HTTP_CLIENT: transport_read: error - -1 | ESP_FAIL
E (22465) transport_base: poll_read select error 113, errno = Software caused connection abort, fd = 54
E (22475) HTTP_CLIENT: transport_read: error - 57347 | ERROR
E (22475) esp_https_ota: data read -1, errno 0
E (22485) https_ota: Complete data was not received.
E (22495) https_ota: ESP_HTTPS_OTA upgrade failed

剩余内存不足

9、关闭mqtt连接并按照如下设置可以完成ota

10、修改为短URL后无权限下载固件

E (1074267) esp_https_ota: File not found(403)
E (1074267) esp_https_ota: Failed to establish HTTP connection
E (1074267) https_ota: ESP HTTPS OTA Begin failed //错误后需要处理

11、URL过长

设置1536后实际URL满足存储长度,但是依然报错,最后使用不加密的短URL

12、下载很长时间后报错内存剩余很少,减少OTA任务申请的堆栈并开始前少许延时等待内存分配

/** Reading information from the socket failed. */ #define MBEDTLS_ERR_NET_RECV_FAILED -0x004C

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/392995.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于缓存的理解

关于缓存的理解 为系统引入缓存的理由 通常情况&#xff0c;在我们面临系统的基础设施&#xff0c;例如数据库无法处理量级的请求时候&#xff0c;总是会下意识的使用缓存&#xff0c;这次我们以设计的角度思考&#xff0c;在为你的系统引入缓存之前&#xff0c;它是否真的需…

Windows下nvm的安装配置及使用

目录 一&#xff1a;nvm简介 二&#xff1a;nvm下载及安装 三&#xff1a;nvm配置镜像 四&#xff1a;nvm的基本使用 五&#xff1a;nvm的一些常用命令 一&#xff1a;nvm简介 nvm 全名叫做 nodejs version manage&#xff0c;是一个非常棒的nodejs的版本管理工具&#x…

Mp4屏录文件无法播放的修复方法

屏录文件算是比较特殊的一类文件&#xff0c;原因是其采集范围仅限于桌面&#xff0c;和我们现实的摄像机采集相比&#xff0c;桌面类的更单一&#xff0c;所以能实现较小的长度存放较多的帧。下面我来看一个屏录文件损坏后的修复案例&#xff0c;同时讲下CHS零壹视频修复程序Q…

GraphCut、最大流最小割定理

G&#xff08;V&#xff0c;E&#xff09;&#xff1b;V为点集&#xff0c;E为边集&#xff1b; 节点集V中的节点分为&#xff1a; &#xff08;1&#xff09;终端节点。不包含图像像素&#xff0c;用S和T表示。S为源点&#xff0c;T为汇点。图像分割中通常用S表示前景目标&a…

sql开窗函数

用的Oracle数据库进行测试一、数据准备DROP TABLE T_TEST; CREATE TABLE T_TEST (id NUMBER(10) VISIBLE NOT NULL ,姓名 VARCHAR2(50 BYTE) VISIBLE ,性别 VARCHAR2(50 BYTE) VISIBLE ,班级 VARCHAR2(50 BYTE) VISIBLE ,成绩 NUMBER(5,2) VISIBLE );INSERT INTO T_TEST VALUE…

【蓝桥杯专题】 递归 递推 (C++ | 洛谷 | acwing)

文章目录【蓝桥杯专题】 递归 &递推 &#xff08;C | 洛谷 | acwing&#xff09;复习P5534 【XR-3】等差数列P4994 终于结束的起点P1028 [NOIP2001 普及组] 数的计算波动数列[递归]母牛的故事蓝桥杯&#xff1a;耐摔指数菜狗现在才开始备战蓝桥杯QAQ 【蓝桥杯专题】 递归 &…

8 神经网络及Python实现

1 人工神经网络的历史 1.1 生物模型 1943年&#xff0c;心理学家W.S.McCulloch和数理逻辑学家W.Pitts基于神经元的生理特征&#xff0c;建立了单个神经元的数学模型&#xff08;MP模型&#xff09;。 1.2 数学模型 ykφ(∑i1mωkixibk)φ(WkTXb)y_{k}\varphi\left(\sum_{i1…

基于龙芯+国产FPGA 的VPX以太网交换板设计(三)

调试与测试是本系统设计实现的重要环节。单板调试主要包括各单元电路和接口 的调试&#xff0c;主要通过查看信号波形和运行软件对每个功能进行测试。本章将设计一系列 的调试和测试方案来验证电路设计的正确性。 6.1 电路板静态检查 经过原理图设计、印制板设计、制造、印制板…

HTML5智慧渔业WebGL可视化云平台

中国作为全球第一大水产养殖大国&#xff0c;未来中国水产养殖的出路在哪里?智慧渔业到底能起到多大的作用?在未来它能为我国水产养殖做出什么深刻的变化吗?今天给大家分享一个基于 数维图 的 Sovit3D可视化编辑器 构建的水产养殖3D可视化场景案例——智慧渔业可视化管理系统…

Hadoop框架:MapReduce基本原理和入门案例

Hadoop MapReduce是一种用于处理大数据的编程模型。它将数据集切分成多个小任务&#xff0c;每一个小任务都可以通过独立的计算来完成&#xff0c;最终的结果可以通过合并或更新数据来进行聚合。Hadoop MapReduce极大地简化了处理大数据的过程&#xff0c;因为它可以同时进行多…

锁屏面试题百日百刷-Hive篇(十一)

锁屏面试题百日百刷&#xff0c;每个工作日坚持更新面试题。锁屏面试题app、小程序现已上线&#xff0c;官网地址&#xff1a;https://www.demosoftware.cn。已收录了每日更新的面试题的所有内容&#xff0c;还包含特色的解锁屏幕复习面试题、每日编程题目邮件推送等功能。让你…

大坝安全监测和水雨情测报系统-智慧水利

政策背景2021年3月23日《国务院办公厅关于切实加强水库除险加固和运行管护工作的通知》&#xff08;国办发〔2021〕8号&#xff09;和2021年9月22日国务院常务会议均明确要求&#xff0c;加快推进水库除险加固&#xff0c;加强雨水情和安全监测预警设施建设&#xff0c;健全常态…

23种Java设计模式

目录 &#x1f9e1; Java 设计模式 六大原则 创建型模式 工厂模式 (Factory Pattern) 抽象工厂模式 (Abstract Factory Pattern) 单例模式 (Singleton Pattern) 建造者模式 (BuilderPattern) 原型模式 (Prototype Pattern) 结构型模式 适配器模式 (Adapter Pattern) …

vmware 虚拟机创建 LVM

LVM 原理 LVM (Logical volume Manager): 虚拟设备驱动&#xff0c;是在内核中块设备和物理设备之间添加的一个新的抽象层次, LVM 可以弹性的调整 文件系统的容量 LVM的实现原理&#xff1a;LVM 将几个实体的 partitions/disk 通过软件组合成一块独立的大磁盘VG&#xff0c;之…

中职网络空间安全B-windows渗透

Windows渗透 目录 Windows渗透 要点 cev2017-7269 ms14-064 pr.exe 提权 3389.bat 打开连接 破解hash 总体是众多小点的结合 1.通过本地pc中的渗透平台kali对服务器场景进行服务及版本扫描渗透测试&#xff0c;并将该操作显示结果中445端口对应的服务版本信息字符串作为fla…

Django实践-03模型-02基于admin管理表

文章目录Django实践-03模型利用Django后台管理模型1. 将admin应用所需的表迁移到数据库中。2. 创建访问admin应用的超级用户账号&#xff0c;3. 运行项目4.注册模型类5.对模型进行CRUD操作。6.实现学科页和老师页效果1. 修改polls/views.py文件。2.修改templates/polls/subject…

THUPC-2023 游记

清华校赛&#xff0c;战火重燃 原文链接 宣传图 上周四同学在洛谷无意间看到了宣传图&#xff0c;当时很有感触。不知觉间&#xff0c;又是一年春&#xff0c;又是一场触动心弦的 THUPC 了。 周五的团建过于有趣&#xff0c;致使我完全将 THUPC 抛之脑后了。 周日上午被省选…

原型链(回顾)

概念prototype__proto__原型链查找机制万物皆对象判断私有/共有属性方法Object.prototype.prototype nullObject.create(proto, [propertiesObject])给类的原型上扩展属性方法的4种方法Fn.prototype.xxx xxxObject.prototype.xxx xxxf1.proto.xxx xxx原型重定向 概念 原型…

虚拟相机 Cinemachine Virtual Camera

一.简介 本质上,虚拟相机应该是相机行为的配置文件,虚拟相机之间的切换实际上就是在进行相机行为之间的切换; 虚拟相机并不会创建任何摄像机,他只会创建虚拟节点,实际上操作的是Cinemachine Brain 虚拟相机属性设置完毕后,应尽量避免在游戏中对齐进行修改, 如有需要可以多创建…

RocketMQ-03

1. 高级功能 1.1 消息存储 分布式队列因为有高可靠性的要求&#xff0c;所以数据要进行持久化存储。 消息生成者发送消息MQ收到消息&#xff0c;将消息进行持久化&#xff0c;在存储中新增一条记录返回ACK给生产者MQ push 消息给对应的消费者&#xff0c;然后等待消费者返回A…