Files
bootloader/README.md
rovina d2b8bd7940 Initial commit: STM32 Bootloader extension module
Add a production-ready, educational bootloader extension for STM32 MCUs.

Core features:
- Custom binary protocol with CRC16/CRC32 verification
- AES-256 encryption for firmware security
- Dual-bank firmware management with rollback support
- Version management and firmware validation
- Modular architecture with BSP abstraction layer

Project structure:
- include/: Header files (bootloader.h, bsp_flash.h, bsp_uart.h)
- src/: Core implementation (bootloader, protocol, crypto, firmware manager)
- port/: MCU-specific adaptation layer (STM32F4xx)
- docs/: Documentation (integration guide, porting guide)

Supported platforms:
- STM32F4xx (primary)
- STM32F1xx (via porting)

Quick start:
1. Copy extension module to project
2. Configure bootloader_config.h
3. Modify linker script for APP_BASE_ADDR
4. Build and flash bootloader to 0x08000000

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 15:03:51 +08:00

696 lines
24 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# STM32 Bootloader Extension
> 一个教学导向的、可移植的、生产就绪的Bootloader扩展模块
![License](https://img.shields.io/badge/license-MIT-blue.svg)
![Platform](https://img.shields.io/badge/platform-STM32-orange.svg)
![Language](https://img.shields.io/badge/language-C-green.svg)
---
## 目录
- [项目简介](#项目简介)
- [核心特性](#核心特性)
- [快速开始](#快速开始)
- [架构设计](#架构设计)
- [学习路径](#学习路径)
- [模块详解](#模块详解)
- [配置指南](#配置指南)
- [移植指南](#移植指南)
- [上位机工具](#上位机工具)
- [常见问题](#常见问题)
- [贡献指南](#贡献指南)
---
## 项目简介
这是一个专为**教学目的**设计的STM32 Bootloader扩展模块采用**分层架构**和**模块化设计**,让您:
- 理解Bootloader的核心原理
- 掌握固件升级的完整流程
- 学习安全启动的设计思想
- 获得可直接用于生产环境的代码
### 为什么需要Bootloader
```
┌─────────────────────────────────────────────────┐
│ 传统固件升级:需要拆卸设备、连接调试器 │
│ → 成本高、效率低、用户体验差 │
├─────────────────────────────────────────────────┤
│ Bootloader升级串口/USB直接更新固件 │
│ → 无需拆卸、远程升级、用户友好 │
└─────────────────────────────────────────────────┘
```
### 适用场景
- IoT设备远程固件更新
- 嵌入式产品现场升级
- 需要安全启动的设备
- 学习嵌入式Bootloader开发
---
## 核心特性
| 特性 | 描述 | 状态 |
|------|------|:----:|
| 自定义协议 | 高效可靠的数据传输协议 | ✅ |
| AES-256加密 | 固件传输全程加密保护 | ✅ |
| CRC32校验 | 数据完整性验证 | ✅ |
| 双Bank备份 | 安全升级,失败可回滚 | ✅ |
| 版本管理 | 固件版本控制 | ✅ |
| 模块化设计 | 易于理解和移植 | ✅ |
| 跨MCU支持 | 通过BSP抽象层适配 | ✅ |
---
## 快速开始
### 5分钟集成到您的项目
#### 步骤1: 复制扩展模块
```bash
# 将extensions目录复制到您的STM32项目根目录
cp -r extensions/ /path/to/your/project/
```
#### 步骤2: 配置参数
编辑 `extensions/bootloader/include/bootloader_config.h`:
```c
// 选择您的MCU系列
#define MCU_FAMILY_STM32F4XX 1
#define MCU_FAMILY_STM32F1XX 0
// 配置Flash布局
#define BOOTLOADER_SIZE_KB 32
#define APP_BASE_ADDR 0x08008000
#define BANK1_ADDR 0x08008000
#define BANK2_ADDR 0x08038000
// 配置串口参数
#define BOOT_UART_BAUDRATE 115200
```
#### 步骤3: 修改main.c
```c
#include "bootloader.h"
int main(void) {
HAL_Init();
SystemClock_Config();
// === Bootloader入口 ===
bootloader_init();
if (bootloader_check_enter()) {
// 进入Bootloader模式
while (bootloader_get_state() != BOOT_STATE_JUMP_APP) {
bootloader_process();
}
}
// =====================
// 您的应用代码...
MX_GPIO_Init();
MX_USART1_UART_Init();
while (1) {
// 主循环
}
}
```
#### 步骤4: 修改链接脚本
将应用程序的起始地址修改为 `APP_BASE_ADDR`:
```ld
/* 原始 */
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
/* 修改为 */
FLASH (rx) : ORIGIN = 0x08008000, LENGTH = 992K
```
#### 步骤5: 编译并烧录
```bash
# 编译Bootloader
cd extensions/bootloader
mkdir build && cd build
cmake .. -DMCU_FAMILY=stm32f4xx
make
# 烧录Bootloader到0x08000000
st-flash write bootloader.bin 0x08000000
```
---
## 架构设计
### 分层架构图
```
┌─────────────────────────────────────────────────────────┐
│ 应用层 (Application) │
│ main.c / 用户代码 │
├─────────────────────────────────────────────────────────┤
│ API层 (bootloader.h) │
│ 统一对外接口,屏蔽内部实现细节 │
├─────────────────────────────────────────────────────────┤
│ 功能模块层 (MCU无关) │
│ ┌────────────┬────────────┬────────────┬───────────┐ │
│ │ Protocol │ AES Crypto │ CRC Check │ Firmware │ │
│ │ Handler │ Engine │ Module │ Manager │ │
│ └────────────┴────────────┴────────────┴───────────┘ │
├─────────────────────────────────────────────────────────┤
│ BSP抽象层 (bsp_*.h) │
│ 定义硬件操作接口,实现解耦合 │
├─────────────────────────────────────────────────────────┤
│ 移植适配层 (MCU相关) │
│ ┌──────────────┬──────────────┬──────────────┐ │
│ │ STM32F4xx │ STM32F1xx │ Others │ │
│ │ flash_port │ flash_port │ flash_port │ │
│ │ uart_port │ uart_port │ uart_port │ │
│ └──────────────┴──────────────┴──────────────┘ │
└─────────────────────────────────────────────────────────┘
```
### 数据流图
```
上位机 Bootloader 应用
│ │ │
│ ①加密固件 │ │
├─────────────────────────────────>│ │
│ │ │
│ ②发送数据包 │ │
├─────────────────────────────────>│ │
│ │ ③解密、校验 │
│ ├──────┐ │
│ │ │ │
│ │<─────┘ │
│ │ │
│ │ ④写入Flash │
│ ├──────┐ │
│ │ │ │
│ │<─────┘ │
│ │ │
│ ⑤应答确认 │ │
│<─────────────────────────────────┤ │
│ │ │
│ │ ⑥跳转执行 │
│ ├───────────────────────────>│
│ │ │
```
### Flash内存布局
```
STM32F407ZGTx (1MB Flash)
┌──────────────┬──────────────────┬─────────────────────┐
│ 地址范围 │ 用途 │ 大小 │
├──────────────┼──────────────────┼─────────────────────┤
│ 0x08000000 │ Bootloader │ 32KB │
│ ~ │ 启动引导程序 │ 包含加密/校验模块 │
│ 0x08007FFF │ │ │
├──────────────┼──────────────────┼─────────────────────┤
│ 0x08008000 │ Bank1 - App │ 192KB │
│ ~ │ 主固件存储区 │ 当前运行版本 │
│ 0x08037FFF │ │ │
├──────────────┼──────────────────┼─────────────────────┤
│ 0x08038000 │ Bank2 - Backup │ 192KB │
│ ~ │ 备份固件区 │ 升级临时存储 │
│ 0x08067FFF │ │ 回滚备份 │
├──────────────┼──────────────────┼─────────────────────┤
│ 0x08068000 │ Reserved │ 608KB │
│ ~ │ 预留空间 │ 可用于文件系统 │
│ 0x080FFFFF │ │ │
└──────────────┴──────────────────┴─────────────────────┘
```
---
## 学习路径
### 推荐学习顺序
```
第1阶段理解基础概念
├── 阅读本文档了解Bootloader原理
├── 理解Flash内存布局
└── 学习启动流程和中断向量表
第2阶段搭建开发环境
├── 集成Bootloader到您的项目
├── 配置串口通信
└── 编译并烧录测试
第3阶段深入核心模块
├── protocol.c - 理解通信协议设计
├── bsp_flash.c - 掌握Flash操作
├── aes_crypto.c - 学习加密实现
└── firmware_mgr.c - 理解固件管理
第4阶段实践与扩展
├── 移植到其他MCU平台
├── 添加自定义功能
└── 开发上位机工具
第5阶段生产部署
├── 安全性加固
├── 稳定性测试
└── 现场升级测试
```
### 学习资源
| 资源 | 说明 | 链接 |
|------|------|------|
| [INTEGRATION.md](docs/INTEGRATION.md) | 详细集成指南 | 本地文档 |
| [PORTING.md](docs/PORTING.md) | 移植到其他MCU | 本地文档 |
| [协议设计文档](docs/PROTOCOL.md) | 自定义协议详解 | 本地文档 |
| STM32参考手册 | Flash操作说明 | ST官网 |
| AES加密教程 | 加密算法原理 | 网络资源 |
---
## 模块详解
### 1. 协议模块 (protocol.c)
自定义二进制协议,高效可靠:
```
帧结构:
┌──────┬──────┬──────┬────────┬──────┬──────┐
│ HEAD │ CMD │ LEN │ DATA │ CRC16│ TAIL │
│ 0xAA │ 1字节│ 2字节│ N字节 │ 2字节│ 0x55 │
└──────┴──────┴──────┴────────┴──────┴──────┘
支持命令:
- CMD_HANDSHAKE (0x01): 握手建立连接
- CMD_ERASE_FLASH (0x02): 擦除Flash扇区
- CMD_WRITE_DATA (0x03): 写入数据包
- CMD_VERIFY_FIRM (0x04): 校验固件
- CMD_JUMP_APP (0x05): 跳转应用
- CMD_GET_VERSION (0x06): 查询版本
- CMD_SWITCH_BANK (0x07): 切换Bank
```
**设计亮点:**
- 简洁高效仅7字节开销
- CRC16校验保证数据完整性
- 支持应答重传机制
- 超时自动恢复
### 2. 加密模块 (aes_crypto.c)
AES-256加密保护固件安全
```c
// 加密流程
.bin AES-256 .bin
// 解密流程Bootloader中
AES-256 Flash
```
**安全特性:**
- 256位密钥长度
- CBC模式加密
- 随机IV向量
- 密钥不存储在代码中
### 3. 固件管理模块 (firmware_mgr.c)
完整的固件生命周期管理:
```
┌─────────────────────────────────────────┐
│ 固件升级流程 │
├─────────────────────────────────────────┤
│ 1. 接收加密固件 │
│ ↓ │
│ 2. AES-256解密 │
│ ↓ │
│ 3. CRC32完整性校验 │
│ ↓ │
│ 4. 写入Bank2临时区 │
│ ↓ │
│ 5. 验证写入数据 │
│ ↓ │
│ 6. 复制到Bank1主区 │
│ ↓ │
│ 7. 更新版本信息 │
│ ↓ │
│ 8. 重启并跳转 │
└─────────────────────────────────────────┘
```
**错误恢复:**
- 写入失败 → 保留原固件
- 校验失败 → 自动重传
- 升级中断 → Bank切换恢复
### 4. 双Bank管理
安全的固件备份机制:
```
正常升级流程:
Bank1[App v1.0] ──→ 接收新固件 → Bank2[v2.0]
验证通过复制到Bank1
Bank1[v2.0] ← Bank2[备份]
异常恢复流程:
Bank1[App v2.0] ──→ 运行异常 → 从Bank2恢复
Bank1[v1.0] ← Bank2[v1.0]
```
---
## 配置指南
### 完整配置参数
编辑 `bootloader_config.h` 文件:
```c
/*============================================================================
* MCU平台配置
*============================================================================*/
#define MCU_FAMILY_STM32F4XX 1 // STM32F4系列
#define MCU_FAMILY_STM32F1XX 0 // STM32F1系列
/*============================================================================
* Flash布局配置
*============================================================================*/
// Bootloader占用空间 (KB)
#define BOOTLOADER_SIZE_KB 32
// Flash基地址 (不要修改)
#define FLASH_BASE_ADDR 0x08000000
// 应用程序基地址
#define APP_BASE_ADDR (FLASH_BASE_ADDR + BOOTLOADER_SIZE_KB * 1024)
// 双Bank配置
#define BANK1_ADDR 0x08008000 // Bank1起始地址
#define BANK2_ADDR 0x08038000 // Bank2起始地址
#define APP_SIZE_MAX (192 * 1024) // 单个Bank最大192KB
// 版本信息存储区
#define VERSION_INFO_ADDR 0x08007C00 // 最后1KB用于存储版本信息
/*============================================================================
* 串口通信配置
*============================================================================*/
#define BOOT_UART_BAUDRATE 115200 // 串口波特率
#define BOOT_UART_TIMEOUT_MS 3000 // 接收超时 (毫秒)
#define BOOT_UART_BUFFER_SIZE 2048 // 接收缓冲区大小
/*============================================================================
* 协议配置
*============================================================================*/
#define PROTOCOL_MAX_DATA_LEN 1024 // 单包最大数据长度
#define PROTOCOL_RETRY_COUNT 3 // 重试次数
#define PROTOCOL_RETRY_DELAY_MS 100 // 重试间隔 (毫秒)
/*============================================================================
* 功能开关
*============================================================================*/
#define BOOT_ENABLE_AES 1 // 启用AES加密
#define BOOT_ENABLE_CRC 1 // 启用CRC校验
#define BOOT_ENABLE_DUAL_BANK 1 // 启用双Bank备份
#define BOOT_ENABLE_VERSION_MGR 1 // 启用版本管理
#define BOOT_ENABLE_LOG 1 // 启用日志输出
/*============================================================================
* 安全配置
*============================================================================*/
#define BOOT_AES_KEY_SIZE 256 // AES密钥长度 (128/256)
#define BOOT_AES_IV_SIZE 16 // IV向量长度
// AES密钥 (实际应用中应从安全区域读取)
#define BOOT_AES_KEY {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, \
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, \
0x76, 0x2e, 0x71, 0x60, 0xf3, 0x8b, 0x4d, 0xa5, \
0x6a, 0x78, 0x4d, 0x90, 0x45, 0x19, 0x0c, 0xfe}
/*============================================================================
* 触发方式配置
*============================================================================*/
#define BOOT_TRIGGER_TIMEOUT_MS 3000 // 启动时等待命令超时 (毫秒)
// 按键触发 (可选)
// #define BOOT_TRIGGER_PIN GPIO_PIN_0
// #define BOOT_TRIGGER_PORT GPIOA
// #define BOOT_TRIGGER_ACTIVE 0 // 0: 低电平触发, 1: 高电平触发
/*============================================================================
* 日志配置
*============================================================================*/
#if BOOT_ENABLE_LOG
#define BOOT_LOG_LEVEL_DEBUG 0
#define BOOT_LOG_LEVEL_INFO 1
#define BOOT_LOG_LEVEL_WARNING 2
#define BOOT_LOG_LEVEL_ERROR 3
#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_INFO
#endif
/*============================================================================
* 调试配置
*============================================================================*/
#define BOOT_DEBUG_MODE 0 // 调试模式 (生产环境关闭)
```
### 配置示例
#### 示例1: 最小配置 (无加密)
```c
#define BOOT_ENABLE_AES 0 // 关闭加密
#define BOOT_ENABLE_CRC 1 // 仅CRC校验
#define BOOT_ENABLE_DUAL_BANK 0 // 单Bank模式
#define BOOT_ENABLE_VERSION_MGR 0 // 不管理版本
```
#### 示例2: 生产配置 (安全最高)
```c
#define BOOT_ENABLE_AES 1 // 启用AES-256加密
#define BOOT_ENABLE_CRC 1 // 启用CRC校验
#define BOOT_ENABLE_DUAL_BANK 1 // 双Bank备份
#define BOOT_ENABLE_VERSION_MGR 1 // 版本管理
#define BOOT_ENABLE_LOG 0 // 关闭日志
```
---
## 移植指南
详细移植步骤请参考 [PORTING.md](docs/PORTING.md)
### 快速移植到新MCU
1. **复制移植模板**
```bash
cp -r port/port_template port/your_mcu
```
2. **实现Flash操作接口**
```c
// flash_port.c
int flash_port_init(void) { /* ... */ }
int flash_port_erase(uint32_t addr, uint32_t size) { /* ... */ }
int flash_port_write(uint32_t addr, const uint8_t *data, uint32_t len) { /* ... */ }
int flash_port_read(uint32_t addr, uint8_t *data, uint32_t len) { /* ... */ }
```
3. **实现UART操作接口**
```c
// uart_port.c
int uart_port_init(uint32_t baudrate) { /* ... */ }
int uart_port_send(const uint8_t *data, uint32_t len) { /* ... */ }
int uart_port_recv(uint8_t *data, uint32_t len, uint32_t timeout) { /* ... */ }
```
4. **修改CMakeLists.txt**
```cmake
set(MCU_FAMILY "your_mcu" CACHE STRING "MCU family")
```
---
## 上位机工具
### 命令行工具
```bash
# 查看帮助
./flash_tool --help
# 连接设备
./flash_tool --port COM3 --baud 115200
# 烧录固件
./flash_tool --port COM3 --write firmware.bin
# 查看版本
./flash_tool --port COM3 --version
# 擦除Flash
./flash_tool --port COM3 --erase
# 切换Bank
./flash_tool --port COM3 --switch-bank
# 加密固件
./flash_tool --encrypt firmware.bin firmware_enc.bin
```
### Python脚本 (简易版)
```python
import serial
import struct
def send_firmware(port, baudrate, firmware_path):
ser = serial.Serial(port, baudrate, timeout=3)
# 发送握手
handshake = bytes([0xAA, 0x01, 0x00, 0x00, 0x55])
ser.write(handshake)
# 读取固件
with open(firmware_path, 'rb') as f:
firmware = f.read()
# 发送数据包...
# (详细实现见 tools/flash_tool)
ser.close()
if __name__ == '__main__':
send_firmware('COM3', 115200, 'firmware.bin')
```
---
## 常见问题
### Q1: Bootloader启动后无法跳转到应用?
**A:** 检查以下几点:
1. 应用程序的链接脚本起始地址是否正确设置为 `APP_BASE_ADDR`
2. 应用程序的中断向量表是否偏移 `SCB->VTOR = APP_BASE_ADDR`
3. 应用程序是否正确编译烧录
### Q2: Flash写入失败?
**A:** 常见原因:
1. Flash未解锁
2. 写入地址未擦除
3. 写入地址未对齐
4. Flash页大小配置错误
### Q3: 串口通信不稳定?
**A:** 建议:
1. 降低波特率到 9600 或 57600
2. 增加超时时间 `BOOT_UART_TIMEOUT_MS`
3. 添加硬件流控
4. 检查串口线缆质量
### Q4: 如何调试Bootloader?
**A:** 方法:
1. 启用日志输出 `BOOT_ENABLE_LOG = 1`
2. 设置日志级别 `BOOT_LOG_LEVEL = BOOT_LOG_LEVEL_DEBUG`
3. 使用串口打印调试信息
4. 使用调试器单步调试
### Q5: 如何确保固件安全性?
**A:** 建议:
1. 启用AES-256加密 `BOOT_ENABLE_AES = 1`
2. 密钥不要硬编码,从安全区域读取
3. 使用固件签名验证
4. 启用读保护 (RDP)
---
## 性能指标
| 指标 | 数值 |
|------|------|
| Bootloader大小 | ~16KB (启用所有功能) |
| 最小程序大小 | ~4KB (仅基础功能) |
| RAM占用 | ~2KB |
| 192KB固件升级时间 | ~15秒 @115200 |
| 支持最大固件大小 | 192KB (单Bank) |
| 可靠性 | CRC校验 + 重传机制 |
---
## 版本历史
| 版本 | 日期 | 说明 |
|------|------|------|
| v1.0.0 | 2026-01 | 初始版本,基础功能 |
| v1.1.0 | TBD | 添加AES加密支持 |
| v1.2.0 | TBD | 添加双Bank支持 |
| v2.0.0 | TBD | 重构架构支持多MCU |
---
## 许可证
本项目采用 MIT 许可证,详见 [LICENSE](LICENSE) 文件。
---
## 贡献指南
欢迎贡献代码、报告问题或提出建议!
1. Fork 本仓库
2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
4. 推送到分支 (`git push origin feature/AmazingFeature`)
5. 提交 Pull Request
---
## 联系方式
- 问题反馈: [GitHub Issues](https://github.com/your-repo/issues)
- 技术讨论: [GitHub Discussions](https://github.com/your-repo/discussions)
---
## 致谢
感谢以下开源项目的启发:
- STM32 HAL库
- TinyAES库
- STM32CubeProgrammer
---
**Happy Coding!**
如果您觉得这个项目有帮助,请给一个 ⭐ Star 支持一下!