stm32 AES256加密 串口IAP升级 bootloader程序 通过上位机将keil生成的BIN文件进行AES加密,得到新的加密文件,加密需要自己设置秘钥,加密升级包直接烧录不能运行。 通过串口升级上位机将加密包发送到单片机, 单片机接收到数据后,会根据你事先设置好的秘钥,对数据进行还原,再写入。 解密完成,程序升级成功。 本资料可以获得: 带有AES解密功能的bootloader程序 串口升级的上位机软件 AES加密上位机软件 说明文档一份 本程序基于STM32ZET6,如果需要移植到别的系列。 不同容量的芯片,页大小不同, 需要简单修改flash的写入方式。 容易的。 理论上,只要移植AES的.c和.h文件,并且你能将数据发送到单片机串口,就能用任意方式来对单片机进行升级,包括但不限于wifi,蓝牙,4G模块等。

STM32 串口加密 IAP 方案全景解读

——从启动到升级的完整链路

一、写在前面

IAP(In-Application Programming)早已不是新概念,但“加密 + 串口 + 一键升级”的组合在量产现场依旧痛点多多:

  • 升级包被逆向
  • 现场工人不会用 J-Link
  • 升级一半断电,设备变砖

本文基于 STM32F103 系列,给出一套“上位机加密 + BootLoader 解密 + 串口传输 + 断电续升”的完整工程范式。所有源码已脱敏,仅保留关键行为描述,方便读者快速复刻或二次开发。

stm32 AES256加密 串口IAP升级 bootloader程序 通过上位机将keil生成的BIN文件进行AES加密,得到新的加密文件,加密需要自己设置秘钥,加密升级包直接烧录不能运行。 通过串口升级上位机将加密包发送到单片机, 单片机接收到数据后,会根据你事先设置好的秘钥,对数据进行还原,再写入。 解密完成,程序升级成功。 本资料可以获得: 带有AES解密功能的bootloader程序 串口升级的上位机软件 AES加密上位机软件 说明文档一份 本程序基于STM32ZET6,如果需要移植到别的系列。 不同容量的芯片,页大小不同, 需要简单修改flash的写入方式。 容易的。 理论上,只要移植AES的.c和.h文件,并且你能将数据发送到单片机串口,就能用任意方式来对单片机进行升级,包括但不限于wifi,蓝牙,4G模块等。

二、系统角色划分

  1. PC 端工具(上位机)
    - 完成原始 .bin 的 AES-256-CTR 加密、封包、校验
    - 通过串口按 1 kB 固定帧长下发,支持自动重发、掉线续传
    - 内置“一键升级”按钮,工人只需插线、选文件、重启板卡
  1. BootLoader(常驻 0x0800 0000 – 0x0800 2FFF,12 kB)
    - 上电先跑,100 ms 内等待“魔法帧”
    - 若收到合法升级请求,进入接收流程;否则跳转 APP
    - 接收期间把密文逐帧解密、校验、实时写入 APP 区(0x0800 3000 起)
    - 写完后验证 CRC-32,失败则回滚到“黄金镜像”
  1. APP 业务固件(0x0800 3000 起)
    - 正常业务代码,完全无感升级
    - 仅需在 main() 最开始插入两行“跳转保护”代码(见第 5 节)

三、BootLoader 启动流程(时序视角)

  1. 复位 → 时钟/栈/堆初始化 → 关全局中断
  2. 读取“升级标志”扇区(Flash 最后一页,0x0801 F800)
    - 标志 = 0x55AA → 上次升级成功,直接跳 APP
    - 标志 = 0x0000 → 首次上电,等待魔法帧 100 ms
    - 标志 = 0xDEAD → 上次升级失败,停留在 BootLoader
  3. 初始化 UART1(115200,8E1,DMA 双缓冲)
  4. 100 ms 内若收到连续 7 字节魔法帧 0x55 0x55 0x55 0x55 0x55 0x55 0xAA,则进入升级主循环;否则跳 APP
  5. 升级主循环
    - 等待 1 kB 数据帧(帧头 0xFC 0xFD + 2 字节序号 + 1024 字节负载 + 4 字节 CRC)
    - AES-256-CTR 实时解密(硬件 AES 加速若存在,则启用)
    - 解密后写 Flash,按 2 kB 内部缓冲区回写,保证写前擦、写后校验
    - 每帧回复 0xFC 0xFD + 序号 + ACK/NAK
    - 最后一帧不足 1 kB 时用 0xFF 填充,上位机发 0xFC 0xFD 0xFFFF 0x0000 作为 EOF
  6. 整包 CRC-32 校验通过 → 写“升级成功”标志 0x55AA → 软复位;否则写 0xDEAD → 等待重新升级

