背景:对于资源受限的esp32,官方给的factory和双ota方案是不现实的。目前固件是1.3m,总flash大小是4m。所以需要调整分区表。

环境:目前手上这块esp32是移植了openharmony 5.1.0的系统。是有很多修改点的。

方案:目前采用的升级方案是wifi+http的形式。

调整sdkconfig.h和sdkconfig.gni文件,这是必须要同时调整的,不然用的分区表还是旧的。

修改后分区表如下:

# Name,   Type, SubType, Offset,   Size,     Flags
nvs,      data, nvs,     0x9000,   0x6000,
phy_init, data, phy,     0xf000,   0x1000,
ota_0,  app,  ota_0, 0x10000,  0x180000,
ota_1,    app,  ota_1,   0x190000, 0x180000,
otadata,    data,  ota,   0x310000, 0x2000,
storage,  data, spiffs,  0x312000, 0xd0000,

sdkconfig.h 修改如下:

// #define CONFIG_PARTITION_TABLE_SINGLE_APP 1
#define CONFIG_PARTITION_TABLE_TWO_OTA 1
#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv"
// #define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv"
#define CONFIG_PARTITION_TABLE_FILENAME "partitions_ota.csv"

sdkconfig.gni 修改:

#
# Partition Table
#
# CONFIG_PARTITION_TABLE_SINGLE_APP=true
# CONFIG_PARTITION_TABLE_TWO_OTA is not set
CONFIG_PARTITION_TABLE_TWO_OTA=true
# CONFIG_PARTITION_TABLE_CUSTOM is not set
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions_ota.csv"
CONFIG_PARTITION_TABLE_OFFSET="0x8000"
CONFIG_PARTITION_TABLE_MD5=true
# end of Partition Table

重新编译烧录,烧录前要擦除所有flash,防止之前的分区信息残留。

升级方案程序:接收数据处理部分程序不公开。

static esp_err_t ota_upgrade_handler(httpd_req_t *req)
{
    // 检查 Content-Length 是否有效
    if (req->content_len <= 0) {
        httpd_resp_send_err(req, HTTPD_411_LENGTH_REQUIRED, "Content-Length required");
        return ESP_FAIL;
    }

    const esp_partition_t *running = esp_ota_get_running_partition();
    ESP_LOGI("OTA", "Running partition: %s, addr=0x%08x, size=0x%x",
                running->label, running->address, running->size);

    // 获取下一个可用的 OTA 分区
    const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL);
    if (update_partition == NULL) {
        httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "No OTA partition found");
        return ESP_FAIL;
    }

    ESP_LOGI("OTA", "Update partition : %s, addr=0x%08x, size=0x%x",
                update_partition->label, update_partition->address, update_partition->size);

    esp_ota_handle_t ota_handle = 0;
    esp_err_t err = esp_ota_begin(update_partition, OTA_WITH_SEQUENTIAL_WRITES, &ota_handle);
    if (err != ESP_OK) {
        ESP_LOGI("OTA", "esp_ota_begin FAILED: %s", esp_err_to_name(err));
        httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "OTA begin failed");
        return ESP_FAIL;
    }

// .....  接收部分不公开

    // 完成 OTA 写入
    err = esp_ota_end(ota_handle);
    if (err != ESP_OK) {
        httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "OTA end failed");
        return ESP_FAIL;
    }


    // 设置启动分区为新固件
    err = esp_ota_set_boot_partition(update_partition);
    if (err != ESP_OK) {
        httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Set boot partition failed");
        return ESP_FAIL;
    }

    ESP_LOGI("OTA", "OTA update complete, restarting...");

    // 返回成功响应
    httpd_resp_set_type(req, "application/json");
    httpd_resp_sendstr(req, "{\"result\":\"upgrading\"}");

    // 延迟 2 秒后重启,确保响应已发送
    osDelay(200);
    g_restart = true;

    // 不会执行到这里
    return ESP_OK;
}

最终串口运行输出是:

第一次升级输出:

I (272) OTA: Running partition: ota_0, addr=0x00010000, size=0x180000
I (281) OTA: Update partition : ota_1, addr=0x00190000, size=0x180000

第二次升级输出:

I (272) OTA: Running partition: ota_1, addr=0x00190000, size=0x180000
I (281) OTA: Update partition : ota_0, addr=0x00010000, size=0x180000

【注意】分区表信息中type不要搞错,不然升级检索可用ota时会找不到可用的ota。

Logo

更多推荐