ESP32S系列芯片通过EC20完成OTA统一流程

    uint32_t end_size = 0;            // 最后一包的大小
    uint16_t page_number = 0;         // 总包数
    uint16_t now_number = 0;          // 当前写入页数
    uint32_t bin_addr = 0;            // 文件地址指针偏移量
    uint16_t read_size = ENCRYT_SIZE; // 每次读3088 最后一页需要计算
    uint8_t bin_handle_s[100];
    uint16_t bin_handle_d = 0;
    esp_err_t err;
    uint16_t i = 0;
    uint8_t percent = 0;

    static char bar[102];
    memset(bar, 0, sizeof(bar));
    const char *lable = "|/-\\";

    updating_flag = 1;

    ESP_LOGI(TAG, "Starting OTA example...\n");
    const esp_partition_t *configured = esp_ota_get_boot_partition();
    const esp_partition_t *running = esp_ota_get_running_partition();
    if (configured != running)
    {
        ESP_LOGI(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x\n(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)\n", configured->address, running->address);
    }
    ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)\n", running->type, running->subtype, running->address);
    update_partition = esp_ota_get_next_update_partition(NULL);
    assert(update_partition != NULL);
    ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x\n", update_partition->subtype, update_partition->address);
    err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "esp_ota_begin failed, error=%d\n", err);
        vTaskDelay(5000);
        esp_restart();
    }
    ESP_LOGI(TAG, "esp_ota_begin succeeded\n");

    end_size = LTE_EC20.BIN_len % max_read_size; // 最后一包大小
    if (end_size == 0)                           // 恰巧是完整包
    {
        page_number = LTE_EC20.BIN_len / max_read_size;
    }
    else
        page_number = LTE_EC20.BIN_len / max_read_size + 1;
    ESP_LOGI(TAG, "总长:%d 总包:%d 末包:%d\r\n", LTE_EC20.BIN_len, page_number, end_size);


    while (1)
    {
        if (percent % 10 == 0 && percent != 0)
        {
            User_Reply_Progress(percent);//上报OTA进度百分比
        }
        if (stop_update_flag == 1)//收到停止升级指令
        {
            stop_update_flag = 0;

            Log_Write(TAG, "OTA aborted by cloud mqtt server!\r");
            esp_ota_abort(update_handle); // 暂停OTA
            ESP_LOGE(TAG, "Stop Update!! Restart!\n");
           
            vTaskDelay(5000);
            esp_restart();
        }
        // 打开UFS 文件系统
        if (bin_addr == 0) // 首次读取
        {
            // 打开文件
            ucExecRes = LTE_AT_SR("AT+QFOPEN=\"ota.bin\",0\r\n", "+QFOPEN: ", "ERROR", 5000 / portTICK_PERIOD_MS); // 返回值为文件句柄 当操作文件比较多时有可能是变量
            if (ucExecRes == ExecFail)
            {
                ESP_LOGE(TAG, "Open file system failed ,stop ota");
                ucExecRes = LTE_AT_SR("AT+QFCLOSE=0", "OK", "ERROR", 1000 / portTICK_PERIOD_MS); //
                goto err_res;
            }
            Find_string((char *)Get_AT_Rev_Buffer(), "+QFOPEN: ", "\n", (char *)bin_handle_s); // 获取文件句柄
            bin_handle_d = atoi((char *)bin_handle_s);
            ESP_LOGI(TAG, "Bin handle:%d\r\n", bin_handle_d);
        }
        // 设置文件指针位置
        memset(AT_send, 0x00, sizeof(AT_send));
        snprintf((char *)AT_send, sizeof(AT_send), "AT+QFSEEK=%d,%d,0\r\n", bin_handle_d, bin_addr);
        ucExecRes = LTE_AT_SR((char *)AT_send, "OK", "ERROR", 5000 / portTICK_PERIOD_MS); //

        if (ucExecRes == Normal)
        {
            (void)0;
        }
        if (bin_addr == 0) // 第一次seek需要点时间才能到最开头的位置
            vTaskDelay(1000);
        else
            vTaskDelay(20);
        // 读文件
        memset(AT_send, 0x00, sizeof(AT_send));
        snprintf((char *)AT_send, sizeof(AT_send), "AT+QFREAD=%d,%d\r\n", bin_handle_d, read_size);
        ucExecRes = LTE_AT_SR((char *)AT_send, "OK", "ERROR", 2000 / portTICK_PERIOD_MS); //
        if (ucExecRes == Normal)
        {
            // ESP_LOGE(TAG, "CNT:%d  NUM:%d LAST:%d LEN:%d ", now_number,  page_number, end_size,LTE_EC20.BIN_len);
            percent = ((now_number * 1.0) / (page_number * 1.0)) * 100.0;
            printf("\n\033[1;32m[%-100s]\033[0m [%d%%][%c]\r\n", bar, percent, lable[percent % 4]); // 显示进度条
            fflush(stdout);                                                                         // 刷新缓冲区
            bar[percent] = '#';

            memset(ota_write_data, 0, max_read_size);
            // 根据读取的位数来判断从哪个字符开始复制
            if (read_size >= 1000 && read_size < 10000) // CONNECT 999
                memcpy(ota_write_data, Get_AT_Rev_Buffer() + 16, read_size);
            else if (read_size < 1000 && read_size >= 100) // CONNECT 999
                memcpy(ota_write_data, Get_AT_Rev_Buffer() + 15, read_size);
            else if (read_size < 100 && read_size >= 10) // CONNECT 99
                memcpy(ota_write_data, Get_AT_Rev_Buffer() + 14, read_size);
            else if (read_size < 10 && read_size >= 1) // CONNECT 9
                memcpy(ota_write_data, Get_AT_Rev_Buffer() + 13, read_size);

            err = esp_ota_write(update_handle, (const void *)ota_write_data, UNENCRYT_SIZE); // 写入数据
            if (err != ESP_OK)
            {
                ESP_LOGE(TAG, "OTA:esp_ota_write failed! err=0x%x\n", err);
                printf("Firmware write failed! restart");
                goto err_res;
            }
            now_number += 1;
            if ((now_number == page_number - 1) && (end_size != 0)) // 存在最后不整包,并且到达了最后一包
            {
                bin_addr += max_read_size; // 把读过的地址加上
                read_size = end_size;
            }
            else if (now_number == page_number) // 下载完成
            {
                ESP_LOGI(TAG, "read packet over...\r");
                snprintf((char *)AT_send, sizeof(AT_send), "AT+QFCLOSE=%d\r", bin_handle_d);
                ucExecRes = LTE_AT_SR((char *)AT_send, "OK", "ERROR", 1000 / portTICK_PERIOD_MS); //
                printf("Firmware reception completed....\nVerifying...coming soon to restart\n");
                if (esp_ota_end(update_handle) != ESP_OK || esp_ota_set_boot_partition(update_partition) != ESP_OK)
                {
                    ESP_LOGE(TAG, "esp_ota_end failed!");
                    printf("OTA end failed and set boot partition failed!\n");
                }
                else
                {
                    ESP_LOGI(TAG, "esp_ota_end succeed!");
                    printf("OTA end succeed and set boot partition succeed!\n");
                }
                ESP_LOGI(TAG, "Prepare to restart system!");
                printf("OTA finished.Prepare to restart system!\n");
            err_res:
                vTaskDelay(3000);
                updating_flag = 0;
                esp_restart();
                break;
            }
            else
            {
                bin_addr += max_read_size;
                read_size = max_read_size;
            }
        }
    }

