esp32 Flash分区与OTA功能简析

本文解析了ESP32的Flash分区配置及SDK OTADemo的升级流程,介绍了如何自定义分区以满足产品需求,详细分析了升级策略,包括固件获取与烧录过程以及OTA升级策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

升级功能对于所有的嵌入式产品都是非常重要的。尤其是当产品量产/销售阶段,已经没有条件让厂家对产品升级,因此升级方式的设计必须防呆防错以及稳定。

乐鑫ESP32作为蓝牙WIFI合一的物联网芯片,开发成产品后势必会使用OTA方式进行升级。本文档对ESP32的Flash分区配置情况以及SDK提供的OTA Demo进行简要分析,并以此作为未来产品OTA流程设计的参考。

本文档只分析SDKOTA Demo的升级流程,不涉及过于具体的Flash操作,具体问题在实际开发过程中再做处理。

 

1:ESP32 Flash空间分区情况

 

1.1ESP32 Flash空间分区配置

目前使用的ESP-WROOM-32集成4MB SPI Flash。在编译esp32程序时,通过make menuconfig -> PartitionTable 可以有三种分区选择:工厂程序(无OTA分区)/工厂程序(双OTA分区)/用户自定义分区。

menuconfig中的配置只是修改配置文件中的宏,实际上ESP32 SDK对应Flash分区配置的源码路径是:

\esp-idf-v3.0-rc1\components\partition_table

该路径下有文件partitions_singleapp/partitions_singleapp_coredump/partitions_two_ota/partitions_two_ota_coredump都是用来对Flash分区进行配置的。

这里以最为复杂的partitions_two_ota_coredump为例,再参考部分代码,可以得知使用partitions_two_ota_coredump配置分区时4M SPI Flash的分区情况:  

                                                    

分区用处需要特殊说明的是:

<1>core dump分区:core dump分区用于查找系统崩溃时的软件错误,简单的说就是软件崩溃的时候会刷写调试信息到Flash保存(掉电不丢失)以便于开发者分析。关于这个分区的使用有博客:《使用ESP32 的调试工具 coredump》

https://blog.youkuaiyun.com/tidyjiang/article/details/72123346

可见core dump分区在实际开发产品时比较有用,需要保留。

<2>Factory App分区:出厂时的主程序存储区

<3>OTA data/OTA_0/OTA_1与OTA升级功能相关,后面再做叙述。

 

1.2 自定义ESP32 Flash分区配置

对于产品开发而言,需要进行Flash分区自定义配置以满足需求。简单的说,至少core dump分区,OTA相关分区,以及掉电需要保存的用户数据区都是必要的。

现在在1.1节 partitions_two_ota_coredump的基础上进行自定义Flash分区配置,在core dump分区后面加上128K user data分区用于保存用户数据,方法如下:

<1>makemenuconfig -> Partition Table -> Custom partition table CSV

选择后会要求输入自定义的分区配置csv文件名,例如填入partition.csv。

<2>从路径\esp-idf-v3.0-rc1\components\partition_table下拷贝一个分区配置文件,使用写字板修改,例如添加128K user data分区:


<3>将新编辑好的partition.csv分区配置文件拷到用户的App目录下,make即可。

<4>烧录编译好的固件后,从调试信息看,Flash分区已经变更完成。用户需要掉电保存的数据可以通过nvs api(nvs_open_from_partition)写入到user data区。(暂时未测试)


2:ESP32 SDK OTA Demo升级流程

 

ESP32SDK路径\esp-idf-v3.0-rc1\examples\system\ota是官方提供的OTA Demo,并且有OTA升级流程图(使用说明):


但是很显然这对于嵌入式开发而言没有太大参考意义。

ESP32SDK OTA Demo部分代码目前未经调试测试,因此不保证分析完全正确,有谬误再做更改。

 

2.1 ESP32 SDK OTA Demo升级策略

 

升级策略分为两个部分讨论:1:升级目标固件的获取与烧录;2:OTA升级策略。后者是关键。

 

2.1.1升级目标固件的获取与烧录

升级固件的获取与写入非常简单:ESP32连接HTTP服务器;发送请求Get升级固件;每次读取1KB固件数据;写入Flash。嵌入式设备的升级流程基本都是类似的。

期间出现异常的处理是停止升级,指针原地跳转。

 

2.1.2 OTA升级策略

 

OTA升级策略是关键的。欠缺考虑的升级策略会坑死开发人员,更因为终端用户非专业人士,缺乏防呆防错的升级策略经常会使产品升级失败变砖,投诉与赔偿在所难免(手动笑脸)。

    刨去繁琐的代码,简述ESP32SDK OTA Demo的升级策略如下: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固件。


