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

基于STM32的数据意外变化导致条件判断流程异常

[复制链接]
攻城狮Melo 发布时间:2023-12-7 15:29
01问题描述& `0 n: W9 c; ~% ^! e* l
用户使用的 MCU 型号是 STM32H750VB。
2 y6 D8 v, ~) I  |% N" a) O3 o) s, w/ q* d
在客户的代码中有多个条件语句,在条件里面的变量数值没有变化的情况下执行了条件里面的逻辑。有点类似如下 C 语句 :( v+ k* U  A% u0 \
9 R) `& Y$ I3 \8 a2 Q1 O; S8 c* C
微信图片_20231207152903.jpg
: H- z& C  A/ S

5 \: x/ v2 p' R4 u即变量 A 在明明没有变化且条件不满足的情况下, 程序运行时偏偏执行了条件内部的代码. 很奇怪的现象。一时很难判断是编译器的问题还是芯片问题.
, v" ^, q0 w+ z3 r/ p6 b. F8 A7 J7 a. h6 ]$ C; R) Z, V3 G- c. M
了解到客户的代码中使用了第三方库, xx.o 文件, 像这样的条件有 80 多个, 每次出现问题的具体变量并不是固定哪一个, 但是在大概 10 分钟内肯定会有其中一个出现执行逻辑问题。随意动一下代码问题就不出现, 或者出现的位置发生变化 ; 用 KEIL 编译器去设置断点, 想看该变量信息, 也会导致问题不再出现。
* y9 X  V5 n: Z& M) S- Y: Q! Q: L5 u5 @
02问题分析
' d% Z: Y" y; W9 ]) X一开始查看 errta sheet, 看到以下相关内容 :( h- [2 Q0 d! G" z% o
微信图片_20231207152900.jpg ! L5 [4 m8 \2 W& o) ~
6 }& L/ J3 T% |3 p' C4 ^
即怀疑问题跟 AXI SRAM 相关. 查看客户的这些变量, 确实是存放在 AXI SRAM 中. 由于任何修改代码都可能导致问题不再出现, 因此所有尝试须建立在不修改代码的基础上, 不然无法说明问题。- }# U4 D2 J0 J; T# c
" G' G: g' ^7 q. x6 x7 `1 F
于是让客户用 STM32CubeProgrammer 以 hot plug 模式连接 MCU, 按照勘误手册中 2.2.9 节所描述的 workaround 方式将 AXI_TARG7_FN_MOD 寄存器的 READ_ISS_OVERRIDE 位通过地址的方式直接修改 :
9 U& r0 R! B8 ]9 C4 W
2 h7 R; s! v) N) ^: t$ ]: E* V! _/ y
微信图片_20231207152856.jpg
$ b! K2 s: I$ r& c$ B- h) G