其实简化下来就是获取数据、写入数据、完成OTA重启三个步骤

简化代码为:


    ESP_LOGI(TAG, "Starting OTA example...\n");
    const esp_partition_t *configured = esp_ota_get_boot_partition();
    const esp_partition_t *running = esp_ota_get_running_partition();
    if (configured != running)
    {
        ESP_LOGI(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x\n(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)\n", configured->address, running->address);
    }
    ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)\n", running->type, running->subtype, running->address);
    update_partition = esp_ota_get_next_update_partition(NULL);
    assert(update_partition != NULL);
    ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x\n", update_partition->subtype, update_partition->address);
    err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
    if (err != ESP_OK)
    {
        esp_restart();
    }

    err = esp_ota_write(update_handle, (const void *)ota_write_data, UNENCRYT_SIZE); // 写入数据
            if (err != ESP_OK)
            {
                ESP_LOGE(TAG, "OTA:esp_ota_write failed! err=0x%x\n", err);
                goto err_res;
            }
           
                if (esp_ota_end(update_handle) != ESP_OK || esp_ota_set_boot_partition(update_partition) != ESP_OK)
                {
                    ESP_LOGE(TAG, "esp_ota_end failed!");
                }
                else
                {
                    ESP_LOGI(TAG, "esp_ota_end succeed!");
                }
                ESP_LOGI(TAG, "Prepare to restart system!");

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ESP32-S3支持通过OTA(Over-The-Air)方式进行固件升级,以下是ESP-IDF中实现OTA的基本步骤: 1. 配置OTA服务器和升级包生成工具,可以使用ESP-IDF中提供的ota服务和espsecure.py工具。 2. 在应用程序中添加OTA服务的客户端代码,通过WiFi接口连接OTA服务器并下载升级包。 3. 将升级包写入ESP32-S3的闪存中,可以使用ESP-IDF中提供的OTA API。 以下是基本的OTA升级流程: 1. 配置OTA服务器和升级包生成工具 在ESP-IDF中,可以使用ota服务和espsecure.py工具来搭建OTA服务器和生成升级包。具体步骤请参考ESP-IDF官方文档。 2. 添加OTA客户端代码 在应用程序中,可以使用ESP-IDF提供的OTA客户端代码来连接OTA服务器并下载升级包。以下是基本的OTA客户端代码: ```c #include "esp_http_client.h" #include "esp_https_ota.h" esp_err_t ota_task(void) { esp_http_client_config_t config = { .url = "http://ota_server_address/image.bin", .cert_pem = (char *)server_cert_pem_start, }; esp_err_t ret = esp_https_ota(&config); if (ret == ESP_OK) { esp_restart(); } return ret; } ``` 在以上代码中,url参数指定OTA服务器的地址和升级包的文件名。server_cert_pem_start是一个指向OTA服务器证书的指针,可以使用ESP-IDF提供的certs.c文件来存储证书。 3. 写入升级包 下载完成升级包后,可以使用OTA API将升级包写入ESP32-S3的闪存中。以下是基本的OTA API代码: ```c #include "esp_ota_ops.h" esp_err_t update_firmware(void) { esp_err_t ret; const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL); if (update_partition == NULL) { return ESP_FAIL; } ret = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, NULL); if (ret != ESP_OK) { return ret; } // Write OTA data to flash // ... ret = esp_ota_end(update_partition); if (ret != ESP_OK) { return ret; } ret = esp_ota_set_boot_partition(update_partition); if (ret != ESP_OK) { return ret; } esp_restart(); return ESP_OK; } ``` 在以上代码中,esp_ota_get_next_update_partition函数用于获取下一个可用的OTA分区。esp_ota_begin函数用于开始OTA更新过程,esp_ota_end函数用于结束OTA更新过程。在OTA更新结束后,可以使用esp_ota_set_boot_partition函数将新的固件分区设置为启动分区,并重启设备以完成更新。 需要注意的是,OTA更新的过程中需要保证设备的可靠性和稳定性,尤其是在写入升级包的过程中,需要确保闪存写操作的正确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值