用esp32实现一个可配置的网关应用记录:通过网页进行OTA升级

前言

ota升级是嵌入式应用的一个重要功能,能够让千里之外的用户不需烧录等开发知识就能轻松升级程序。

之前在第一家公司的时候,产品基于stm32, 所有的应用升级都是直接拿的烧录器去烧录,当时还不知道有这个东西,以至于某次产品出产,程序出了问题,没法直接给客户bin文件去解决,只能把产品批量退回来,调试解决完,一个个去重新烧录。。。。。后面我跟面试官去讨论这段经历的时候面试官都是惊呆的。

esp32已经封装好了bootloader,自带wifi功能,esp-idf本身提供了很多例程,包括webserver,配置wifi, 软件加密,文件系统, ota等,很好上手,十分适合做不需要太多引脚的物联网消费应用。

如果要在stm32上实现类似的功能就要自己配置bootloader, 移植lwip等网络栈,会比较麻烦。

在公司就见到这么一个esp32应用, ota, wifi, 文件系统,网页配置一应俱全,正好花点时间把相关的功能熟悉一遍,扩宽技术。

实战

原理

网页ota的升级流程是,点击按钮上传页面,浏览器会向esp32的服务器发送POST请求,里面包含用于升级的文件,esp32服务器接收到这个文件后,经过版本和完整性验证无误后,写入自己的ota分区,然后设置启动分区到这个ota分区,重启,重启完后芯片就会运行在ota分区中写入的程序。

对于ota, esp32本身提供了两个例程: simple_ota和native_ota, 两个都是作为http客户端向服务器下载程序。

区别在于,前者已经把整个从http下载和升级的过程封装在了esp_https_ota,代码十分简短。

	 esp_http_client_config_t config = {
   
        .url = CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL, // http://192.168.1.4:8080/blink.bin
   		...
    };
	...
	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);
    }

而后者过程就比较详细了,能够访问到ota分区以及bin的数据结构,将bin通过esp_ota_write写入ota分区之前, 还包括从http循环读取数据,版本验证等一大堆流程,比较繁琐。

我要做的是向服务器上传程序,让esp32接触到这个程序来进行升级做不到上述需求,simple_ota没法接触到bin,做不到这个需求,只有native_ota可以做。

webserver方面,我直接用的esp-idf的**file_serving**例程去改。

配置分区表

Flash大小配置为4MB,分区采用自定义分区,节省空间起见,把factory删掉,让bootloader在ota_0分区启动程序。

分区表如下:

# Name,   Type, SubType, Offset,  Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
nvs,data,   nvs,            0x9000,     16K,
otadata,    data,   ota,    0xd000,     8K,
phy_init,   data,   phy,    0xf000,     4K,
ota_0,      app,    ota_0,  ,   1M,
ota_1,      app,    ota_1,  ,   1M,
storage,  data, spiffs,  ,     1M,

弄懂分区表花了不少时间,不需要配的过大,主要看设置的flash大小以及编译出的程序大小,我编译出来的程序大概1M左右,出来的factory默认就是1M,因此ota_0和ota_1都是1M,spiffs我就设置成了1M,加上nvs,otadata和phy_init, 不超过4M。

根据文档,分区表的用到的一些特性记录如下:

  • 在使用 OTA 功能时,应用程序应至少拥有 2 个 OTA 应用程序分区(ota_0ota_1)。
  • ota (0) 即 OTA 数据分区 ,用于存储当前所选的 OTA 应用程序的信息。这个分区的大小需要设定为 0x2000(即8K,esp32一个扇区0x1000=4k)。
  • 如果你希望在 OTA 项目中预留更多 flash,可以删除 factory 分区,转而使用 ota_0 分区。
  • 强烈建议为 NVS 分区分配至少 0x3000 字节空间。

取消大文件限制

file_serving例程默认有200kb的大小限制,超过这个限制的文件都无法被上传,需要修改file_server.c配置的文件大小,我这里随便设置到了3MB。

/* Max size of an individual file. Make sure this
 * value is same as that set in upload_script.html */
#define MAX_FILE_SIZE   (3024*1024) // 3 KB
#define MAX_FILE_SIZE_STR "3MB"

请求头设置

sdkconfig设置Component config → HTTP Server

Max HTTP Request Header Length 从默认512设置成4096,避免出现请求头超过报错的问题。

测试页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tron6000 File Server</title>
    <style>
        .logo {
   
            font-size: 25px;
            text-align: left;
            margin-bottom: 10px;
        }
        .version {
   
            font-size: 15px;
            color: gray;
            text-align: left;
            margin-bottom: 10px;
        }
        #progressContainer {
     
            margin-top: 10px;
            display: none;
        }
        #uploadProgress {
     
            width: 200px;
            height: 20px;
        }
        #percentage {
     
            margin-left: 10px;
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值