打印
[信息]

【实战经验】SRAM 中的数据丢失

[复制链接]
1979|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 香水城 于 2017-8-17 14:24 编辑

SRAM 中的数据丢失

问题:
该问题由某客户提出,发生在 STM32F103VDT6 器件上。据其工程师讲述:在该公司的某型号产品的设 计中用到了 STM32F103VDT6 器件,而其软件的设计采用了 IAP+APP 的架构。IAP 是一段 BOOT 程序, 负责对硬件进行初始化以及在接到相关指令的情况下更新 APP 程序,而 APP 程序则负责对常规业务 处理。在 STM32 启动后,IAP 首先运行。在初始化硬件之后,检查是否有更新 APP 的指令,如果 有,则更新 APP,如果没有,则跳转到 APP。APP 对常规业务进行处理时,如果接到更新指令则复位 STM32,以使程序的流程回到 IAP。在 IAP 和 APP 进行切换的过程中,需要相互传递一些数据。其软 件的实现的方法是,发送方将数据写到 SRAM 的某个区域,接收方则到同一区域将数据读回。然而实 测中发现,相关数据并未被正确的传递,而是丢失了。在整个切换过程中,STM32 并未掉电。

调研:
检查其软件设计,了解到其所使用的开发工具为 Keil MDK,而 IAP 和 APP 分别由两个独立的软件工 程所生成。进一步检查相关的代码,发现在 IAP 和 APP 中,用于数据传递的缓冲区定义相同,如表
(一),而其 IAP 和 APP 的内存分配也相同,如表(二)


对其软件加以分析:
1. 编 译两 个 工程 , 通 过 检 查 map 文件 确认 IAP 中定 义 的 IapToAppBuf 与 APP 中 定义 的 IapToAppBuf 所分配的地址相同,都是 0x20000000 开始的内存区域。
2. 修改 IAP 的代码,使其在缓冲区内填满 0x55。修改 APP 的代码,使其在进入 main()函数后打 印整个缓冲区。编译两个工程后,全部加载到 STM32。运行结果表明,APP 从缓冲区内读出的数据匀为 零,而不是 0x55。
3. 修改 APP 的代码,使其在缓冲区内填满 0x55,然后复位 STM32。修改 IAP 的代码,使其进入 main()函数后,打印缓冲区内的数据。结果表明,IAP 从缓冲区内读出的数据匀为零,而不是 0x55。 修改 APP 的内存分配,如(三),然后重复“分析”中的测试:

1. 重复测试(2),结果表明 APP 读出的数据为 0x55,是 IAP 放在缓冲区内的数据。
2. 重复测试(3),结果表明 IAP 读出的数据匀为零,不是 APP 放在缓冲区内的 0x55。 修改 IAP 的内存分配,如表(三),然后重复“分析”中的测试:
1. 重复测试(2),结果表明 APP 读出的数据为 0x55,是 IAP 放在缓冲区内的数据。
2. 重复测试(3),结果表明 IAP 读出的数据为 0x55,是 APP 放在缓冲区内的数据。

结论:
为缓冲区分配的内存未加 UNINIT 属性控制,导致 C 语言初始化程序对该区域进行了清零处理,造成 存放在其中的数据丢失。

处理:
修改内存分配,将该内存区域加上 UNINIT 属性。

建议:
C 语言初始化程序是由 C 语言开发工具中的链接器(Linker)加到应用程序当中的一段程序,它早于 main()函数得以执行,完成对 C 语言运行环境的初始化工作。这段程序会对所有用到的且没有 UNINIT 属性的内存做清零处理。所以,要使得某段内存区域的数据保留给 main()函数而不被清除, 需要对这段内存加上 UNINIT 属性。当然,也可以把一段内存区域隐藏起来,不交给 C 语言初始化程 序管理,如表(四)所示。其中 0x20000000 – 0x20000063 这段内存没有被分配,于是 C 语言初始 化程序不知道它的存在,也就不会对它做任何的处理。在应用程序中,可以通过指针来访问这一区 域,从而实现通过这段内存向 main()函数传递数据功能。



对应的PDF:SRAM 中的数据丢失
更多实战经验请看:【ST MCU实战经验汇总贴】



沙发
mmuuss586| | 2015-8-3 19:35 | 只看该作者

学习了;

使用特权

评论回复
板凳
309030106| | 2015-8-3 22:13 | 只看该作者
为缓冲区分配的内存未加 UNINIT 属性控制,导致 C 语言初始化程序对该区域进行了清零处理,造成 存放在其中的数据丢失。学习了

使用特权

评论回复
地板
戈卫东| | 2015-8-4 01:05 | 只看该作者
不安全的方案。。。。。。。。

使用特权

评论回复
5
myxiaonia| | 2015-8-4 08:18 | 只看该作者
如果iap和app传递的参数数据量不是很大,可以使用后备域寄存器传递参数,这样就不需要修改默认的内存区属性等

我就是这么干的

使用特权

评论回复
6
冰河w| | 2015-8-4 09:21 | 只看该作者
修改内存分配,将该内存区域加上 UNINIT 属性,还不会用,收藏先

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:意法半导体(中国)投资有限公司
简介:STM32技术专家

596

主题

17097

帖子

287

粉丝