【ESP32】用于 OTA 升级的 .bin 固件格式
·
用于 OTA 升级的 .bin 固件格式
ESP-IDF 编译生成的 .bin 固件文件由以下几个部分组成:
整体结构
[文件头 (8字节)] + [扩展文件头 (16字节)] + [若干数据段] + [页脚]
所有多字节字段均为小端序(little-endian)。 [ESP32 固件格式]
1. 文件头(File Header,8字节)
| 字节 | 说明 |
|---|---|
| 0 | 魔术字节,固定为 0xE9 |
| 1 | 数据段数量 |
| 2 | SPI Flash 模式(0=QIO, 1=QOUT, 2=DIO, 3=DOUT) |
| 3 | 高4位:Flash 大小;低4位:Flash 频率 |
| 4–7 | 程序入口地址 |
这就是为什么 OTA 校验时要求第一个字节必须是
0xE9。
2. 扩展文件头(Extended File Header,16字节)
| 字节 | 说明 |
|---|---|
| 0 | WP 引脚配置 |
| 1–3 | SPI Flash 引脚驱动设置 |
| 4–5 | 芯片 ID(标识该固件适用于哪款 ESP 芯片) |
| 6 | 最低芯片版本(已废弃) |
| 7–8 | 最低芯片版本(格式:major × 100 + minor) |
| 9–10 | 最高芯片版本(格式:major × 100 + minor) |
| 11–14 | 保留字节 |
| 15 | 是否附加 SHA256 哈希(1 = 附加) |
这就是为什么芯片 ID 不匹配时会报
mismatch chip ID错误。 [ESP32C3 固件格式]
3. 数据段(Segment)
每个段的格式:
| 字节 | 说明 |
|---|---|
| 0–3 | 内存加载地址 |
| 4–7 | 段数据大小 |
| 8…n | 段数据内容 |
4. 页脚(Footer)
- 文件用零填充,直到大小为 16 字节的倍数减 1。
- 最后一个字节是所有段数据的校验和(所有字节与
0xEF的异或值)。 - 若扩展头中
hash_appended = 0x01,则在校验和之后附加整个镜像的 SHA256 摘要(用于检测数据损坏,与 Secure Boot 无关)。 - 若启用了 Secure Boot,还会在 SHA256 之后附加签名块。 [ESP32 固件格式]
5. 应用程序描述符(App Descriptor)
在应用程序镜像偏移 0x20 处,还有一个应用描述符,包含版本号、项目名称、编译时间、IDF 版本、安全版本等信息:
typedef struct {
uint32_t magic_word; // 魔术字
uint32_t secure_version; // 安全版本(用于防回滚)
uint32_t reserv1[2];
char version[32]; // 固件版本
char project_name[32]; // 项目名称
char time[16]; // 编译时间
char date[16]; // 编译日期
char idf_ver[32]; // IDF 版本
uint8_t app_elf_sha256[32]; // ELF 文件的 SHA256
uint32_t reserv2[20];
} esp_app_desc_t;
[OTA 框架]
分析固件文件
可以使用 esptool 的 image_info 命令查看固件的完整头部和段信息:
esptool.py image_info your_firmware.bin
更多推荐



所有评论(0)