You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

双扇区STM32动态固件更新的Bootloader适配方案咨询

STM32双应用扇区OTA固件适配问题与解决方案

项目背景

基于STM32开发带Bootloader的固件更新系统,设备包含两个应用扇区(APP1、APP2),用于存储同一应用的不同版本。OTA升级逻辑为:当前运行APP1时,将新版本写入APP2;当前运行APP2时,写入APP1。复位后Bootloader通过读取两个扇区上方的元数据,选择版本较新的应用启动。

核心问题

项目仅编译单固件镜像,但链接脚本硬编码绑定到APP1或APP2的存储地址,导致固件与特定存储区域强绑定,无法动态适配所在的扇区。

初步思路

考虑使用两个不同的链接脚本编译两次,生成对应APP1和APP2的固件,OTA前根据当前运行扇区选择对应版本。但希望了解是否存在Bootloader动态配置应用的方法,或更优的单镜像适配双扇区方案。

附:内存映射

/* Specify the memory areas */
MEMORY
{
   /* Bootloader region */
    FLASH_BOOTLOADER(rx) : ORIGIN = 0x08000000, LENGTH = 32K

    /* METADATA region for App1 */
    FLASH_METADATA_APP1 (r) : ORIGIN = 0x08008000, LENGTH = 1K 

    /* Application 1 region */
    FLASH_APP1 (rx) : ORIGIN = 0x08008400, LENGTH = 363K

    /* METADATA region for App2 */
    FLASH_METADATA_APP2 (rx) : ORIGIN = 0x08063000, LENGTH = 1K

    /* Application 2 region */
    FLASH_APP2 (rx) : ORIGIN = 0x08063400, LENGTH = 363K

    /* Eeprom section */
    FLASH_EEPROM (rx) : ORIGIN = 0x080BE000, LENGTH = 8K

    /* Reserved region */
    FLASH_RESERVED (r) : ORIGIN = 0x080BF000, LENGTH = 60K

    /* Wireless stack region */
    FLASH_BLE_STACK (x) : ORIGIN = 0x080CE000, LENGTH = 120K

    /* FUS region */
    FLASH_FUS (rx) : ORIGIN = 0x080EC000, LENGTH = 16K

    /* RAM region */
    RAM (xrw) : ORIGIN = 0x20000008, LENGTH = 0x2FFF8
   
    RAM_SHARED (xrw) : ORIGIN = 0x20030000, LENGTH = 10K
}

附:链接脚本片段

/* The startup code goes first into FLASH */
.isr_vector :
{
  . = ALIGN(4);
  KEEP(*(.isr_vector)) /* Startup code */
  . = ALIGN(4);
    
} >FLASH_APP1

解决方案

方案1:单镜像位置无关代码(PIC)适配

  • 核心逻辑:让应用代码脱离绝对地址依赖,运行时自动识别所在扇区并调整运行环境
  • 实现步骤:
    1. 修改链接脚本,将应用链接到虚拟基地址(如0x00000000),开启编译器位置无关代码选项(GCC需添加-fPIC或-fpic)
    2. 在应用启动阶段(如启动文件的复位处理函数中),读取当前PC值,判断其落在APP1或APP2的地址范围内,计算自身所在扇区的基地址
    3. 动态设置中断向量表偏移:通过SCB->VTOR寄存器,将向量表地址设置为当前应用扇区的起始地址
    4. 所有访问自身Flash数据的代码,均通过相对地址计算(如使用段属性标记数据,通过偏移量访问)
  • 注意:部分STM32型号对VTOR的设置有对齐要求(如必须是0x200的倍数),需确保扇区起始地址符合要求;外设初始化代码若有硬编码Flash地址,需改为相对偏移。

方案2:Bootloader动态重定位应用

  • 核心逻辑:由Bootloader负责调整应用的运行环境,让应用无需感知自身所在扇区
  • 实现步骤:
    1. 编译应用时,链接脚本使用虚拟地址或统一基地址(无需绑定到APP1/APP2)
    2. Bootloader读取选中应用的元数据,获取其所在扇区的基地址
    3. 设置SCB->VTOR为该应用扇区的起始地址,然后跳转到应用的复位向量
    4. 若应用需要访问自身Flash数据,Bootloader可将应用基地址写入共享RAM区域,应用启动后从该区域读取基地址并计算实际访问地址
  • 优势:无需修改应用的编译流程,仅需Bootloader增加少量逻辑,兼容性较好。

方案3:双镜像编译(初步思路优化)

  • 核心逻辑:编译两个分别绑定APP1和APP2的固件镜像,OTA时根据当前运行扇区选择对应镜像下载
  • 实现步骤:
    1. 复制现有链接脚本,生成两个版本:linker_app1.ld(绑定FLASH_APP1)和linker_app2.ld(绑定FLASH_APP2)
    2. 在编译脚本(Makefile)或IDE工程中添加两个编译目标,分别使用不同的链接脚本,生成两个独立的固件镜像
    3. OTA过程中,Bootloader先读取当前运行的应用扇区,然后请求对应版本的固件镜像,写入另一扇区
  • 优势:实现最简单,无需修改应用核心代码,兼容性最好,适合对开发复杂度要求低的场景。

内容的提问来源于stack exchange,提问作者WITC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 01:21:02