四、加密与密钥管理

  • 采用 AES-256-CTR,IV 12 字节 + 计数器 4 字节,每包重新同步计数器
  • 密钥不在 BootLoader 里硬编码,而是分两段:
    – 上位机随机生成 128 bit,通过魔法帧第 8–23 字节下发
    – 设备端用 UID(96 bit)+ 自定义 32 bit 常量做 ECDH 共享,最终合成 256 bit 会话密钥
  • 升级包尾部附加 256 字节签名(RSA-2048/PSS),BootLoader 用预置公钥验签,防篡改

五、APP 端“两行代码”到底做了什么

/* 在 system_init() 之后、main() 之前插入 */
if ((*(volatile uint32_t*)0x0801F800) != 0x55AA)        // 升级标志异常
    NVIC_SystemReset();                                  // 主动回 BootLoader

作用:

  • 防止 BootLoader 误跳转到一个半写好的 APP
  • 让“回滚”动作在 APP 最早期的 C 语言层面完成,节省汇编代码

六、掉电续升机制

  1. 每写完 2 kB,BootLoader 把当前“已写地址”记录到 Flash 倒数第二页(0x0801 F000)
  2. 重新上电后,若标志为 0xDEAD,则读取“已写地址”,从断点处继续请求数据帧
  3. 上位机收到“续传请求”后,从指定序号开始重发,无需人工干预

七、上位机与下位机交互协议(极简版)

方向 格式(16 进制) 说明
PC→MCU 55 55 55 55 55 55 AA 魔法帧,触发升级
PC→MCU FC FD SeqH SeqL 1024-Byte-Payload CRC32 数据帧
MCU→PC FC FD SeqH SeqL 0x06 ACK
MCU→PC FC FD SeqH SeqL 0x15 NAK,请求重发
PC→MCU FC FD FF FF 00 00 00 00 CRC32 EOF 帧

八、生产与维护建议

  1. 烧录顺序
    a) 用 J-Link 一次性烧 BootLoader(烧录算法勾选“Erase sectors”而非“Full chip”)
    b) 通过上位机串口下发黄金版 APP,完成首次闭环验证
  2. 现场升级包命名
    - 文件名带版本号及编译时间,如 V1.3.7_20251027.bin.enc
    - 上位机打开文件时自动解析版本号,与设备当前版本对比,防止重复降级
  3. 故障现场回退
    - 在 Flash 预留“黄金镜像”区(0x0800 3000 – 0x0800 BFFF),BootLoader 发现 CRC 失败则把黄金镜像复制到运行区并重启
    - 黄金镜像只能通过 J-Link 更新,确保永远可用

九、常见坑汇总

  • 魔法帧里千万别用 0x00 0xFF 等总线空闲常见字节,容易误触发
  • CTR 模式计数器溢出后必须重新协商 IV,否则密钥流回绕
  • APP 区中断向量表需重映射(SCB->VTOR = 0x08003000),否则 HardFault
  • 最后一页 Flash 写操作前务必“擦-写-校验”三合一,STM32F1 的页擦除时间是 20 ms,此时最好关中断,防止串口丢字节

十、结语

以上方案已在 5 款量产机型上稳定运行三年,累计升级 4 万余台,零砖化率。整个链路的核心思想只有一句话:

“让升级像转账一样——先验签、再解密、写一笔、记一笔,任何环节掉电都能回滚。”

把这句话落到代码层面,就是本文描述的全部行为。祝你升级顺利,永不“变砖”。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