基于stm32的OTA Boot逻辑

0 阅读1分钟

       对于ota大家应该都因该很熟悉,比如说智能语音音响手机升级等。看千差万别实际有些内容大同小异。本次我们针对stm32进行讲解

       对于ota来说一般来说分为两个部分boot+app,app比较复杂,下一篇文章再说,本次们就得先把最底层的“看门人”——Bootloader(简称 Boot)给整明白。

       很多人觉得 Boot 只是个引导程序,几行代码就完事了,但实际上,它是整个固件更新过程中最稳的一道防线。如果 App 升级挂了,我们还能靠 Boot 重来;如果 Boot 挂了,那就只能严重客诉了😂😂😂——J-Link 拆机或者返厂了。

一、 Bootloader 的核心逻辑:

在 STM32 中,Bootloader 本质上是一个独立于 App 的小工程(也可以理解为是运行其他功能的平台),它驻留在 Flash 的起始地址(通常是 0x08000000)。它的核心任务只有三个:

  1. 判断:是直接跳到旧的 App 运行,还是开始更新固件?或者是升级报错。

  2. 搬运:把存储在外部(如 SD卡or SPI Flash)或暂存在备份区的固件搬到 App 运行区。

  3. 跳转:交出 CPU 的控制权,跳转执行 App。

二、 内存布局(Memory Layout)

做 OTA 之前,你必须做一份关于Flash资源分布的内存图。以 STM32F103 为例,我们通常把内部 Flash 划分为以下几个区域:

区域名称

作用

典型起始地址

Bootloader

存放升级逻辑,永不更新

0x08000000

Flag Param

存放升级标志位(比如:是否有新固件)

0x08004000

Application

正常的业务代码运行区

0x08005000 (示例)

三、 Boot 升级的核心三步走

1. 标志位检查

Boot 启动后,第一时间不是跑 App,而是去读在参数区的标志位。

  • 如果标志位显示 UPDATE_FLG = 1,说明有新固件来了,乖乖开始搬运。

  • 如果标志位是 0,且 App 区代码校验通过,直接跳转。

2. 固件搬运与校验

本次工作主要是需要把加密或压缩的固件“解密/解压”并写到 App 区。

注意事项:在写 Flash 之前,一定要进行 app区全部擦除。STM32 的 Flash 只能把 1 变成 0,不擦除直接写,你的代码就会出现乱码和其他异常情况。

3. 跳转指令

这是最能体现嵌入式功底的地方,也是很多人跳转app失败的原因。跳转前需要完成四件事:

  1. 屏蔽全局中断__disable_irq();

  2. 清除 Pending 中断:防止有还没处理完的中断标志位影响 App。

  3. 关闭 Systick 定时器:这是很多人忽略的,Systick 是内核定时器,跳转后如果不关,它会继续跑。

  4. 设置栈指针__set_MSP(*(uint32_t *)APP_ADDR);

    /* 1. 声明函数指针 */ typedef void (*pFunction)(void); pFunction Jump_To_Application;

    /* 2. 检查 App 地址的首地址(通常是栈顶地址,应在 RAM 范围内) / if ((((__IO uint32_t*)APP_ADDR) & 0x2FFE0000 ) == 0x20000000) { /* 3. 找到 App 的 Reset_Handler 地址 (App 起始地址 + 4) */ uint32_t JumpAddress = (__IO uint32_t) (APP_ADDR + 4); Jump_To_Application = (pFunction) JumpAddress;

    /* 4. 这里的收尾工作至关重要 */
    HAL_RCC_DeInit();        // 恢复时钟到默认状态(HSI)
    HAL_DeInit();            // 关闭外设
    SysTick->CTRL = 0;       // 关闭 Systick
    __disable_irq();         // 关中断
    
    /* 5. 重新映射中断向量表(也可以在 App 的 SystemInit 里做) */
    SCB->VTOR = APP_ADDR;
    
    /* 6. 设置栈指针并跳转 */
    __set_MSP(*(__IO uint32_t*) APP_ADDR);
    Jump_To_Application();
    

    }

四、 开发注意事项

一个完整的产品的OTA Bootloader 必须具备极强的**容错性,**下面两项一定要注意:

  • 断电保护:如果搬运过程中突然断电,Boot 必须能识别出“固件不完整”,并停留在升级模式等待重传,而不是尝试运行一个“残废”的 App。

  • 版本回滚:如果新 App 运行崩溃,Boot 最好能自动检测并跳回备份区执行旧版本。