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

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

[复制链接]
攻城狮Melo 发布时间:2023-12-7 15:29
01问题描述% t$ g( d5 a( p# P( Y
用户使用的 MCU 型号是 STM32H750VB。 - X% c. e4 F% l0 T2 B/ J9 Q

: M! I1 n; ^' Q在客户的代码中有多个条件语句,在条件里面的变量数值没有变化的情况下执行了条件里面的逻辑。有点类似如下 C 语句 :
6 }0 [( H2 ?0 g
( }2 K2 P1 W& U/ E- C0 o, X' \' B' Q 微信图片_20231207152903.jpg
! j3 @4 ?" r3 U! u! y

7 }" {4 L: {2 W即变量 A 在明明没有变化且条件不满足的情况下, 程序运行时偏偏执行了条件内部的代码. 很奇怪的现象。一时很难判断是编译器的问题还是芯片问题.
% K  j' o# o$ U! O
6 j6 _" g' j) g, C. c. ?了解到客户的代码中使用了第三方库, xx.o 文件, 像这样的条件有 80 多个, 每次出现问题的具体变量并不是固定哪一个, 但是在大概 10 分钟内肯定会有其中一个出现执行逻辑问题。随意动一下代码问题就不出现, 或者出现的位置发生变化 ; 用 KEIL 编译器去设置断点, 想看该变量信息, 也会导致问题不再出现。
: k+ z$ b: x: r7 d) k. J- {0 A7 Z" `; T! v$ A( D( ?. J
02问题分析2 M( n5 E/ w& C5 k0 j  f
一开始查看 errta sheet, 看到以下相关内容 :% Q, m: p( V/ w
微信图片_20231207152900.jpg
. \7 O  r! C! l) E! h
! W6 t9 d  b1 k+ o- v: z  r! J$ N3 n" R
即怀疑问题跟 AXI SRAM 相关. 查看客户的这些变量, 确实是存放在 AXI SRAM 中. 由于任何修改代码都可能导致问题不再出现, 因此所有尝试须建立在不修改代码的基础上, 不然无法说明问题。# D1 x' y, G" w

, \8 n8 b9 I5 s4 P. w8 F9 J于是让客户用 STM32CubeProgrammer 以 hot plug 模式连接 MCU, 按照勘误手册中 2.2.9 节所描述的 workaround 方式将 AXI_TARG7_FN_MOD 寄存器的 READ_ISS_OVERRIDE 位通过地址的方式直接修改 :8 d0 h0 e4 e' g7 P) I% X
6 U( }) G  V% u* p$ \  V
微信图片_20231207152856.jpg # M" ]! w( k8 H7 }/ ]2 T4 ^! f
' n) n8 n/ t6 r( Z( J3 {& F0 l: O$ J' N
结果发现并没什么效果. 于是排除了这种可能性. 2 B5 Q1 z4 |# S+ |
& w( h/ U; P& J5 q- F; ^7 e$ p
一开始也怀疑问题可能跟 Cache 有关, 于是测试下关闭 Cahce 会怎么样. 通过 KEIL 调试模式下,暂停住 CPU 运行, 然后手动关闭 D-Cache :
, {; x+ J$ s. C/ `, t: n8 ]2 @! r; }8 H' |# R! O
微信图片_20231207152853.jpg
9 Y8 M; d! l! R. e1 d( d) g" X
/ y1 V3 ]: s$ z# ~8 M0 M
结果发现问题消失不见 ! 说明问题肯定跟 Cache 有关.
+ |) M9 h5 a# B! ?3 e# ?2 p5 \- _0 \& U% b' O$ l" [; e/ R/ ?
但客户的代码最终肯定是不能关闭 Cache 的, 想到内核中有一个寄存器可以打开全局 Cache 的write throght 模式, 如下编程手册中的 CACR 寄存器的 FORCEWT 位 :0 i1 t5 o! w1 T7 a$ Z
" |1 o; j3 ~3 J9 W2 F2 n
微信图片_20231207152849.jpg
3 v$ B; }. N  u) R4 H9 @% q8 A
/ b8 j" |- o( {9 k结果发现, 客户的代码本身就已经打开 :
- G/ s4 g! }  s: e% [. Q, y; `/ D" A* s6 T
微信图片_20231207152846.jpg , o4 q" S$ P5 V5 o

2 j; ?$ o$ d  Y- ^看样子此模式与此问题无关. 得换个思路.
4 b2 j+ P* ^9 r& e
" ~5 b/ X2 A% K考虑到问题跟内存数据有关, 代码又不能动. 但是得想办法让内存中数据的位置动动, 看看会有什么效果 ?& J" y9 m+ J! F8 s
9 g# y$ h, l6 J+ y1 P& s
通过修改 KEIL 的链接配置文件.sct 文件, 将变量随意动动, 结果发现问题也会消失不见 ! 这说明,数据的地址跟问题绝对有关联.那么具体是哪些数据呢 ?
/ X+ b$ ^+ z( l0 w2 @) P" Q
6 a# h- H! d* C! ?$ X& L  |7 j4 O7 z$ a
为了精确定位到与哪些变量有关, 查看 KEIL 生成的 map 文件, 按地址倒序将每个程序中所用到的.o 的对应变量逐个挪移动 DTCM RAM 中.& G! D- g) W5 J0 \- S: K& e

5 a9 m7 K7 S) Z$ {# j2 z
微信图片_20231207152843.jpg # I' A: w0 b3 V" L# F: s$ }
# P6 E3 x7 ?: ?2 u& q0 S. i- C1 U
为什么要倒序呢? 主要是因为, 假如先挪低地址的变量, 肯定会导致高地址的变量向低地址移动.这好比, 如果先抽掉下面的砖头, 那么上面的砖头会自动移动下面去. 假如先抽掉上面的砖头情况就不一样了, 下面的砖头还会保持不动. 这就是为什么先挪移上面的砖头的意义, 也就是所谓的倒序.2 S. v' h: E. O& a" S+ u

, i( b: t' d' N& b6 M" n4 C  }通过这种方式, 最终定位到问题跟 heap_4.o 文件以及用户使用到的第三方提供的 xx.o 文件中的ZI 数据有关. 只要保持这两种数据位置不变, 那么问题就可以稳定触发, 一旦其中任何一个位置有所变动, 问题就消失不见.8 Y' I, v8 e) ~8 Q: x
8 Z1 v; B' G( a- ~/ O' n
微信图片_20231207152840.jpg ) M( B) ?0 [5 L5 Q% c

: d" Y' A) X, a2 n0 J现在我们知道规律了, 那么只要固定好这两种 ZI 数据位置不变的情况下, 再去尝试修改代码, 结果发现, 此时修改代码不再会对结果产生影响! 换句话说, 现在可以自由修改代码了. / X: |0 {) C% O$ r+ v& v& t
; ^3 k% T: m* m, G9 V( n2 y/ c
考虑到此问题与 Cache 有关, 于是接下来通过 MPU 设置将 heap_4.o 所在区域的 Cache 功能关闭, 结果发现问题消失.+ r6 A) v9 W, u

: i2 R# q6 S' T; R 微信图片_20231207152836.jpg
$ a7 Z, s, p/ B' f& c

' _4 q# |( y2 w9 l+ T, ]( N4 p 微信图片_20231207152833.jpg . {" B, r6 g1 F' e' o

& x& w) {: M8 C, T3 lHeap_4.o 的 ZI 数据是存放在 SRAM2 中的 0x3002 E050 位置.
! L6 ]8 B1 f; O3 Q$ W. n3 u1 t1 |" ~0 m" @5 z; t2 r
微信图片_20231207152830.jpg
  n& ~* d' ?. V" q9 Z* c 微信图片_20231207152819.jpg
, v, Q) y' ?1 i% E; n
% A$ X" w5 J& g, ^4 _
现在的现象是,Heap_4.o 的 ZI 数据只需要固定在这个位置, 问题就能稳定重现,只不过将其对应的cache 关闭, 问题则消失.  B. X" i& S. u. M& J0 p/ c& u% I6 f

) L5 E, i( b- A; F6 S  }$ h那么此区域默认的 Cache 属性是怎么样的呢? 这个在 AN4839 中可以找到其默认属性:# Z. s7 L' x6 p  v- H. K5 Q& V
0 _1 T, Y# o$ v+ |. [
微信图片_20231207152816.jpg
* |+ ]. p3 y2 r% B* p+ S9 D
  `. C- n# p, ^, d1 E1 L  N于是我们通过代码, 将其 MPU 属性再次配置其默认属性:  X7 f: m8 V9 ^* Q) y- A

" w3 |# `. J& p* a  t5 o/ z9 Y

