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!");