BootLoader-ESP8266
BootLoader-ESP8266
概括
由于是stm32主动获取固件,所以我使用了类似于AT指令的架构去处理如何连接wifi,设置固件位置,拉取固件等,将主动权交给stm32
没有云服务器也没关系,可以自己的电脑当作服务器。
视频内效果




ESP8266部分
1. 简介
本固件将 ESP8266 作为 STM32 的 Wi-Fi 协处理器(网关)。它通过串口(UART)接收 STM32 的 AT 指令,负责连接 Wi-Fi、管理配置信息(EEPROM),并从指定的 HTTP 服务器下载固件数据,通过自定义的分包协议传输给 STM32,用于实现 OTA(空中升级)功能。
2. 硬件连接与通信参数
- 通信接口: UART (Serial)
- 波特率:
115200bps - 连接方式:
- ESP8266
TX<--> STM32RX - ESP8266
RX<--> STM32TX - GND <--> GND
- VCC <--> 5V
- ESP8266
3. 启动流程与默认配置
ESP8266 上电后会执行以下操作:
- 加载配置: 读取 EEPROM。如果是首次运行(Magic Number 校验失败),将加载默认配置并写入 EEPROM。
- 连接 Wi-Fi: 尝试连接配置中的 SSID。
- 状态输出:
- 启动中输出:
[ESP8266] Booting... - 连接成功输出:
[WiFi] Connected!及 IP 地址。 - 连接失败输出:
[WiFi] Connect Failed - 就绪信号:
READY(STM32 应在收到此信号后开始发送指令)。
- 启动中输出:
默认配置 (恢复出厂)
- SSID:
aaa - Password:
aaaaaaaa - Version URL:
http://111.231.116.18/version.txt - Firmware URL:
http://111.231.116.18/app.bin
4. AT 指令集
STM32 通过发送字符串指令控制 ESP8266,指令需以换行符 \n 结尾。
4.1 基础指令
| 指令 | 描述 | 成功响应 | 失败响应 |
|---|---|---|---|
AT | 测试通信链路 | OK | 无响应 |
4.2 配置指令 (自动保存至 EEPROM)
| 指令格式 | 描述 | 响应 | 备注 |
|---|---|---|---|
AT+SetWifi=<ssid>,<pwd> | 设置Wi-Fi名称和密码 | OK_RECONNECTING 或 ERR_PARAM | 设置后会立即断开重连 |
AT+SetVerUrl=<url> | 设置版本号文件地址 | OK 或 ERR_LEN | URL最大长度 127 字节 |
AT+SetFwUrl=<url> | 设置固件文件地址 | OK 或 ERR_LEN | URL最大长度 127 字节 |
AT+GetConfig | 查询当前所有配置 | SSID: ...VerURL: ...FwURL: ...OK | - |
4.3 OTA 功能指令
| 指令 | 描述 | 响应数据 |
|---|---|---|
AT+GetNewVersion | 获取服务器上的版本号文本 | 成功:<版本号字符串>失败: ERR <HTTP_CODE> |
AT+GetBinSize | 获取服务器固件大小 (字节) | 成功:<字节大小>失败: ERR <HTTP_CODE> |
AT+GetBin | 开始固件下载流程 | 见下方“固件传输协议” |
5. 固件数据传输协议 (重点)
当 STM32 发送 AT+GetBin 指令后,ESP8266 进入透传模式。它将利用 HTTP Range 头分块下载固件,并按以下协议打包发送给 STM32。
5.1 数据包结构
每个数据包包含 1024 字节(或最后一块剩余字节)的有效固件数据。
| 字节索引 | 含义 | 说明 |
|---|---|---|
| 0 | 帧头 | 固定为 0xAA |
| 1 | 长度低位 | 有效数据长度 (Low Byte) |
| 2 | 长度高位 | 有效数据长度 (High Byte) |
| 3 ... (3+n-1) | 有效数据 | 固件二进制数据 (最大 1024 bytes) |
| 3+n | CRC低位 | CRC16 Modbus 校验 (Low Byte) |
| 3+n+1 | CRC高位 | CRC16 Modbus 校验 (High Byte) |
| 3+n+2 | 帧尾 | 固定为 0x55 |
总包长: DataLen + 6 字节。
5.2 握手流程 (流控)
为了防止 STM32 写入 Flash 速度跟不上串口接收速度,采用“发一答一”的机制:
- ESP8266 发送: 发送一个完整的数据包(如上表结构)。
- ESP8266 等待: 等待 STM32 回复
OK字符串。- 超时时间:3000ms (3秒)。
- 如果超时,ESP8266 将输出
ERR_TIMEOUT并终止传输。
- STM32 处理:
- 接收数据包 -> 校验 CRC -> 写入 Flash。
- 处理完成后通过串口发送
OK。
- 循环: ESP8266 收到
OK后,下载并发送下一个数据包。
5.3 传输结束
当所有数据传输完毕后,ESP8266 会发送字符串:END
5.4 异常处理
如果在传输过程中出现网络错误或服务器错误,ESP8266 会输出:ERR_HTTP <错误码> 或 ERR_SIZE,随后终止传输。
STM32部分
本项目实现了一个基于 STM32F407(适配代码中的扇区定义)和 ESP8266 的 OTA (Over-The-Air) 在线升级 Bootloader。
Bootloader 运行在 MCU 启动的最前端,负责连接 Wi-Fi、检查服务器是否有新版本的固件。如果有,则下载固件并写入 Flash,最后跳转到用户应用程序(App)运行。
Keil配置
boot keil:
app keil
1.核心功能
- 网络通信: 通过串口 AT 指令控制 ESP8266 连接 Wi-Fi 和 HTTP 服务器。
- 版本管理: 对比本地 Flash 与服务器端的版本号,决定是否更新。
- 固件下载: 支持 HTTP
Range断点续传(分包下载),并通过自定义协议(含 CRC16 校验)接收数据。 - Flash 操作: 自动擦除 App 区域、写入新固件、更新版本元数据。
- 程序跳转: 安全跳转至用户 App 运行。
2. 系统内存布局 (Memory Map)
这是 Bootloader 最关键的配置,决定了程序存放在 Flash 的哪个位置。
| 区域名称 | 起始地址 | 扇区 (STM32F4) | 用途 |
|---|---|---|---|
| Bootloader | 0x0800 0000 | Sector 0 ~ 1 | 本代码存放位置,系统上电默认运行。 |
| Metadata | 0x0800 8000 | Sector 2 (16KB) | 元数据区。存储版本号、发布者、更新时间。 |
| Application | 0x0800 C000 | Sector 3 ~ 7 | 用户 APP 区。下载的固件会被写入这里。 |
注意: 用户编写的 APP 程序,其 Keil 工程的起始地址必须设置为
0x0800C000,并且在代码初始化时设置中断向量表偏移SCB->VTOR = 0x0800C000。
3. 核心数据结构
3.1 AppMetadata_t (版本元数据)
存储在 Flash Sector 2 中,用于记录当前已安装的固件信息。
typedef struct {
uint32_t magic_word; // 有效标志 (0xA5A5A5A5),用于判断是否已写入过版本信息
char version[32]; // 版本号字符串,如 "v1.0.2"
char publisher[32]; // 发布者
char date[32]; // 发布日期
} AppMetadata_t;4. 关键函数详解
4.1 初始化与配置
ESP_Config_Init(void)
- 功能: 初始化 ESP8266,设置 Wi-Fi 账号密码和服务器 URL。
- 逻辑:
- 发送
AT检查模块是否在线。 - 发送
AT+SetWifi设置 SSID 和密码。 - 发送
AT+SetVerUrl和AT+SetFwUrl设置资源地址。
- 发送
- 教学点: 使用了简单的“发送指令 -> 等待特定回复”机制,这是嵌入式与模组通信最常用的方式。
4.2 核心 OTA 逻辑
OTA_CheckAndDownload(void)
这是 main 函数中调用的主业务逻辑,流程如下:
- 获取服务器版本: 发送
AT+GetNewVersion。 - 版本对比:
- 读取 Flash
0x08008000处的本地版本。 - 如果服务器版本与本地不同,或者本地没有版本信息(Magic Word 不对),则触发更新。
- 读取 Flash
- 获取固件大小: 发送
AT+GetBinSize,用于计算下载进度百分比。 - 擦除 Flash: 调用
Flash_Erase_App()擦除 Sector 3 到 Sector 7,为新固件腾出空间。 - 下载循环:
- 发送
AT+GetBin请求数据。 - 接收协议包: 头(
0xAA) + 长度 + 数据 + CRC + 尾(0x55)。 - 校验: 计算 CRC16,如果正确则写入 Flash (
Flash_Write_Data) 并回复OK;否则回复错误码。 - 结束判断: 如果收到字符
END,说明下载完成。
- 发送
- 收尾: 更新元数据 (
Flash_Update_Metadata) 并重启 MCU。
4.3 硬件底层操作
JumpToApplication(void)
- 功能: 从 Bootloader 跳转到 App。这是 Bootloader 的“最后一公里”。
- 关键步骤:
- 检查栈顶地址:
if (((*(__IO uint32_t*)APP_ADDRESS) & 0x2FFE0000) == 0x20000000),确保 APP 地址合法且栈指针在 RAM 范围内。 - 关闭中断:
__disable_irq()。跳转过程中如果有中断触发会导致 HardFault,必须全局关闭。 - 清理现场: 关闭 SysTick,清除 NVIC 中断挂起位。
- 重定向向量表:
SCB->VTOR = APP_ADDRESS。告诉 CPU 现在的中断向量表在 APP 的起始位置,而不是 Bootloader 的位置。 - 设置主堆栈指针 (MSP):
__set_MSP(...)。将栈指针恢复到 APP 预设的初始状态。 - 跳转: 执行函数指针跳转。
Flash_Erase_App(void)
- 检查栈顶地址:
- 功能: 擦除存放 App 的 Flash 区域。
- 细节: 本代码配置为擦除
FLASH_SECTOR_3开始的连续 5 个扇区。在 STM32F4 中,Flash 是按扇区擦除的,写入前必须先擦除(将位变为 1)。
4.4 辅助工具
UART_Flush(void)
- 功能: 清空串口接收缓冲区。
- 作用: 在发送新指令前,如果缓冲区里还有上次通信残留的垃圾数据(如
\r\n),会导致后续解析出错。此函数通过循环读取寄存器直至清空,保证通信可靠性。crc16_modbus(...) - 功能: 计算数据的校验和。
- 作用: 串口传输容易受干扰出错,CRC 校验能确保写入 Flash 的数据与服务器上的文件完全一致,防止变砖。
