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

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

[复制链接]
攻城狮Melo 发布时间:2023-12-7 15:29
01问题描述% |- p6 W, l5 B' H) i* q  L5 y
用户使用的 MCU 型号是 STM32H750VB。 , N* s) S& }, c' H% V' x$ V

3 a# O* Y3 T" ]# W: ?. H在客户的代码中有多个条件语句,在条件里面的变量数值没有变化的情况下执行了条件里面的逻辑。有点类似如下 C 语句 :8 z  d7 x' h1 C9 D7 U

; j1 r$ l5 ]" q! H 微信图片_20231207152903.jpg 1 d1 K4 X2 U: y
* V# [. A. Y. ?
即变量 A 在明明没有变化且条件不满足的情况下, 程序运行时偏偏执行了条件内部的代码. 很奇怪的现象。一时很难判断是编译器的问题还是芯片问题.9 B* K$ Z3 b6 A9 p+ W# G! y# Y/ ?3 U

& V" x' A- t! |' B0 x2 F+ ^& j$ T" n' l了解到客户的代码中使用了第三方库, xx.o 文件, 像这样的条件有 80 多个, 每次出现问题的具体变量并不是固定哪一个, 但是在大概 10 分钟内肯定会有其中一个出现执行逻辑问题。随意动一下代码问题就不出现, 或者出现的位置发生变化 ; 用 KEIL 编译器去设置断点, 想看该变量信息, 也会导致问题不再出现。
# h7 m% |3 n0 a' y4 Y3 X3 C" c! \0 i% s" @0 d6 O
02问题分析
3 q! j, U7 _2 i: P; v* I2 A0 Z2 C4 ?一开始查看 errta sheet, 看到以下相关内容 :
. b1 P- Z9 l8 d2 b8 }, x
微信图片_20231207152900.jpg
* ?5 q$ K8 R; S4 [$ \: ]9 `
1 Y' F  ?6 ?' R5 d2 d$ p
即怀疑问题跟 AXI SRAM 相关. 查看客户的这些变量, 确实是存放在 AXI SRAM 中. 由于任何修改代码都可能导致问题不再出现, 因此所有尝试须建立在不修改代码的基础上, 不然无法说明问题。
# h7 H1 p9 C$ x# T, ?) s
! ?5 X/ }0 \, s0 \; n8 w于是让客户用 STM32CubeProgrammer 以 hot plug 模式连接 MCU, 按照勘误手册中 2.2.9 节所描述的 workaround 方式将 AXI_TARG7_FN_MOD 寄存器的 READ_ISS_OVERRIDE 位通过地址的方式直接修改 :
; ?2 c* }1 c  d0 H' N( g! b6 o
+ S; [( ^' l5 g( g- Z( Y  g
微信图片_20231207152856.jpg
: ]" j3 P- c1 N' F; D" _
- u6 x% `4 c5 ~- T. S
结果发现并没什么效果. 于是排除了这种可能性.
6 T0 [! F3 E7 T
& }4 y) _3 N4 v$ e一开始也怀疑问题可能跟 Cache 有关, 于是测试下关闭 Cahce 会怎么样. 通过 KEIL 调试模式下,暂停住 CPU 运行, 然后手动关闭 D-Cache :
  H4 r8 t  i2 i/ Q1 F5 w; v" W. S6 }& ^( X. b3 W