2 |! `1 x0 \! x4 ^; h5 Q/ ^结果发现并没什么效果. 于是排除了这种可能性.
- j; S6 I& E) E4 S6 K8 H
0 P6 p' v, t$ e! ]; t3 Y4 {/ C一开始也怀疑问题可能跟 Cache 有关, 于是测试下关闭 Cahce 会怎么样. 通过 KEIL 调试模式下,暂停住 CPU 运行, 然后手动关闭 D-Cache :) K/ q% G# G) T- B

5 u/ K- _& x9 Q4 \5 @) h
微信图片_20231207152853.jpg
  h  ]* ?; K, K! T8 f

- U( Q0 q  I: k" j. B& F; b+ v! D# }结果发现问题消失不见 ! 说明问题肯定跟 Cache 有关. + E  w. o, Q: Z  f3 A; w! n, D1 ?
+ n" {8 a* e6 @! v* R4 I, p9 e
但客户的代码最终肯定是不能关闭 Cache 的, 想到内核中有一个寄存器可以打开全局 Cache 的write throght 模式, 如下编程手册中的 CACR 寄存器的 FORCEWT 位 :
2 P* J# w0 s  i9 W: M
6 d9 a; I, ?# y7 W4 P
微信图片_20231207152849.jpg ) T( I  c" Y* \5 F  p' E

5 S8 j0 o/ ?. y$ \8 G$ i结果发现, 客户的代码本身就已经打开 :
7 M& A0 H. A3 I; C
7 }* o: d" |) @  q
微信图片_20231207152846.jpg
# X; q' L8 i; t; l4 a, L9 L6 ^
" ^1 y3 R5 F9 o- r; X看样子此模式与此问题无关. 得换个思路. 0 G* c( I4 H& U+ x' V

" y& L' E4 f) N" ^- o考虑到问题跟内存数据有关, 代码又不能动. 但是得想办法让内存中数据的位置动动, 看看会有什么效果 ?2 P( ~) e7 {( e# L' }

) [/ h/ u: c0 l2 l# X通过修改 KEIL 的链接配置文件.sct 文件, 将变量随意动动, 结果发现问题也会消失不见 ! 这说明,数据的地址跟问题绝对有关联.那么具体是哪些数据呢 ?+ a7 u! h3 t& A8 h6 M% f4 M
# S" N# k) \2 m9 o0 s
为了精确定位到与哪些变量有关, 查看 KEIL 生成的 map 文件, 按地址倒序将每个程序中所用到的.o 的对应变量逐个挪移动 DTCM RAM 中.
+ C9 g3 F2 y6 r/ r" Y% y0 [- o3 |$ E2 b( p3 x
微信图片_20231207152843.jpg
/ m5 q" T3 i' N6 U

& W6 _; \# E6 F为什么要倒序呢? 主要是因为, 假如先挪低地址的变量, 肯定会导致高地址的变量向低地址移动.这好比, 如果先抽掉下面的砖头, 那么上面的砖头会自动移动下面去. 假如先抽掉上面的砖头情况就不一样了, 下面的砖头还会保持不动. 这就是为什么先挪移上面的砖头的意义, 也就是所谓的倒序.
$ |' P* ^5 H. ?' U7 j  Q5 S" X. Z

4 l( b; `  ]$ a' ?$ |( U通过这种方式, 最终定位到问题跟 heap_4.o 文件以及用户使用到的第三方提供的 xx.o 文件中的ZI 数据有关. 只要保持这两种数据位置不变, 那么问题就可以稳定触发, 一旦其中任何一个位置有所变动, 问题就消失不见.% Y' I& w5 N, {  M5 g
! o  e( Q9 o- o  W% N& b
微信图片_20231207152840.jpg
8 v' w/ ~! [. @  L# ]# v$ {

+ A1 S- O" [2 h. [3 ?* w现在我们知道规律了, 那么只要固定好这两种 ZI 数据位置不变的情况下, 再去尝试修改代码, 结果发现, 此时修改代码不再会对结果产生影响! 换句话说, 现在可以自由修改代码了.
% _! l& z" Z9 h. s2 O  Q: Q- ]
: v. `+ k/ }# L: n7 M9 u6 z考虑到此问题与 Cache 有关, 于是接下来通过 MPU 设置将 heap_4.o 所在区域的 Cache 功能关闭, 结果发现问题消失.
7 K! U7 B7 b+ b4 d+ J
* E! g1 K2 w" J' T5 d9 w& w2 t
微信图片_20231207152836.jpg
- m( K) X: p6 O

- v- ?% @/ D4 C( {% J! x 微信图片_20231207152833.jpg ; }4 K! I% W: b+ g; W- E

4 Q$ l+ u8 y1 G! PHeap_4.o 的 ZI 数据是存放在 SRAM2 中的 0x3002 E050 位置.
4 _0 `' k+ q- A- a' u% |/ ]3 H# j+ ^7 I" P0 l8 d
微信图片_20231207152830.jpg
8 ^6 s$ F' ^9 H  b: v 微信图片_20231207152819.jpg
5 K" A: L% ]9 P: ]: t; I
6 m# {; o! F9 t5 B4 t/ Y9 F
现在的现象是,Heap_4.o 的 ZI 数据只需要固定在这个位置, 问题就能稳定重现,只不过将其对应的cache 关闭, 问题则消失.2 w9 f- |( }6 z" O( J

& p" V* i3 F- c  J& D1 ]那么此区域默认的 Cache 属性是怎么样的呢? 这个在 AN4839 中可以找到其默认属性:
. e* h' w6 B7 f/ ?$ V7 Y8 s) D- j1 @: a
微信图片_20231207152816.jpg
' z  G2 F1 U  Q( G& u7 R" w& `: r9 d1 a, i0 K8 r# K
于是我们通过代码, 将其 MPU 属性再次配置其默认属性:
, H# k) T9 p* g$ w  ]2 G$ U1 y
& Z: b; I+ k& f
+ L$ T3 `$ F2 P+ u! `% J0 b
5 p9 I7 p) {  L
微信图片_20231207152809.jpg
7 h5 e* Y' V/ u0 m; B
3 s. b7 F, m2 A" f$ J4 {2 q* s$ E结果问题可以重现. 这再次说明, cache 属性对结果有影响.
. Y3 @: H2 c- X0 R$ @8 |& e7 G, R/ }1 Z) O1 b1 q
但是此时还无法对其产生的过程细节进行解释.
; N( X( V! g( t
! b' O* Q# Y5 b" e9 p2 v# t
与此同时, 尝试关闭客户使用第三方库 xx.o 文件中的数据 cache, 问题也同样会消失。这说明, 此问题跟客户所使用的第三方库是有关系的, 其数据在 cache 中产生了一致性问题.
0 v" U& u& \4 N( ?

: }/ E+ Z0 {( |! z于是询问客户这个第三方库是如何来的? 他们回复是一家欧洲公司提供的, 且是以 M4 内核编译的.0 J# w. z+ F9 ?7 }

! N& n- Y( s9 P- ^4 N很明显, 在使用原则上, M4 编译出来的.o 文件, 就不应该用在 H7 工程上. 2 g- U& P9 j- B: p; {( ~% ]

# w  _) t6 F% L2 s+ r& o; F以 M4 为内核编译的.o 文件放到 M7 工程中会产生什么样的影响? 虽然理论上, M7 内核的指令集是向下兼容的, 但是也需要考虑 M7 内核相关的一些特性, 比如 Cache, memory barrier 等等. 不能完全确保不会出问题, 最保险就是重新以 M7 内核编译这个.o 文件. 5 e: g. t5 F6 i8 y9 q* V3 b- h8 \' \

0 h7 z, [& X& x由于这个第三方.o 文件客户自己也是无法知道其内部是如何实现的, 因此, 问题的具体产生过程是没办法进一步调查了. 但定位到这个.o 文件已经是当前能得到的最终结果.9 b) Z7 U5 l8 p& l) k/ Y2 c: h

/ F# H4 b1 N$ f0 ?03小结
9 M- r5 n0 k0 |* {5 ^: H" m本文最终问题的真相虽有点匪夷所思, 但这正反映了当前国内软件应用上的混乱情况. 本文所描述的问题根本原因虽然很另类, 但所涉及到的方法却对开发者有一定的参考意义, 在不能动代码的情况下, 需要挪动数据的位置, 这就必须对编译器有一定的了解. 虽也不至于太难, 但对很多开发都来说, 对编译器的了解未必很深, 因此, 一开始很多人就会卡住。另外, 对 MPU 的了解也是一大门槛. 因此, 特奉上此文, 以供参考.
, v& c8 Q) v' j! O& E- P  e6 m$ I( f0 b5 a+ p3 w5 n' C
转载自: STM32单片机: X  b% B4 M( t
如有侵权请联系删除
- C7 _8 [& ~( f5 |: x
& a( b; _/ n3 z" ~' H; [
  B) B0 X5 C  o  \) C) ^9 [
微信图片_20231207152812.jpg
赞 收藏 评论0 发布时间:2023-12-7 15:29

举报

0个回答

所属标签

相似技术帖

官网相关资源

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