//****************************************************************************************************************************//
//****************************************************************************************************************************//
//*****************************************OTA部分****************************************************************************//
//****************************************************************************************************************************//
//****************************************************************************************************************************//
//****************************************************************************************************************************//
/*******************************************************************************
* Function Name : http_cleanup
* Description : 关闭http服务
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static void http_cleanup(esp_http_client_handle_t client)
{
esp_http_client_close(client);
esp_http_client_cleanup(client);
}
// static void __attribute__((noreturn)) task_fatal_error(void)
// {
// ESP_LOGE(TAG, "Exiting task due to fatal error...");
// (void)vTaskDelete(NULL);
// while (1) {
// ;
// }
// }
static void print_sha256 (const uint8_t *image_hash, const char *label)
{
char hash_print[HASH_LEN * 2 + 1];
hash_print[HASH_LEN * 2] = 0;
for (int i = 0; i < HASH_LEN; ++i) {
sprintf(&hash_print[i * 2], "%02x", image_hash[i]);
}
ESP_LOGI(TAG, "%s: %s", label, hash_print);
}
/*******************************************************************************
* Function Name : ota_init
* Description : ota_init 初始化
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void ota_init(void)
{
uint8_t sha_256[HASH_LEN] = { 0 };
esp_partition_t partition;
//分区表sha256
partition.address = ESP_PARTITION_TABLE_OFFSET;//CONFIG_PARTITION_TABLE_OFFSET:分区表偏移0x8000
partition.size = ESP_PARTITION_TABLE_MAX_LEN;//0xC00=3K
partition.type = ESP_PARTITION_TYPE_DATA;
esp_partition_get_sha256(&partition, sha_256);
print_sha256(sha_256, "SHA-256 for the partition table: ");
//boot sha256
partition.address = ESP_BOOTLOADER_OFFSET;//CONFIG_BOOTLOADER_OFFSET_IN_FLASH:boot偏移0x1000
// partition.size = ESP_PARTITION_TABLE_OFFSET;//此处官方代码有问题,修改成如下
partition.size = ESP_PARTITION_TABLE_OFFSET-ESP_BOOTLOADER_OFFSET;//0x8000-0x1000=0x7000=28K
partition.type = ESP_PARTITION_TYPE_APP;
esp_partition_get_sha256(&partition, sha_256);
print_sha256(sha_256, "SHA-256 for bootloader: ");
//应用程序sha256
esp_partition_get_sha256(esp_ota_get_running_partition(), sha_256);//应用程序
print_sha256(sha_256, "SHA-256 for current firmware: ");
ESP_LOGI(TAG, "----------------------------------------------------------------------");
//获取当前运行APP分区信息
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) {
//检查能否运行
bool diagnostic_is_ok = 1;
if (diagnostic_is_ok) {
ESP_LOGI(TAG, "Diagnostics completed successfully! Continuing execution ...");
//当前APP运行正常,不用回滚
esp_ota_mark_app_valid_cancel_rollback();
} else {
ESP_LOGE(TAG, "Diagnostics failed! Start rollback to the previous version ...");
//回滚到以前可用的应用程序,重启
esp_ota_mark_app_invalid_rollback_and_reboot();
}
}else{
ESP_LOGE(TAG, "ota_state != ESP_OTA_IMG_PENDING_VERIFY : = ota_state = %d",ota_state);
}
}else{
ESP_LOGE(TAG, "error esp_ota_get_state_partition");
}
//读取当前运行app的版本号
esp_app_desc_t running_app_infor;
if (esp_ota_get_partition_description(running, &running_app_infor) == ESP_OK) {
ESP_LOGI(TAG, "Running firmware version: %s", running_app_infor.version);
}
}
/*******************************************************************************
* Function Name : ota_example_task
* Description : 固件升级
* Input : file_buf:url地址
* Output : None
* Return : None
*******************************************************************************/
void ota_example_task(char * file_buf)//void *pvParameter
{
esp_err_t err;
/* update handle : set by esp_ota_begin(), must be freed via esp_ota_end() */
esp_ota_handle_t update_handle = 0 ;
const esp_partition_t *update_partition = NULL;
ESP_LOGI(TAG, "Starting OTA example");
const esp_partition_t *configured = esp_ota_get_boot_partition();
const esp_partition_t *running = esp_ota_get_running_partition();
if (configured != running) {
ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08"PRIx32", but running from offset 0x%08"PRIx32,
configured->address, running->address);
ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)");
}
ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08"PRIx32")",
running->type, running->subtype, running->address);
esp_http_client_config_t config = {
.url = file_buf,//"http://192.168.2.53:8070/1.bin"
// .cert_pem = (char *)server_cert_pem_start,
// .crt_bundle_attach = esp_crt_bundle_attach,
.timeout_ms = 5000,
.keep_alive_enable = true,
};
#ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL_FROM_STDIN
char url_buf[OTA_URL_SIZE];
if (strcmp(config.url, "FROM_STDIN") == 0) {
example_configure_stdin_stdout();
fgets(url_buf, OTA_URL_SIZE, stdin);
int len = strlen(url_buf);
url_buf[len - 1] = '\0';
config.url = url_buf;
} else {
ESP_LOGE(TAG, "Configuration mismatch: wrong firmware upgrade image url");
abort();
}
#endif
#ifdef CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK
config.skip_cert_common_name_check = true;
#endif
esp_http_client_handle_t client = esp_http_client_init(&config);
if (client == NULL) {
ESP_LOGE(TAG, "Failed to initialise HTTP connection");
// task_fatal_error();
uart_write_bytes(UART_NUM_1, (const char *) "B8.2", strlen("B8.2"));//http连接失败
return;
}
err = esp_http_client_open(client, 0);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
esp_http_client_cleanup(client);
// task_fatal_error();
uart_write_bytes(UART_NUM_1, (const char *) "B8.2", strlen("B8.2"));//http连接失败
return;
}
//获取http头
esp_http_client_fetch_headers(client);
//获取下一个可用的OTA分区,用于存储OTA数据
update_partition = esp_ota_get_next_update_partition(NULL);
assert(update_partition != NULL);
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%"PRIx32,
update_partition->subtype, update_partition->address);
int binary_file_length = 0;
/*deal with all receive packet*/
bool image_header_was_checked = false;
while (1) {
//读取http数据
int data_read = esp_http_client_read(client, ota_write_data, BUFFSIZE);
if (data_read < 0) {//异常
ESP_LOGE(TAG, "Error: SSL data read error");
http_cleanup(client);
uart_write_bytes(UART_NUM_1, (const char *) "B8.2", strlen("B8.2"));//升级失败
return;
// task_fatal_error();
} else if (data_read > 0) {//有数据
if (image_header_was_checked == false) {//第一包数据
esp_app_desc_t new_app_info;
if (data_read > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t)) {
//比较三个版本号,
//读取OTA的版本号
memcpy(&new_app_info, &ota_write_data[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t));
ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version);
//读取当前运行app的版本号
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);
}
//获取无效分区(下一个可用的分区)app的版本号
const esp_partition_t* last_invalid_app = esp_ota_get_last_invalid_partition();
esp_app_desc_t invalid_app_info;
if (esp_ota_get_partition_description(last_invalid_app, &invalid_app_info) == ESP_OK) {
ESP_LOGI(TAG, "Last invalid firmware version: %s", invalid_app_info.version);
}
// check current version with last invalid partition
if (last_invalid_app != NULL) {
//OTA版本和无效分区版本相同退出,不下载
if (memcmp(invalid_app_info.version, new_app_info.version, sizeof(new_app_info.version)) == 0) {
ESP_LOGW(TAG, "New version is the same as invalid version.");
ESP_LOGW(TAG, "Previously, there was an attempt to launch the firmware with %s version, but it failed.", invalid_app_info.version);
ESP_LOGW(TAG, "The firmware has been rolled back to the previous version.");
http_cleanup(client);
//infinite_loop();
return ;
}
}
#ifndef CONFIG_EXAMPLE_SKIP_VERSION_CHECK
//OTA版本和当前版本相同退出,不下载,可以跳过检查版本
// 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.");
// http_cleanup(client);
// // infinite_loop();
// uart_write_bytes(UART_NUM_1, (const char *) "B8.1", strlen("B8.1"));//版本一致,不需要升级
// return ;
// }
#endif
//头结束,准备接受OTA数据包
image_header_was_checked = true;
//开始OTA保存(先擦除),放在可用的OTA分区
err = esp_ota_begin(update_partition, OTA_WITH_SEQUENTIAL_WRITES, &update_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err));
http_cleanup(client);
esp_ota_abort(update_handle);
uart_write_bytes(UART_NUM_1, (const char *) "B8.2", strlen("B8.2"));//升级失败
return;
// task_fatal_error();
}
ESP_LOGI(TAG, "esp_ota_begin succeeded");
} else {//头包异常
ESP_LOGE(TAG, "received package is not fit len");
http_cleanup(client);
esp_ota_abort(update_handle);
uart_write_bytes(UART_NUM_1, (const char *) "B8.2", strlen("B8.2"));//升级失败
return;
// task_fatal_error();
}
}
//保存OTA数据包
err = esp_ota_write( update_handle, (const void *)ota_write_data, data_read);
if (err != ESP_OK) {
http_cleanup(client);
esp_ota_abort(update_handle);
uart_write_bytes(UART_NUM_1, (const char *) "B8.2", strlen("B8.2"));//升级失败
// task_fatal_error();
return;
}
//总的OTA数据长度
binary_file_length += data_read;
ESP_LOGI(TAG, "Written image length %d", binary_file_length);
} else if (data_read == 0) {//OTA结束,http连接断开
/*
* As esp_http_client_read never returns negative error code, we rely on
* `errno` to check for underlying transport connectivity closure if any
*/
if (errno == ECONNRESET || errno == ENOTCONN) {
ESP_LOGE(TAG, "Connection closed, errno = %d", errno);
break;
}
if (esp_http_client_is_complete_data_received(client) == true) {
ESP_LOGI(TAG, "Connection closed");
break;
}
}
}
ESP_LOGI(TAG, "Total Write binary data length: %d", binary_file_length);
//检查是否读取了http响应中的整个数据而没有任何错误
if (esp_http_client_is_complete_data_received(client) != true) {
ESP_LOGE(TAG, "Error in receiving complete file");
http_cleanup(client);
esp_ota_abort(update_handle);
// task_fatal_error();
uart_write_bytes(UART_NUM_1, (const char *) "B8.2", strlen("B8.2"));//升级失败
return;
}
//OTA保存结束,与esp_ota_begin对应,esp_ota_write居中保存
err = esp_ota_end(update_handle);
if (err != ESP_OK) {
if (err == ESP_ERR_OTA_VALIDATE_FAILED) {
ESP_LOGE(TAG, "Image validation failed, image is corrupted");
}
ESP_LOGE(TAG, "esp_ota_end failed (%s)!", esp_err_to_name(err));
http_cleanup(client);
// task_fatal_error();
uart_write_bytes(UART_NUM_1, (const char *) "B8.2", strlen("B8.2"));//升级失败
return;
}
//设置启动新的OTA分区APP
err = esp_ota_set_boot_partition(update_partition);
if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err));
http_cleanup(client);
// task_fatal_error();
uart_write_bytes(UART_NUM_1, (const char *) "B8.2", strlen("B8.2"));//升级失败
return;
}
uart_write_bytes(UART_NUM_1, (const char *) "B8.0", strlen("B8.0"));//升级成功返回
//重启
ESP_LOGI(TAG, "Prepare to restart system!");
esp_restart();
return ;
}
/*******************************************************************************
* Function Name : ota_version_read
* Description : 固件版本读取
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void ota_version_read(void)
{
const esp_partition_t *running = esp_ota_get_running_partition();
//读取当前运行app的版本号
esp_app_desc_t running_app_infor;
if (esp_ota_get_partition_description(running, &running_app_infor) == ESP_OK) {
ESP_LOGI(TAG, "Running firmware version: %s", running_app_infor.version);
}
char device_version_read[50];
sprintf(device_version_read,"B9=%s",running_app_infor.version);
uart_write_bytes(UART_NUM_1, (const char *) device_version_read, strlen(device_version_read));
}
ESP32 开发笔记——OTA
最新推荐文章于 2024-07-16 14:05:36 发布