你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】SRAM 中的数据丢失

[复制链接]
STMCU小助手 发布时间:2022-2-21 19:51
问题:
* G( v, f( H1 b( d' R$ R6 r该问题由某客户提出,发生在 STM32F103VDT6 器件上。据其工程师讲述:在该公司的某型号产品的设计中用到了 STM32F103VDT6 器件,而其软件的设计采用了 IAP+APP 的架构。IAP 是一段 BOOT 程序,负责对硬件进行初始化以及在接到相关指令的情况下更新 APP 程序,而 APP 程序则负责对常规业务处理。在 STM32 启动后,IAP 首先运行。在初始化硬件之后,检查是否有更新 APP 的指令,如果有,则更新 APP,如果没有,则跳转到 APP。APP 对常规业务进行处理时,如果接到更新指令则复位STM32,以使程序的流程回到 IAP。在 IAP 和 APP 进行切换的过程中,需要相互传递一些数据。其软件的实现的方法是,发送方将数据写到 SRAM 的某个区域,接收方则到同一区域将数据读回。然而实测中发现,相关数据并未被正确的传递,而是丢失了。在整个切换过程中,STM32 并未掉电。
, l* ^  t' h( K8 ^( f
! Q8 `5 @' Z" B5 b5 T% C7 x+ O- t调研:
/ i5 _. U6 t& K1 E0 `. j  v检查其软件设计,了解到其所使用的开发工具为 Keil MDK,而 IAP 和 APP 分别由两个独立的软件工程所生成。进一步检查相关的代码,发现在 IAP 和 APP 中,用于数据传递的缓冲区定义相同,如表(一),而其 IAP 和 APP 的内存分配也相同,如表(二)
% C; \, _; L; ]& m. [9 y% B, O6 N3 J. U6 _/ b& c5 j
% i1 Y$ @3 Q9 _8 {. |
{}A4LW1}B98]L}NVYML3$V4.png
) ^- v; `# \5 b! s$ x; Q0 q6 L8 v8 o3 g! ]( f
JH~DR@XN8]8ROW2Z(32YOYB.png 1 r; D/ V+ j4 j* l' y

" ]2 _. G  x& M" Z9 F' \/ C& x, I对其软件加以分析:
2 Z; [. k3 R8 h; ^* n- j1. 编译两个工程,通过检查 map 文件确认 IAP 中定义的 IapToAppBuf 与 APP 中定义的IapToAppBuf 所分配的地址相同,都是 0x20000000 开始的内存区域。3 l( i6 w5 ~$ x6 W8 z* Z: n
2. 修改 IAP 的代码,使其在缓冲区内填满 0x55。修改 APP 的代码,使其在进入 main()函数后打印整个缓冲区。编译两个工程后,全部加载到 STM32。运行结果表明,APP 从缓冲区内读出的数据匀为零,而不是 0x55。  i3 P) |. Q: {, x; m! d* j
3. 修改 APP 的代码,使其在缓冲区内填满 0x55,然后复位 STM32。修改 IAP 的代码,使其进入main()函数后,打印缓冲区内的数据。结果表明,IAP 从缓冲区内读出的数据匀为零,而不是 0x55。修改 APP 的内存分配,如表(三),然后重复“分析”中的测试:7 C# ~" q$ U5 E: Y* d! }
$ j: H! l* p2 s
0 h3 e" ]8 K% d( d
BZ]YZ@1ZW{7JZ8I[G)V])78.png
4 b) u6 L. B0 m7 I1 V3 F8 `* T1 r6 |& |) g- B2 _
1. 重复测试(2),结果表明 APP 读出的数据为 0x55,是 IAP 放在缓冲区内的数据。
5 u2 V% ^6 C/ n. D2. 重复测试(3),结果表明 IAP 读出的数据匀为零,不是 APP 放在缓冲区内的 0x55。
8 U$ A; v' f% ?! g$ C7 F7 O+ ?修改 IAP 的内存分配,如表(三),然后重复“分析”中的测试:
" L8 w7 |, T, w6 i# u2 g& A1. 重复测试(2),结果表明 APP 读出的数据为 0x55,是 IAP 放在缓冲区内的数据。# Z3 l/ c$ L  L, A2 F7 `+ |
2. 重复测试(3),结果表明 IAP 读出的数据为 0x55,是 APP 放在缓冲区内的数据。$ E( P3 V, f, _

3 m! i& z2 N8 W9 k0 k, X; ]8 p) l3 G4 p0 c# D' r
结论:3 b% s3 D% |1 S% _' s2 k0 [
   为缓冲区分配的内存未加 UNINIT 属性控制,导致 C 语言初始化程序对该区域进行了清零处理,造成存放在其中的数据丢失。8 I2 u+ f3 ^& D: G' P$ G
   
# W2 g1 Z; h- d2 x( V
1 N1 z3 g" }7 y0 N, O# t$ t处理:
/ A& I& B0 H/ t7 q$ u   修改内存分配,将该内存区域加上 UNINIT 属性。
/ [' ?# }3 N& H   
" _# f# X. x  g) \. {3 W6 ~
% g& @+ @$ ?7 ^/ R' _( t建议:
# h( {$ B2 O, ?4 u2 }   C 语言初始化程序是由 C 语言开发工具中的链接器(Linker)加到应用程序当中的一段程序,它早于main()函数得以执行,完成对 C 语言运行环境的初始化工作。这段程序会对所有用到的且没有UNINIT 属性的内存做清零处理。所以,要使得某段内存区域的数据保留给 main()函数而不被清除,需要对这段内存加上 UNINIT 属性。当然,也可以把一段内存区域隐藏起来,不交给 C 语言初始化程序管理,如表(四)所示。其中 0x20000000 – 0x20000063 这段内存没有被分配,于是 C 语言初始化程序不知道它的存在,也就不会对它做任何的处理。在应用程序中,可以通过指针来访问这一区域,从而实现通过这段内存向 main()函数传递数据功能。5 ~. u8 V0 v, p6 I! p% ~4 h
3 C# i8 |' t3 O2 K' V! ?

( }2 R1 H* e9 J _T%)L`M]MYZ5SM294JG5T54.png
' D0 H0 G: N  p2 F& K% z4 A+ W; ]
! a2 |3 F& x. c  s  c" Y: t
赞 收藏 评论0 发布时间:2022-2-21 19:51

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版