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

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

[复制链接]
攻城狮Melo 发布时间:2023-12-7 15:29
01问题描述+ ^: v/ B6 ~  X& N
用户使用的 MCU 型号是 STM32H750VB。 6 O0 v7 ~' L+ c$ S7 M

- G1 I2 f: W- W( n, y$ Z) K在客户的代码中有多个条件语句,在条件里面的变量数值没有变化的情况下执行了条件里面的逻辑。有点类似如下 C 语句 :5 |" ]9 h, s( q' J' G4 I2 W2 }" \

$ B/ W* T- G$ `; f: G4 M# B 微信图片_20231207152903.jpg
' |' Q5 g( p2 `

: ?# v" z! k2 S. I8 [8 n即变量 A 在明明没有变化且条件不满足的情况下, 程序运行时偏偏执行了条件内部的代码. 很奇怪的现象。一时很难判断是编译器的问题还是芯片问题.5 y; E4 Q1 T7 u- u# v: W& t3 n7 g' x

* q: B/ m) N3 u4 ~3 X1 y了解到客户的代码中使用了第三方库, xx.o 文件, 像这样的条件有 80 多个, 每次出现问题的具体变量并不是固定哪一个, 但是在大概 10 分钟内肯定会有其中一个出现执行逻辑问题。随意动一下代码问题就不出现, 或者出现的位置发生变化 ; 用 KEIL 编译器去设置断点, 想看该变量信息, 也会导致问题不再出现。$ X! q, \8 m2 Y2 L9 V

