如何在软件复位后保留指定RAM区域的数据

文章目录

    • 配置介绍
      • 启动文件
      • 链接文件
      • 主程序
    • 例程测试
      • 环境搭建
      • 功能描述
      • 测试现象
    • 注意事项
      • 1. 另一种实现RAM retention功能的方式
      • 2. 自定义RAM区域的地址问题
      • 3. bool类型变量使用RAM retention功能
      • 4. 不使用调试模式进行测试
    • 参考资料
    • 例程分享

在bootloader时,通常需要单独开辟一块区域用来存放一些变量,并且希望这些变量在发生软件复位(boot和app互相跳转)时不被初始化,这些变量一般用来存放跳转boot的原因(正常上电启动或者从app跳转boot)等信息。对于这种变量的存放方式有两种,一种是使用MCU自带的(模拟/真实)EEPROM,一种是针对变量所在的区域做一些修改,使得这些RAM区域在软件复位时不进行初始化,S32K1中这种功能称为RAM retention。前一种方式之前介绍过,如下链接: 《巧用S32K的模拟EEPROM功能标定参数》 ,本文以S32K144为例,介绍第二种方式。

配置介绍

下面从启动文件,链接文件以及主程序中的设置三方面介绍实现RAM retention的方法。

启动文件

如果对S32K144的启动过程不是很清楚,建议看一下胡工的这篇文章:

《浅谈嵌入式MCU软件开发之S32K1xx系列MCU启动过程及重映射代码到RAM中运行方法详解 》

首先,需要关闭SRAM的ECC初始化操作,因为该操作会修改SRAM数据。同时,关闭SRAM的ECC初始化的操作需要在软件复位后执行,如下红框是修改部分:

如何在软件复位后保留指定RAM区域的数据_第1张图片

0x40048004是寄存器CHIPCTL的地址,在进入软件复位之前会操作该寄存器,后面主程序部分会有描述,和此处对该寄存器的值进行判断能够对应上。

链接文件

如果对S32K144的链接文件不是很清楚,可以看一下如下这篇文章:

《S32DS for ARM 2018.R1 链接文件(linker file)学习笔记 》

接着在链接文件中设置两个自定义的地址,用来保存需要实现RAM Retention的变量。

如何在软件复位后保留指定RAM区域的数据_第2张图片
如何在软件复位后保留指定RAM区域的数据_第3张图片

主程序

接着在主程序中使用关键字attribute修饰需要实现RAM retention功能的变量,如下所示:

__attribute__((section (".myRAML"))) uint8_t Led_Color_Flag = 0x00;
__attribute__((section (".myRAMU"))) uint8_t Buffer[10] = {0};

最后在调用软件复位函数之前将CHIPCTL的SRAML_RETEN和SRAML_RETEN两位置0,如下所示:

/*
 * This logic ensures that any attempted access to SRAM is blocked
 * after these bits are written,
 * thereby preventing memory corruption during reset assertion.
 * */
SIM->CHIPCTL &= ~SIM_CHIPCTL_SRAMU_RETEN_MASK;
SIM->CHIPCTL &= ~SIM_CHIPCTL_SRAML_RETEN_MASK;
/*SW software*/
SystemSoftwareReset();

结合参考手册CHIPCTL寄存器和SRAM retention章节的描述,将这两位置为0后,可以让RAM的数据在复位过程中不在篡改,同时在复位之后需要改写为1。

如何在软件复位后保留指定RAM区域的数据_第4张图片

如何在软件复位后保留指定RAM区域的数据_第5张图片

至此,主要的修改注意点已经描述完毕。

例程测试

环境搭建

  • 开发板:S32K144EVB-Q100
  • 开发环境:S32DS for ARM 2.2

功能描述

为了测试RAM retention功能,我定义了两组变量,一组变量使用attribute修饰,使之固定到自定义的区域,一组变量不做修饰,会被放到.bss段(查看map文件可知)。如下图所示:

image-20220206143626611

然后在主函数中判断一下变量的值是否为期望值,如果不是,就亮一段时间的红灯,同时对变量赋值,然后进行软件复位,然后再次判断变量的值是否为期望值,如果是,就一直亮绿灯。主要代码如下:

如何在软件复位后保留指定RAM区域的数据_第6张图片

测试现象

在下图红框处打上断点,当完成软件复位之后再次执行到该语句时,查看变量,发现处于自定义RAM区域的变量保留了之前的值,而处于bss段的变量被初始化为0了。

如何在软件复位后保留指定RAM区域的数据_第7张图片

退出调试模式,重新上电,LED先亮几秒红灯,然后亮绿灯,且一直保持。重复几次,现象一样,符合预期。

注意事项

笔者在调试RAM retention功能时,总结了一些注意事项,分享给大家。

1. 另一种实现RAM retention功能的方式

想要使用RAM retention功能,不一定需要修改ld文件,也可以按如下方式进行:

  • 定义变量如下:
#define SRAMU 0x20006000u
#define SRAML 0x1FFF8600u
uint32_t Temp[2] = {0};
  • 主函数的实现方式如下:

如何在软件复位后保留指定RAM区域的数据_第8张图片

2. 自定义RAM区域的地址问题

在ld文件设置自定义地址时,增加了NOLOAD关键字,主要是为了生成的烧录文件(S19/HEX/BIN)不包含自定义RAM区域的地址,否则无法使用量产工具下载程序。

3. bool类型变量使用RAM retention功能

如果将需要使用RAM retention功能的变量定义为bool类型,在掉电之前该值为true,会发现重新上电之后,该变量的值仍为true。但是,如果掉电之前该值为false,重新上单之后,该值为true。发生该现象的原因笔者并未找到,建议尽量不使用bool类型变量实现该功能。

如果非要使用bool类型,初始化值使用true,主程序中赋值为false,具体如下面两张图,测试结果是OK的。
image-20220206161429733
如何在软件复位后保留指定RAM区域的数据_第9张图片

4. 不使用调试模式进行测试

在测试该例程时,发现重新上电进入debug模式时,自定义区域的变量已经变成了期望值(上电之后并未进行软件复位),和预期结果不符合。但是脱离调试模式,进行的测试结果又是符合预期的。建议读者测试RAM retention功能时离线测试,debug模式下会出现意料之外的情况。

参考资料

  1. Example S32K144 RAM Retention S32DS.R1 - NXP Community
  2. S32K1xxRM Rev12.1, 02/2020,官网已是最新的Rev14
  3. 老王的朋友圈截图

例程分享

本文所使用的例程分享如下:
链接:https://pan.baidu.com/s/155Ok2mU51AMBsaQ9n-XFGg
提取码:89vy

你可能感兴趣的:(S32K1xx,S32K144,NXP,RAM)