2.2 ESP32 SDK OTA Demo API简略说明

 

根据2.1.2对OTA Demo升级策略的描述,这里罗列一下相关的重要函数接口,但不做仔细分析。具体问题待开发过程中出现时再做处理:

<1>源码路径:\esp-idf-v3.0-rc1\examples\system\ota\main\ota_example_main.c

esp_ota_get_boot_partition:

esp_ota_get_running_partition:

获取当前系统执行的固件所在的Flash分区(两者区别暂时未理解)

esp_ota_get_next_update_partition:

获取当前系统下一个(紧邻当前使用的OTA_X分区)可用于烧录升级固件的Flash分区

esp_ota_begin& esp_ota_write & esp_ota_end:

向可用的Flash分区(一般是OTA_X分区)刷入升级目标固件

esp_ota_set_boot_partition:

升级完成更新OTA data区数据,重启时根据OTA data区数据到Flash分区加载执行目标(新)固件

 

<2>源码路径:\esp-idf-v3.0-rc1\components\bootloader\subproject\main\ bootloader_start.c

load_partition_table:加载Flash分区表(从分区表找到OTA data区地址)

get_selected_boot_partition:获取Flash启动分区(计算OTA data区数据得到)

load_boot_imageunpack_load_app:从Flash启动分区加载解压固件并执行

 

2.3 优点与可能的问题

 

从ESP32 SDKOTA Demo升级策略看,应该是比较稳妥的,无论升级期间出现任何异常,只要OTA data区数据未被修改,设备还可以加载原有的固件执行。

目前看来可能需要考虑的地方有:

<1>是否存在可能,OTA data数据指向了一个升级失败的区,导致设备加载损坏的固件;

<2>因为OTA需要三个升级相关区,因此固件大小被限制在小于SPI Flash Size/3

<3>获取升级目标固件还应当加入防错/重传/校验的机制;出现异常时也应当有相应处理。

<4>留出后台控制接口,用于修改OTA data区,便于远程控制程序运行。

 

 

3:ESP32 SDK OTA升级功能设计

TBD




### ESP32 Flash 教程及常见问题解决 #### 一、ESP32 Flash 操作基础 对于 ESP32 设备而言,Flash 是用于存储固件和其他持久化数据的重要部分。在开发过程中,经常需要对 Flash 进行读写操作来更新固件或保存配置参数。 为了开始这些工作,在硬件层面确保选择了正确的开发板型号,并安装好对应的驱动程序[^1]。软件方面,则推荐使用官方支持的工具链如 ESP-IDF 来完成编译和烧录过程[^2]。 #### 二、通过 ESPTOOL.PY 对 Flash 进行基本操作 ESPTOOL.PY 提供了一系列命令用来管理和操作 ESP32Flash 存储空间: - **查看芯片信息** 要获取当前连接的 ESP32 芯片的信息可以执行如下 Python 命令: ```bash esptool.py --port COMX chip_id ``` 这里 `COMX` 需替换为实际使用的串口号。 - **擦除整个 Flash** 如果想要完全清除掉之前所有的内容以便重新部署新的镜像文件,可利用下面这条指令: ```bash esptool.py --port COMX erase_flash ``` 这一步骤非常重要尤其是在遇到一些难以解释的行为时,因为旧版本残留的数据可能会引起冲突。 - **烧录固件至指定地址** 当准备好了一个新构建出来的 bin 文件之后就可以将其下载到目标位置上了: ```bash esptool.py --chip esp32 --port COMX write_flash -z 0x1000 path/to/firmware.bin ``` 注意这里的 `-z` 参数表示压缩模式,而后面的路径则指向本地磁盘上的固件文件;同样地记得调整端口名称以及起始偏移量以适应具体情况需求。 #### 三、处理常见的 Flash 相关错误提示 有时会碰到诸如 "Failed to connect" 或者 "Invalid head of packet" 类型的消息,这时候应该考虑以下几个可能的原因并采取相应措施加以排除: - 确认所选波特率设置适当(比如默认情况下采用的是 921600bps),必要时候下调速率尝试; - 排查物理连线是否存在接触不良的情况,尤其是电源供电是否稳定可靠; - 断开所有不必要的外设后再重试一次,防止它们干扰正常的通信流程; - 如果仍然无法解决问题的话不妨试着更换另一根USB转TTL电缆试试看。 另外值得注意的一点是在某些特殊场景下还需要额外关注 SPI Flash 控制寄存器的状态位变化情况,不过这类高级话题超出了本文讨论范围之内[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值