! V4 n: f5 C: c/ [$ f02问题分析7 n6 C! n2 w0 M! l, R
一开始查看 errta sheet, 看到以下相关内容 :
( e& X5 q2 I7 t
微信图片_20231207152900.jpg
: o2 C) V6 ~% Y2 ^. n, @

4 d  |  E! O* I即怀疑问题跟 AXI SRAM 相关. 查看客户的这些变量, 确实是存放在 AXI SRAM 中. 由于任何修改代码都可能导致问题不再出现, 因此所有尝试须建立在不修改代码的基础上, 不然无法说明问题。
4 k- Z9 x6 F# j8 [: C8 \6 I3 w8 I" S. k, O: J' |+ [. ?5 t. w/ e
于是让客户用 STM32CubeProgrammer 以 hot plug 模式连接 MCU, 按照勘误手册中 2.2.9 节所描述的 workaround 方式将 AXI_TARG7_FN_MOD 寄存器的 READ_ISS_OVERRIDE 位通过地址的方式直接修改 :
2 u2 l0 T3 {( o0 }2 b7 |- w
0 A" y1 d: `# {  `  j
微信图片_20231207152856.jpg
$ N' A) T( i# j% W1 s& `
8 `1 d! }3 q4 Q8 S1 }
结果发现并没什么效果. 于是排除了这种可能性. $ J" a/ `( T1 Y' ]( i& Z) ]

9 x+ B: W/ @5 N6 t一开始也怀疑问题可能跟 Cache 有关, 于是测试下关闭 Cahce 会怎么样. 通过 KEIL 调试模式下,暂停住 CPU 运行, 然后手动关闭 D-Cache :
. A1 J/ W& X3 Q/ q9 J, X$ u, |+ Z; R3 o! u
微信图片_20231207152853.jpg ) T  N* ~9 [" V4 L0 A; r( y2 d

* K. _+ B, g8 B* Q6 {结果发现问题消失不见 ! 说明问题肯定跟 Cache 有关. * u( P! \/ d% P! `
* Y, _/ {0 G# r: B' `
但客户的代码最终肯定是不能关闭 Cache 的, 想到内核中有一个寄存器可以打开全局 Cache 的write throght 模式, 如下编程手册中的 CACR 寄存器的 FORCEWT 位 :
  N( ?$ H* ?# e( e0 N  Z* ?4 a8 U! Z$ I! N4 a
微信图片_20231207152849.jpg
; A( I1 y+ X, K: t+ ~( N
* @" L$ x$ X% ?# E0 M! J4 o* l* O结果发现, 客户的代码本身就已经打开 :' c' T5 [- I, Q+ v1 d; p

8 C- f' ]- l4 j0 v
微信图片_20231207152846.jpg / s6 P9 s& r% _+ Q3 L
  Y  c, ?. {: f0 _( B
看样子此模式与此问题无关. 得换个思路.
; U8 c4 X* j% j" w8 T5 |# L' h( ^! T
考虑到问题跟内存数据有关, 代码又不能动. 但是得想办法让内存中数据的位置动动, 看看会有什么效果 ?7 r) s( Q4 ?/ v) e7 K/ T2 L! u4 W
0 q# z' D* d2 y- m: ]: P- ^
通过修改 KEIL 的链接配置文件.sct 文件, 将变量随意动动, 结果发现问题也会消失不见 ! 这说明,数据的地址跟问题绝对有关联.那么具体是哪些数据呢 ?
$ z" c4 O: d5 i

8 \, J: J) W# a9 n为了精确定位到与哪些变量有关, 查看 KEIL 生成的 map 文件, 按地址倒序将每个程序中所用到的.o 的对应变量逐个挪移动 DTCM RAM 中.1 y- |1 v3 m; P  |% _2 `1 M# R

8 |/ t2 `, U4 c' y
微信图片_20231207152843.jpg
) @8 S& ~3 _& z) z: L& b

4 s) J' }' n+ d2 N" n) w3 y/ B为什么要倒序呢? 主要是因为, 假如先挪低地址的变量, 肯定会导致高地址的变量向低地址移动.这好比, 如果先抽掉下面的砖头, 那么上面的砖头会自动移动下面去. 假如先抽掉上面的砖头情况就不一样了, 下面的砖头还会保持不动. 这就是为什么先挪移上面的砖头的意义, 也就是所谓的倒序.
# |# _7 i, ]* d( z' U2 N

9 ~( u2 P# Z$ f" [: S' t8 J7 m通过这种方式, 最终定位到问题跟 heap_4.o 文件以及用户使用到的第三方提供的 xx.o 文件中的ZI 数据有关. 只要保持这两种数据位置不变, 那么问题就可以稳定触发, 一旦其中任何一个位置有所变动, 问题就消失不见.
) [4 ~# |7 L* W/ ]2 ?4 c% y5 [" X) b7 W) q8 w3 t
微信图片_20231207152840.jpg 8 q2 d2 A. S* v  u- C
1 ]& f6 a/ S% r* R& i. k
现在我们知道规律了, 那么只要固定好这两种 ZI 数据位置不变的情况下, 再去尝试修改代码, 结果发现, 此时修改代码不再会对结果产生影响! 换句话说, 现在可以自由修改代码了.
4 ?& r9 @9 c) Q$ O' _! [6 ~* O# b3 s$ U5 O5 @8 l8 N5 `
考虑到此问题与 Cache 有关, 于是接下来通过 MPU 设置将 heap_4.o 所在区域的 Cache 功能关闭, 结果发现问题消失.
6 D9 n, \: d. D1 M6 r; l& O
6 `: G& @, }! {: T& R# j& h
微信图片_20231207152836.jpg 4 w1 V; E$ Z) w  Y- W
4 \/ Y1 S8 s; z6 w/ S3 t. y4 e
微信图片_20231207152833.jpg
+ k' S; `$ g; e) I  v( b
; i0 U! a( m0 G9 K3 u
Heap_4.o 的 ZI 数据是存放在 SRAM2 中的 0x3002 E050 位置./ v& f) v( s8 \! N6 ~' f

" }) l2 Z, i1 j3 f
微信图片_20231207152830.jpg # z! Q$ w. |3 a( B
微信图片_20231207152819.jpg
/ A% P- L" M1 C: _3 @4 J! {

; J% h; H0 A% T1 b% g+ M现在的现象是,Heap_4.o 的 ZI 数据只需要固定在这个位置, 问题就能稳定重现,只不过将其对应的cache 关闭, 问题则消失.
) w9 y. Z6 P2 ~" p

- N% W) f( w! k. O5 _) \) ~那么此区域默认的 Cache 属性是怎么样的呢? 这个在 AN4839 中可以找到其默认属性:9 ^7 Q# k( c, T( J# E
) u* ^9 S. x; T) p' Q
微信图片_20231207152816.jpg
1 E4 f: ^& O. k" w8 N" r& k
+ Q8 k3 [2 }: A  h1 h# V: c2 j于是我们通过代码, 将其 MPU 属性再次配置其默认属性:
2 d2 `; Q8 R& M, v  r7 d& W- y& y$ A9 _6 l$ |

" j( I' G. B5 m6 V, f$ B, c# _1 X2 b/ c* r# n0 v
微信图片_20231207152809.jpg 1 _/ o, T9 |/ \+ P' R
9 ?7 \0 l& Q4 I5 b
结果问题可以重现. 这再次说明, cache 属性对结果有影响.
" {3 g5 W" b) \( Y! C& M- X
& g0 K1 S, K7 O  w- Z
但是此时还无法对其产生的过程细节进行解释.
3 P# e5 ?8 L/ Q6 y

7 H2 d9 S; o( {! w' h与此同时, 尝试关闭客户使用第三方库 xx.o 文件中的数据 cache, 问题也同样会消失。这说明, 此问题跟客户所使用的第三方库是有关系的, 其数据在 cache 中产生了一致性问题.
+ F6 m  {" t+ s, C, T) Z

+ O4 B8 [. p0 D+ b于是询问客户这个第三方库是如何来的? 他们回复是一家欧洲公司提供的, 且是以 M4 内核编译的.
, T2 o* w5 a0 m+ E+ {
6 M. u; @. a2 c' y
很明显, 在使用原则上, M4 编译出来的.o 文件, 就不应该用在 H7 工程上.
! p9 D/ |( ]4 e  {, Y) D; _- |1 [9 x( N
以 M4 为内核编译的.o 文件放到 M7 工程中会产生什么样的影响? 虽然理论上, M7 内核的指令集是向下兼容的, 但是也需要考虑 M7 内核相关的一些特性, 比如 Cache, memory barrier 等等. 不能完全确保不会出问题, 最保险就是重新以 M7 内核编译这个.o 文件. 1 |! M4 ^/ l! }4 j$ q; j# X

6 g# n  _' d  u  K1 H' Z! q由于这个第三方.o 文件客户自己也是无法知道其内部是如何实现的, 因此, 问题的具体产生过程是没办法进一步调查了. 但定位到这个.o 文件已经是当前能得到的最终结果.* q  A' D* _; T" x4 k, I7 U
- n4 m4 t5 G) l2 d2 h# R4 Z' y( Z
03小结
0 s8 V, d6 j1 F5 x  w0 j+ `. {* O本文最终问题的真相虽有点匪夷所思, 但这正反映了当前国内软件应用上的混乱情况. 本文所描述的问题根本原因虽然很另类, 但所涉及到的方法却对开发者有一定的参考意义, 在不能动代码的情况下, 需要挪动数据的位置, 这就必须对编译器有一定的了解. 虽也不至于太难, 但对很多开发都来说, 对编译器的了解未必很深, 因此, 一开始很多人就会卡住。另外, 对 MPU 的了解也是一大门槛. 因此, 特奉上此文, 以供参考.
# C5 R1 H/ e6 {% a. O3 `% ~& V! W* Y6 o/ m% T0 h- A/ K& B1 b1 v
转载自: STM32单片机
/ G# V2 B6 _5 n. u0 V: I' c如有侵权请联系删除
1 K/ _! W! H& H1 s' U) z/ ?( t( T
6 V4 R. T5 g0 S  [/ \
微信图片_20231207152812.jpg
收藏 评论0 发布时间:2023-12-7 15:29

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版