一 获取升级分区

//获取可升级分区指针
p_ota->update_partition = ( esp_partition_t* )esp_ota_get_next_update_partition(NULL);

二 升级前准备

esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp_ota_handle_t *out_handle)
{
    ota_ops_entry_t *new_entry;
    esp_err_t ret = ESP_OK;

    if ((partition == NULL) || (out_handle == NULL)) {
        return ESP_ERR_INVALID_ARG;
    }
    //验证是否为有效分区
    partition = esp_partition_verify(partition);
    if (partition == NULL) {
        return ESP_ERR_NOT_FOUND;
    }
    //判断是否是ota分区
    if (!is_ota_partition(partition)) {
        return ESP_ERR_INVALID_ARG;
    }
    //判断升级分区是否为运行分区
    const esp_partition_t* running_partition = esp_ota_get_running_partition();
    if (partition == running_partition) {
        return ESP_ERR_OTA_PARTITION_CONFLICT;
    }
    //app回滚使能
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
    esp_ota_img_states_t ota_state_running_part;
    if (esp_ota_get_state_partition(running_partition, &ota_state_running_part) == ESP_OK) {
        if (ota_state_running_part == ESP_OTA_IMG_PENDING_VERIFY) {
            ESP_LOGE(TAG, "Running app has not confirmed state (ESP_OTA_IMG_PENDING_VERIFY)");
            return ESP_ERR_OTA_ROLLBACK_INVALID_STATE;
        }
    }
#endif
    //初始化分区操作结构体,并插入到链表中
    new_entry = esp_ota_init_entry(partition);
    if (new_entry == NULL) {
        return ESP_ERR_NO_MEM;
    }
    //判断是否需要擦除
    new_entry->need_erase = (image_size == OTA_WITH_SEQUENTIAL_WRITES);
    *out_handle = new_entry->handle;
    if (image_size != OTA_WITH_SEQUENTIAL_WRITES) {
        // If input image size is 0 or OTA_SIZE_UNKNOWN, erase entire partition
        if ((image_size == 0) || (image_size == OTA_SIZE_UNKNOWN)) {
        	//擦除分区
            ret = esp_partition_erase_range(partition, 0, partition->size);
        } else {
        	//直接对齐
            const int aligned_erase_size = (image_size + partition->erase_size - 1) & ~(partition->erase_size - 1);
            ret = esp_partition_erase_range(partition, 0, aligned_erase_size);
        }
        if (ret != ESP_OK) {
            return ret;
        }
    }

    return ESP_OK;
}

三 flash写操作

/*
handle :升级句柄
data   :升级数据
size   :数据大小
*/
esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)

四 升级结束处理

esp_ota_end(esp_ota_handle_t handle)
esp_image_verify(image_load)验证bin文件有效性

	//检查bin文件头信息是否正确
    CHECK_ERR(process_image_header(data, part->offset, (verify_sha) ? p_sha_handle : NULL, do_verify, silent));
    //检查数据段是否正常
    CHECK_ERR(process_segments(data, silent, do_load, sha_handle, checksum));
    bool skip_check_checksum = !do_verify || esp_cpu_dbgr_is_attached();
    //检查校验和是否正确
    CHECK_ERR(process_checksum(sha_handle, checksum_word, data, silent, skip_check_checksum));
    //检查hash校验是否正确
    CHECK_ERR(process_appended_hash_and_sig(data, part->offset, part->size, do_verify, silent));

具体对照信息可参考:链接: link

五 设置启动分区

//设置升级分区为启动分区
esp_ota_set_boot_partition(p_ota->update_partition);

六 复位ESP32

esp_restart(); 
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