微信图片_20231207152853.jpg 6 w4 H* l* J' _- e- S9 F! I$ Y
7 W) b; l1 v' r+ ], S
结果发现问题消失不见 ! 说明问题肯定跟 Cache 有关.
9 u9 `( q  W& N* b# C
  o& \% }  ]- k& X' C9 z0 W, l+ }但客户的代码最终肯定是不能关闭 Cache 的, 想到内核中有一个寄存器可以打开全局 Cache 的write throght 模式, 如下编程手册中的 CACR 寄存器的 FORCEWT 位 :
4 v& t) P: T- C: i$ d9 c. x. a% J
, K2 s$ [' O! [9 L
微信图片_20231207152849.jpg % C  a3 Q  o  @& K; N( m  A

' @9 Q. ?4 j2 r& S0 c结果发现, 客户的代码本身就已经打开 :
, i& U5 j! w; {  N2 K/ L  d7 D' u0 E, O3 k
微信图片_20231207152846.jpg
# V; l& S% r' z7 C1 O
2 f- [. k1 R: w# c" v看样子此模式与此问题无关. 得换个思路.
6 d5 k6 e7 Y! ?, V; A3 P% V
: Z& Q  l- L9 T" _% J/ z  u考虑到问题跟内存数据有关, 代码又不能动. 但是得想办法让内存中数据的位置动动, 看看会有什么效果 ?+ u( m) o$ K0 N
: D/ ^6 c$ l! c2 r
通过修改 KEIL 的链接配置文件.sct 文件, 将变量随意动动, 结果发现问题也会消失不见 ! 这说明,数据的地址跟问题绝对有关联.那么具体是哪些数据呢 ?3 V5 c; G7 u$ I: w; X

; V( ?; z9 _$ i* c3 ?  v' i& Q4 c: z为了精确定位到与哪些变量有关, 查看 KEIL 生成的 map 文件, 按地址倒序将每个程序中所用到的.o 的对应变量逐个挪移动 DTCM RAM 中.
9 ]  f) ?' v' d( y; Z' _" p' P
, o3 Q8 c/ S. k6 L! M- T5 j
微信图片_20231207152843.jpg
, o, D: j" k& }# k' P, U1 @
  K1 `8 {: u' t9 Y+ d) n( v' y* d, _
为什么要倒序呢? 主要是因为, 假如先挪低地址的变量, 肯定会导致高地址的变量向低地址移动.这好比, 如果先抽掉下面的砖头, 那么上面的砖头会自动移动下面去. 假如先抽掉上面的砖头情况就不一样了, 下面的砖头还会保持不动. 这就是为什么先挪移上面的砖头的意义, 也就是所谓的倒序.
+ S* A/ ^/ g  _( d2 c
( k9 S4 I* `2 |
通过这种方式, 最终定位到问题跟 heap_4.o 文件以及用户使用到的第三方提供的 xx.o 文件中的ZI 数据有关. 只要保持这两种数据位置不变, 那么问题就可以稳定触发, 一旦其中任何一个位置有所变动, 问题就消失不见.$ I; n: i# @. m, I( H' P9 O( x

2 U# j% ^5 j4 f+ l& p
微信图片_20231207152840.jpg - `( {) I) K+ D- [! a4 k

- M$ f4 |2 s- U现在我们知道规律了, 那么只要固定好这两种 ZI 数据位置不变的情况下, 再去尝试修改代码, 结果发现, 此时修改代码不再会对结果产生影响! 换句话说, 现在可以自由修改代码了. 9 k7 a1 V. K+ k' s

/ u" {7 ~. Z2 L3 X  k考虑到此问题与 Cache 有关, 于是接下来通过 MPU 设置将 heap_4.o 所在区域的 Cache 功能关闭, 结果发现问题消失.
5 R6 x' \" ~' w2 u$ ]+ s
* ^3 P8 b/ H; u, z
微信图片_20231207152836.jpg / `9 y1 }8 D) y
" Y9 A; P* c" z% q
微信图片_20231207152833.jpg ; c/ p8 p. G1 c  m. f2 `: O

  r! {; d& Z  L6 i9 WHeap_4.o 的 ZI 数据是存放在 SRAM2 中的 0x3002 E050 位置.; Z2 b# r8 |7 `% d6 h8 [' `* F

% `; ]5 C% G+ R' Y, y8 o; N
微信图片_20231207152830.jpg
  j4 L/ F6 S0 r! Y6 ]* K/ Z 微信图片_20231207152819.jpg 8 u0 t6 V, @& l+ L

5 i# s* V4 i& R; _现在的现象是,Heap_4.o 的 ZI 数据只需要固定在这个位置, 问题就能稳定重现,只不过将其对应的cache 关闭, 问题则消失.4 G7 d# F. M9 v6 _* ^

! H4 B' Q# T4 ~! Q4 `那么此区域默认的 Cache 属性是怎么样的呢? 这个在 AN4839 中可以找到其默认属性:! b! @# z5 {1 r' |+ x/ C4 H
5 x: T( v$ g( `8 y' }
微信图片_20231207152816.jpg ( m. x5 C+ L, v; K4 g8 C, }6 ~

) ], }: C3 H- t! q; @1 y于是我们通过代码, 将其 MPU 属性再次配置其默认属性:% N; J2 t7 G+ V' y; b( z! m) R

7 O. P% W2 U8 F* L" w% g

9 @. R6 f3 {6 f5 t" q' N; p. ]4 M: o
微信图片_20231207152809.jpg 3 y* u+ \9 `# C* }% w* j
6 |# m# h4 m- _) |" @. c
结果问题可以重现. 这再次说明, cache 属性对结果有影响.
; l3 u0 S  D- r* H5 W- b1 J! S3 n! k: S" P( y  y' h
但是此时还无法对其产生的过程细节进行解释.
6 V; r9 ^  n+ I  |- C( ?/ ]/ l
2 J* Q) S" R8 L6 R' o" l7 s
与此同时, 尝试关闭客户使用第三方库 xx.o 文件中的数据 cache, 问题也同样会消失。这说明, 此问题跟客户所使用的第三方库是有关系的, 其数据在 cache 中产生了一致性问题.* ^& s& c- }6 m: l

" q5 W, }6 g/ o: ~9 ^9 J于是询问客户这个第三方库是如何来的? 他们回复是一家欧洲公司提供的, 且是以 M4 内核编译的.: R: x6 I/ `; N' H% `5 R3 B

% f6 v, P7 F6 e很明显, 在使用原则上, M4 编译出来的.o 文件, 就不应该用在 H7 工程上.
  K$ @  s. H6 A4 T9 g3 i' Q. L$ x
( x( u6 W4 U- k3 A( W以 M4 为内核编译的.o 文件放到 M7 工程中会产生什么样的影响? 虽然理论上, M7 内核的指令集是向下兼容的, 但是也需要考虑 M7 内核相关的一些特性, 比如 Cache, memory barrier 等等. 不能完全确保不会出问题, 最保险就是重新以 M7 内核编译这个.o 文件.
( J- N, @7 E5 s" v4 \+ c# j
  J  D' ~2 T9 k2 o. E: c由于这个第三方.o 文件客户自己也是无法知道其内部是如何实现的, 因此, 问题的具体产生过程是没办法进一步调查了. 但定位到这个.o 文件已经是当前能得到的最终结果.4 B+ H1 w# G0 i2 O6 S

. ^, T4 T4 l) ~6 L9 Z  D( h03小结2 `; m# i' z! W) s: A% I
本文最终问题的真相虽有点匪夷所思, 但这正反映了当前国内软件应用上的混乱情况. 本文所描述的问题根本原因虽然很另类, 但所涉及到的方法却对开发者有一定的参考意义, 在不能动代码的情况下, 需要挪动数据的位置, 这就必须对编译器有一定的了解. 虽也不至于太难, 但对很多开发都来说, 对编译器的了解未必很深, 因此, 一开始很多人就会卡住。另外, 对 MPU 的了解也是一大门槛. 因此, 特奉上此文, 以供参考.1 w5 I( L) r: B& N

/ @, ^, o3 u  D/ M4 ?- c转载自: STM32单片机
! x9 B( M& l6 X9 S如有侵权请联系删除
/ y" i$ f# y! G5 z- L/ Q- `0 {- _; n$ X6 f* c7 R

4 P' N$ T' q2 w# Z4 J0 {% o; v
微信图片_20231207152812.jpg
收藏 评论0 发布时间:2023-12-7 15:29

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版