关于boot对app的校验

基础知识 :对单片机程序中.data、.bss和.text三种数据的解读   ;ARM C语言编程优化策略

UM2262_X_CUBE_SBSFU安全启动和固件更新软件入门

1、.bss段(Block Started by Symbol)

   BSS段通常是指用来存放程序中未初始化或者初始化为0全局变量静态变量的一块内存区域。特点是可读写的,在程序执行之前BSS段会被系统自动清0。。

  2、.data段(data segment)

   数据段通常是指用来存放程序中已初始化(非0)的全局变量的一块内存区域。数据段属于静态内存分配,特点是可读写的。

  3、.text段(code segment/text segment)

   代码段通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,通常属于只读,在代码段中也可能包含一些只读的常数变量

2 为防止非赋值的变量被系统清零,可以用两种方法:主要用于参数的掉电存储(软复位设置保持RAM的供电),

MDK平台下Nordic系列芯片Noinit RAM的设置和应用探讨

应用场景的一些探讨:

  • 在某些不掉电场景下代替flash存储达到变量的保持功能

这个功能可以配合flash存储,在短期内以Noinit RAM保持数据,在关键节点再将数据写进flash,以达到减少flash擦写次数的操作次数(特别是Nordic在协议栈操作下,flash写操作容易失败的情况下)。

  • 系统的DEBUG定位

系统出现硬件错误的时候往往会进入到harfault中断服务线程,此时可以将系统进入harfault前的PC指针和一些详细的DEBUG信息写入Noinit RAM保存起来,等到复位启动后也可以将错误的DEBUG信息拿出来分析。

  • 模拟RTC实时时钟的可记忆寄存器

这个用法下,RTC几乎可以不受复位的影响。

  • 防止某些需要保持的数据在复位下不丢失

如果没有任何flash存储方式,可以尝试使用Noinit RAM代替其功能,在某些场景很实用

  • 检测一个系统是否是人为复位还是意外硬件复位

人为复位之前,Nonit RAM写入某个非0xff的特定值,如果是人为操做复位,则复位后的变量是对应的特定值。如果是意外硬件复位,则就可以通过Nonit RAM检查出来

  • __attribute__((section("no_initialized"))) int i, j;
  • #pragma arm section  zidata = "non_initialized"
    /* uninitialized data in non_initialized section 
     * (without the pragma, would be in .bss section by default) 
     */
    int i, j; 
    #pragma arm section zidata /* back to default (.bss section) */
    int k = 0, l = 0; /* zero-initialized data in .bss section */
  •  

     

  •  在ram里面设置noinit的范围,如何有bootload时,需要相同的设置,

    将RAM映射到0x2000FFF0地址,也就是Noinit RAM部分
    #define __noinit__ __attribute__((at(0x2000FFF0)))   
    __noinit__ u32 noinit_data;
  • debug数据可以保持,system off唤醒后,数据改变有人说需要设置ram供电。

后备寄存器

  STM32共有42个16位后备寄存器,可以用来存储84个字节的用户数据。而所谓的后备寄存器,并不是真正的EEPROM。当VDD电源被切断,VBAT仍然保持供电,后备寄存器的内容才不会丢失。

​在需要使用BKP寄存器时,需要先使能

IAP中的校验:

  bootload利用eeprom/flash的一个变量来判断是否需要IAP升级的隐患,当APP存在看门狗,加入升级过程或其它原因APP出现问题时,系统会在《引导--引导程序检测到不需要IAP--跳转到应用程序--看门狗咬死--复位--引导》进入死循环,系统因为无法识别这种情况所以必须工程师亲自去现场解决。通过禁止系统启动时的变量初始化。在BootLoader与应用程序,都在同一个地址定义相同的变量,在非断电初始化的时候,此变量是不会复位的。在BootLoader中每初始化1次加1,在app中程序正常运行的地方清零。如果出现上述死循环超过一定次数,bootload就认为app出现问题,进行重新iap.

嵌入式程序中,为了增加对升级文件的校验,通常会在boot中对升级的bin文件读取一部分进行校验,通过则说明文件可靠否则丢弃。

具体办法:在keil的启动汇编文件定义一个段,然后在link.sct中将其加载上去,

eg1 :在起始0地址添加,缺点是因为起始0地址所以没有boot,app是不能单独启动的。

 

 

 

 eg:利用中断向量表中的缺省(DCD后面为0)的部分进行校验

 引申阅读:STM32启动文件详解,  STM32F4的sct文件理解STM32高级开发(8)-链接器与启动文件gcc链接脚本和启动文件详解,《The GNU linker》

将变量和函数存在指定位置:__attribute__ ((attribute-list))

attribute-list:

  • at addr存储在指定位置(flash :不小于0x08000000;RAM:不小于0X20000000) 
  • section "name"存在指定的段
  • aligned (n):指定对齐方式,同时要考虑编译器平台的最小的字节对齐
  • (__packed__):内存约束

__attribute__ ((packed)) 的做用就是告诉编译器取消结构在编译过程当中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法(一大特点)。

packed属性:使用该属性可使得变量或者结构体成员使用最小的对齐方式,即对变量是一字节对齐,对域(field)是位对齐

  • __attribute__函数属性(Function Attribute):
  • 变量属性(Variable Attribute)
  • 类型属性(Type Attribute)
posted on 2022-02-14 19:45  杰瑞鼠  阅读(598)  评论(0编辑  收藏  举报