什么是 Bootloader?怎么把它移植到 STM32 上?

发布于:2025-07-13 ⋅ 阅读:(17) ⋅ 点赞:(0)

一、Bootloader 是啥?它都干了些啥?

想象一下你的 MCU(比如 STM32)是一个小机器人,上电之后第一件事,它不会立马开始“干正事”(运行你的主程序),而是先去运行一个“开场引导程序”——这就是 Bootloader。

它主要负责下面这些事:

  • 启动最基础的硬件:比如时钟、串口、Flash 这些,像是“穿衣洗脸”。
  • 判断要不要升级程序:比如你按了个按钮、发了个串口命令,它就不跳到主程序,而是“停在门口”,准备接收新程序。
  • 接收并写入新程序:它能从串口、USB、CAN、SD 卡等接收固件,然后擦掉旧程序,把新程序烧进去。
  • 最后跳转到主程序:一切准备就绪,它就把控制权交给你写的主程序,让它正式运行。

通俗讲,它就像是**“程序界的门房”**,开门、分发信件(固件)、开灯、安排进屋(跳转),全由它负责。


二、Bootloader 跟主程序的位置是怎么安排的?

在 STM32 中,Flash 是按地址划分的。一般我们这样安排:

Bootloader 区域: 0x08000000 ~ 0x08003FFF
主程序区域(App): 0x08004000 ~ Flash 结尾

也就是说,Bootloader 占前面 16KB 的空间(你可以设更多),主程序从后面接着跑。它们不会互相干扰。

Bootloader 的典型流程就像这样:

int main(void)
{
    HAL_Init();                    // 初始化硬件
    SystemClock_Config();         // 配置时钟
    MX_USART2_UART_Init();        // 初始化串口

    if (check_upgrade_flag())     // 判断是否需要升级
    {
        enter_upgrade_mode();     // 进入升级模式
    }

    jump_to_application();        // 跳到主程序区运行
}

三、Bootloader 做事情的重点是啥?

1. 固件怎么接收?

它可以从很多“入口”接收程序,比如:

  • 串口(UART)
  • USB(DFU 模式)
  • CAN、I2C、SPI
  • SD 卡、外部 Flash

接收过程里会做这些事:

  1. 检查程序是不是完整(比如校验 CRC)
  2. 擦掉旧程序(把 App 区的 Flash 擦了)
  3. 把新程序一点点写进去
  4. 写完了,打个勾:“升级完成了!”

2. 怎么跳转到主程序?

最关键的是要设置好跳转地址和栈指针。示例代码如下:

#define APP_ADDR 0x08004000  // 主程序起始地址

typedef void (*pFunction)(void);
pFunction JumpToApplication;
uint32_t JumpAddress;

HAL_DeInit();               // 关闭外设
__disable_irq();            // 禁用中断

JumpAddress = *(__IO uint32_t*)(APP_ADDR + 4);
JumpToApplication = (pFunction)JumpAddress;

__set_MSP(*(__IO uint32_t*)APP_ADDR); // 设置栈
JumpToApplication();                  // 跳转!

要注意:

  • 0x08004000 第一个 4 字节是主程序的栈指针(MSP)
  • 第二个 4 字节是主程序的启动地址(Reset_Handler)
  • 跳转之前要把中断关掉、外设关掉,不然主程序容易“误会”你还没交接完

四、怎么把 Bootloader 移植到 STM32 上?

如果你自己写 Bootloader,要让它配合你的主程序跑起来,大概分这几步:

Step 1:规划 Flash 分布

比如我们规划:

  • Bootloader 占 0x08000000 ~ 0x08003FFF(16KB)
  • 主程序从 0x08004000 开始

这样你就得去你的 App 工程里修改启动地址,不然你主程序会被烧到 Bootloader 区,冲突了。

Step 2:写 Bootloader 的功能

你得实现:

  • 初始化串口
  • 收数据 + 校验
  • 擦除 Flash
  • 写入新固件
  • 跳转主程序

Step 3:改主程序的配置

  • 启动文件 .s 或 .ld 文件中,把起始地址改成 0x08004000
  • 设置中断向量表地址偏移:SCB->VTOR = 0x08004000;

不改这些,你的主程序可能跳转不了,也收不到中断。

Step 4:验证!

Bootloader 烧进去 → 用它烧主程序 → 看能不能正常跳转、运行

记得保留串口 printf 打印,出问题好排查。


五、移植过程中常见的“坑”和解决方案

问题 原因
跳转失败 中断没关 / 地址没设对 / VTOR 没设置
Flash 写失败 没解锁 / 写保护 / 地址错误
主程序不跑 启动文件地址没改 / 向量表没偏移
烧完程序没反应 没跳转、程序错烧、校验失败

解决方法:

  • 多用串口打印调试信息
  • 多测试单步跳转和Flash写入
  • 主程序先写一个最小的 Blinky(闪灯)测试跳转是否成功

网站公告

今日签到

点亮在社区的每一天
去签到