第2章 固件升级基础概念:理解什么是固件、Bootloader、应用程序以及它们之间的关系

各位同学,咱们今天聊点最基础,但也最容易被忽视的东西。

做固件升级,你得先搞清楚三个角色:固件Bootloader应用程序。它们仨是什么关系?说白了,就像你家里的三层小楼——地基、一楼、二楼。没有地基,楼就塌了;没有一楼,你上不去二楼;没有二楼,你住哪儿?

2.1 什么是固件?

固件,英文叫 Firmware。我习惯把它理解成「硬件和软件之间的粘合剂」。它不是纯软件,也不是纯硬件,而是固化在非易失性存储器里的程序

你想想看,一个 MCU 上电后,它怎么知道自己该干什么?它得从 Flash 里读指令。这些指令就是固件。固件里包含了芯片的初始化、外设驱动、中断向量表等等。

我在项目中遇到过一件事:有个同事把固件和应用程序混为一谈,结果升级时只刷了应用层,忘了更新底层驱动,导致新功能死活跑不起来。嗯,这就是没搞清楚固件的边界。

固件的核心特征:

  • 存储在 Flash、EEPROM 等非易失介质中
  • 掉电不丢失
  • 通常包含启动代码、驱动库、运行时环境
  • 更新频率低,但一旦更新往往涉及底层改动

2.2 什么是 Bootloader?

Bootloader,直译就是「引导加载程序」。我个人觉得,叫它「看门大爷」更形象——它负责在系统启动时,决定让谁进来、怎么进来。

Bootloader 是 MCU 上电后第一个执行的程序。它的任务很简单:检查条件,然后跳转到应用程序。但就这么简单的任务,里面门道可不少。

我举个例子。你在做 OTA 升级时,Bootloader 要干这些事:

  1. 检查有没有新固件下载完成
  2. 如果有,校验完整性(CRC、签名等)
  3. 把新固件从下载区搬到执行区
  4. 跳转到新固件执行

如果没有 Bootloader,你想想看,MCU 上电后直接跑应用程序,那你怎么升级?只能通过调试器烧录。这在产线上还行,但远程升级?门儿都没有。

我的经验:Bootloader 的代码要尽量精简。我曾经见过一个 Bootloader 写了 64KB,结果 Flash 不够用,还得压缩应用程序的空间。Bootloader 只做一件事:引导。别往里塞太多功能。

2.3 什么是应用程序?

应用程序,就是用户真正关心的功能代码。比如控制电机、采集传感器数据、通信协议栈等等。它跑在 Bootloader 之上,由 Bootloader 跳转过来执行。

应用程序和 Bootloader 的关系,有点像「老板和前台」。前台(Bootloader)先到公司,开门、开灯、检查设备,然后通知老板(应用程序)可以进来了。老板只管干活,不用管这些杂事。

在 TC3xx 平台上,应用程序通常放在 Flash 的高地址区域。Bootloader 放在低地址区域。为什么?因为 MCU 上电后默认从 0x80000000 开始执行,所以 Bootloader 必须放在那里。

注意:应用程序和 Bootloader 的中断向量表必须分开。应用程序启动时,要重新设置 VTOR 寄存器,指向自己的中断向量表。否则,中断来了,MCU 会跑到 Bootloader 的向量表里去,那就乱套了。

2.4 三者之间的关系

好,咱们把这三个角色串起来看。

角色 存储位置 执行顺序 主要职责
固件 Flash 全局 贯穿始终 提供底层驱动和运行时环境
Bootloader Flash 低地址 第1个执行 引导、校验、跳转
应用程序 Flash 高地址 第2个执行 实现用户功能

它们之间的关系,我用一句话总结:固件是土壤,Bootloader 是种子,应用程序是长出来的庄稼。

没有固件,芯片连基本的外设都用不了。没有 Bootloader,你没法远程更新庄稼。没有应用程序,你种地干嘛?

2.5 避坑指南

我曾经在项目里踩过一个坑:Bootloader 和应用程序使用了同一个全局变量,结果升级后变量值被覆盖,系统直接死机。后来我学乖了——Bootloader 和应用程序的链接脚本必须严格隔离,共享数据通过固定的 RAM 区域传递,别用全局变量。

还有一点:Bootloader 里不要用复杂的库函数。比如 printf、malloc 这些,能不用就不用。为什么?因为 Bootloader 的代码量要小,越小越稳定。你想想看,Bootloader 出问题了,连升级都做不了,那车就真成砖了。

核心原则:

  • Bootloader 只做引导,不做业务
  • 应用程序不碰 Bootloader 的 Flash 区域
  • 固件升级时,Bootloader 必须保持可执行
  • 中断向量表必须独立配置

2.6 小结

这一章的内容,说白了就是让你搞清楚三个角色的分工。很多新手一上来就写应用程序,忽略了 Bootloader 的设计,结果到了 OTA 阶段才发现——根本没法远程升级。

我个人建议,做项目之前,先把这三者的 Flash 分区画清楚。哪块是 Bootloader,哪块是应用程序,哪块是下载区,哪块是备份区。画清楚了,后面的事情就顺了。

下一章,咱们聊聊 TC3xx 的 Flash 架构和分区策略。嗯,那才是真正动手的地方。