niepangu 2025-09-02 09:06 采纳率: 37.5%
浏览 6

如何更新产品的Bootloader程序

嵌入式设备中设计一个Bootloader,通过串口等方式升级升序的方法非常方便,例如常见的STM32芯片,

但有一个困惑,Bootloader程序其实也是一个应用程序,它的功能就是接收串口或者其他接口的数据然后写入Flash更新用户程序, 如果Bootloader程序里边出现bug或者需求变化需要更新,怎么实现更新Bootloader程序呢?

  • 写回答

4条回答 默认 最新

  • 檀越@新空间 2025-09-02 09:07
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    在嵌入式系统中,Bootloader 是一个非常关键的程序,它负责初始化硬件并加载用户应用程序。然而,Bootloader 本身也是一个程序,因此它也有可能出现 bug 或者需要更新。那么,如何更新 Bootloader 程序呢?这是一个常见的问题。


    一、为什么不能直接通过 Bootloader 更新自己?

    • Bootloader 的作用是加载用户程序(Application),而不是更新自身。
    • 如果 Bootloader 出现 bug,无法正常启动,就会导致设备无法运行。
    • 因此,必须设计一种机制,在不依赖当前 Bootloader 的情况下更新 Bootloader

    二、更新 Bootloader 的方法

    1. 使用双 Bank Flash(适用于 STM32 等支持双 Bank 的芯片)

    这是最常见且安全的方式:

    步骤如下:

    1. 将 Bootloader 分为两个部分:

      • Bank A(主 Bootloader):用于启动和加载用户程序。
      • Bank B(备用 Bootloader):用于接收新的 Bootloader 并更新到 Bank A。
    2. 使用跳转机制:

      • 启动时从 Bank A 运行 Bootloader。
      • 如果检测到需要更新 Bootloader,则跳转到 Bank B 执行升级逻辑。
    3. 通过串口或其他接口传输新 Bootloader 文件。

    4. 将新 Bootloader 写入 Bank A。

    5. 重启后,从 Bank A 加载新的 Bootloader。

    优点: 安全,不会因为更新失败导致设备无法启动。
    缺点: 需要支持双 Bank Flash 的 MCU。


    2. 使用外部存储(如 SD 卡、Flash 芯片等)

    如果 MCU 不支持双 Bank Flash,可以考虑使用外部存储来保存 Bootloader。

    步骤如下:

    1. 将 Bootloader 存储在外部存储(如 SD 卡或 SPI Flash)中。
    2. 在启动时,从外部存储加载 Bootloader 到内存中运行。
    3. 如果需要更新 Bootloader,只需更新外部存储中的文件即可。

    优点: 不受 MCU Flash 结构限制。
    缺点: 需要额外的硬件支持,可能增加成本。


    3. 使用“自举”方式(Bootloader 自身具备更新能力)

    某些 Bootloader 设计为具有自我更新能力,即:

    • 在运行时,可以接收新的 Bootloader 文件。
    • 将其写入 Flash 中的指定区域。
    • 然后重启,从新版本的 Bootloader 启动。

    ⚠️ 注意: 这种方式存在风险,如果更新过程中出错,可能导致 Bootloader 损坏,设备无法启动。


    三、推荐方案:双 Bank Flash + Bootloader 自更新机制

    具体实现步骤:

    1. 硬件配置:

      • 使用支持双 Bank Flash 的 MCU(如 STM32F4/F7 系列)。
      • 确保 Bootloader 和 Application 分别位于不同的 Bank。
    2. Bootloader 功能:

      • 提供一个更新接口(如 UART、USB、CAN 等)。
      • 接收新的 Bootloader 文件。
      • 将其写入另一个 Bank。
      • 重启后,从新 Bootloader 启动。
    3. 代码示例(基于 STM32):

    // 假设我们使用 UART 接收 Bootloader 文件
    void UpdateBootloader(void) {
        uint8_t buffer[1024];
        int len = 0;
    
        while (len < BOOTLOADER_SIZE) {
            len += UART_Receive(buffer, sizeof(buffer));
            // 将 buffer 写入 Bank B 的 Flash 地址
            WriteToFlash(BANK_B_ADDRESS, buffer, len);
        }
    
        // 重启,从 Bank B 启动
        NVIC_SystemReset();
    }
    

    📌 注意: WriteToFlash() 必须使用 Flash 编程 API(如 STM32 的 HAL_Flash_Program())。


    四、注意事项

    • 备份原始 Bootloader: 在更新前,建议先备份原 Bootloader,防止更新失败导致设备损坏。
    • 校验机制: 在更新完成后,进行 CRC 校验,确保 Bootloader 文件完整无误。
    • 恢复机制: 如果更新失败,应能回退到之前的版本。

    五、总结

    | 方法 | 优点 | 缺点 | |------|------|------| | 双 Bank Flash | 安全,可回滚 | 需要支持双 Bank 的 MCU | | 外部存储 | 灵活,不受 MCU 限制 | 需要额外硬件 | | 自我更新 | 简单,无需额外硬件 | 风险高,易崩溃 |


    六、推荐做法

    优先选择:使用双 Bank Flash + Bootloader 自更新机制,这是目前最稳定、最常用的解决方案。

    如果你使用的是 STM32,可以参考官方提供的 STM32 Bootloader 示例项目,它们通常已经实现了这种机制。


    如有具体芯片型号或开发环境(如 Keil、IAR、STM32CubeMX),我可以提供更详细的代码示例。

    评论

报告相同问题?

问题事件

  • 创建了问题 9月2日