概览
OTA 升级机制可以让设备在固件正常运行时根据接收数据(如通过 Wi-Fi 或蓝牙)进行自我更新。
步骤
1、配置ESP32分区表
2、下载支持OTA的固件
3、开发一个工具,充当服务器,推送新的固件
4、将最新的固件下载到ESP32上
5、调换到新应用
配置分区表
idf.py menuconfig->partition_table->factory two OTA
ESP32 SPI Flash 内有与升级相关的(至少)四个分区:OTA data、Factory App、OTA_0、OTA_1。其中 FactoryApp 内存有出厂时的默认固件。
首次进行 OTA 升级时,OTA Demo 向 OTA_0 分区烧录目标固件,并在烧录完成后,更新 OTA data 分区数据并重启。
系统重启时获取 OTA data 分区数据进行计算,决定此后加载 OTA_0 分区的固件执行(而不是默认的 Factory App 分区内的固件),从而实现升级。
同理,若某次升级后 ESP32 已经在执行 OTA_0 内的固件,此时再升级时 OTA Demo 就会向 OTA_1 分区写入目标固件。再次启动后,执行 OTA_1 分区实现升级。以此类推,升级的目标固件始终在 OTA_0、OTA_1 两个分区之间交互烧录,不会影响到出厂时的 Factory App 固件。
示例代码
#include <string.h>
#include "esp_log.h"
#include "esp_ota_ops.h"
#include "esp_https_ota.h"
#include "esp_http_client.h"
static const char *TAG = "ota";
static const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start");
static TaskHandle_t ota_handle;
static void ota_task(void *data)
{
ESP_LOGI(TAG, "Starting OTA example task");
esp_http_client_config_t* config = (esp_http_client_config_t*)data;
#ifdef CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK
config.skip_cert_common_name_check = true;
#endif
esp_https_ota_config_t ota_config = {
.http_config = config,
};
ESP_LOGI(TAG, "Attempting to download update from %s", config->url);
esp_err_t ret = esp_https_ota(&ota_config);
if (ret == ESP_OK)
{
ESP_LOGI(TAG, "OTA Succeed, Rebooting...");
esp_restart();
}
else
{
ESP_LOGE(TAG, "Firmware upgrade failed");
}
while (1)
{
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void ota_init(http_event_handle_cb event_handler)
{
vTaskDelete(ota_handle);
esp_http_client_config_t config = {
.url = "http://192.168.2.102:8080/build/hello_world.bin",
.cert_pem = (char *)server_cert_pem_start,
.event_handler = event_handler
};
xTaskCreate(&ota_task, "ota_task", 8192, &config, 5, &ota_handle);
}
注意事项
| 如果 url 是 https 需要配置 https 证书,否则无法请求成功