( u% }' v* X% r5 M4 n  |
/ m" s9 g, n; o- [( O# i1 L8 R4 c) u 微信图片_20231207152809.jpg
( s+ e" t+ N" Z6 A
" m7 Z. S* i5 m0 e; T结果问题可以重现. 这再次说明, cache 属性对结果有影响.. V6 r8 j2 A8 s9 G& D# j' Y  ?
: s. y# {2 V( Q6 R
但是此时还无法对其产生的过程细节进行解释.# T8 y/ w6 J& c2 w4 C7 o

% B4 w0 @2 E1 I与此同时, 尝试关闭客户使用第三方库 xx.o 文件中的数据 cache, 问题也同样会消失。这说明, 此问题跟客户所使用的第三方库是有关系的, 其数据在 cache 中产生了一致性问题.
2 A% e- X: f7 ]+ a

% r( j# D, p4 L% V0 P  T, L于是询问客户这个第三方库是如何来的? 他们回复是一家欧洲公司提供的, 且是以 M4 内核编译的.
9 S% M5 P( w0 ^1 ~3 }8 c

0 p% T. |. t  P0 G很明显, 在使用原则上, M4 编译出来的.o 文件, 就不应该用在 H7 工程上. ! Q% d- C! |/ ~; O8 C
' `0 B7 Z* r/ a6 {) f
以 M4 为内核编译的.o 文件放到 M7 工程中会产生什么样的影响? 虽然理论上, M7 内核的指令集是向下兼容的, 但是也需要考虑 M7 内核相关的一些特性, 比如 Cache, memory barrier 等等. 不能完全确保不会出问题, 最保险就是重新以 M7 内核编译这个.o 文件.
. {* ^% a* j" n' B# b$ I' U2 x2 J2 L5 [8 r
由于这个第三方.o 文件客户自己也是无法知道其内部是如何实现的, 因此, 问题的具体产生过程是没办法进一步调查了. 但定位到这个.o 文件已经是当前能得到的最终结果.
  ~- D  l" i( I0 o  I+ G( B7 J, I  D
03小结
. t, j2 }7 Y9 C  {本文最终问题的真相虽有点匪夷所思, 但这正反映了当前国内软件应用上的混乱情况. 本文所描述的问题根本原因虽然很另类, 但所涉及到的方法却对开发者有一定的参考意义, 在不能动代码的情况下, 需要挪动数据的位置, 这就必须对编译器有一定的了解. 虽也不至于太难, 但对很多开发都来说, 对编译器的了解未必很深, 因此, 一开始很多人就会卡住。另外, 对 MPU 的了解也是一大门槛. 因此, 特奉上此文, 以供参考.7 k- M5 O# v* G* P! d2 B
/ u: H( T, |/ l" l7 l
转载自: STM32单片机
1 `3 P" [, P( U8 O  C" R8 `2 M* S如有侵权请联系删除
; p' t0 A& D* _/ l3 C; ]
6 m- W6 }$ S3 V2 j* Q
0 o$ d: @+ w) a9 D, u. D
微信图片_20231207152812.jpg
收藏 评论0 发布时间:2023-12-7 15:29

举报

0个回答

所属标签

相似分享

官网相关资源

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