1、问题背景
客户基于 STM32Cube 包下的 SBSFU 示例工程(STM32Cube_FW_U5_V1.2.0ProjectsB-U585I-IOT02AApplicationsSBSFU)开发,程序中从 Boot 程序跳转到 Loader 程序是通过检测 UserButton 是否按下或者 Appli 程序是否为空来决定是否跳转到 Loader 程序。但客户现实的应用场景是,需要在 APP 中触发从 Boot 程序跳转到 loader 程序。这就需要在 Boot 工程中添加一个每次复位都能保持原来值的变量,用来标记是否需要进入到 loader 程序中。客户使用的 IDE 为 STM32CubeIDE, 自己尝试新增这个变量,但一直失败。我这里帮客户弄好后,特整理成文档,以供后续有类似需求的客户借鉴。
2、问题背景知识
2.1. 三种全局变量介绍
很多用户以为全局变量只有两种,一种是带初始值的,比如 int a=100 ; 还有一种是不带初始值的,如 int b ; 编译器在为这两种变量编译时,代码中会自动(如 IAR)或半自动(如STM32CubeIDE)为其生成一些 “拷贝数据”的代码,在 MCU 复位时,代码会将数据从flash 拷贝到内存中(带初始值的全局变量),或者将对应内存中的变量初始值设置为 0(不带初始值的全局变量)。这两种变量,在 MCU 复位并代码启动时,代码均会将变量对应内存地址的值修改。因此,很多用户均以为这是 MCU 的特性,其实并不是的,而是编译器干预的结果,本质上还是由代码来执行的结果。MCU 内存的值,只要 VDD 不掉电,在非上电复位的情况下,RAM 中的内容还是会保存之前的值的,只不过在复位且代码运行起来后,代码去修改了它。这部分代码往往隐藏在编译器生成的代码内,在常规 C 代码内是看不到的,从而使用户产生了 MCU 复位会自动清空 RAM 的假象。
其实,除了上述的两类变量,还存在第三种变量,即 MCU 复位后其值依然保留,代码不对其赋初始值,也不清空,仅仅每次复位(非上电复位)保持原来的值而已,这种变量即是此文要讲的内容。
另外,话说回来,STM32U5 的 SRAM 确实可以让 MCU 复位时通过硬件自动清空SRAM,此特性是通过选项字节来激活的,且默认情况下并未激活。这是其一,此外,像STM32F1, F2, F4 这类传统 MCU 芯片并没有此特性,它们在 MCU 复位时默认也是保留原始值的(代码对其赋了初始值或者清空)。有关 U5 的硬件自动清空 RAM 的特性后面我们将继续讲述。
2.2. SBSFU 工程介绍
STM32CubeU5 包下关于安全启动和安全固件升级(SBSFU)的示例工程其实有两个,
- 一个是 TF-M 的实现方案: STM32Cube_FW_U5_V1.2.0ProjectsB-U585I
IOT02AApplicationsTFM
- 一个是基于 MCU boot 开源项目的实现方案(可理解成 TFM 方案的简化版本):
STM32Cube_FW_U5_V1.2.0ProjectsB-U585I-IOT02AApplicationsSBSFU
SBSFU_Boot : 开源项目 MCU boot 移植后的参考实现。运行在安全区域。简称为 Boot 工程。
SBSFU_Appli:即 APP_S,和 APP_NS。对应安全和非安全 APP。
SBSFU_Loader:Loader 程序,也包含 Loader_S, Loader_NS 两部分。
本文要讨论的正是 SBSFU_Boot 工程。在此工程中添加一个 no_init 变量。