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

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

[复制链接]
攻城狮Melo 发布时间:2023-12-7 15:29
01问题描述) W+ \. G' E3 H9 N% [
用户使用的 MCU 型号是 STM32H750VB。
, n% ^) Y3 V/ x5 r7 h3 V
; e& F- h" \( O7 c! }) j# V8 S% i- d在客户的代码中有多个条件语句,在条件里面的变量数值没有变化的情况下执行了条件里面的逻辑。有点类似如下 C 语句 :
, f4 p8 m% _* y6 u% v! w  `$ w7 T: M
微信图片_20231207152903.jpg
& y( C; n8 W; U
" c# f" {6 j6 W- l; u; y+ J
即变量 A 在明明没有变化且条件不满足的情况下, 程序运行时偏偏执行了条件内部的代码. 很奇怪的现象。一时很难判断是编译器的问题还是芯片问题.
# f, r2 e  {2 r! I2 Y7 `  W7 {
' e* q- \1 D7 P; m了解到客户的代码中使用了第三方库, xx.o 文件, 像这样的条件有 80 多个, 每次出现问题的具体变量并不是固定哪一个, 但是在大概 10 分钟内肯定会有其中一个出现执行逻辑问题。随意动一下代码问题就不出现, 或者出现的位置发生变化 ; 用 KEIL 编译器去设置断点, 想看该变量信息, 也会导致问题不再出现。
7 C6 x; S: B$ u4 }+ }& d
  Z" W. B6 R& b02问题分析
0 E- U  }. i$ I2 \9 \) ~一开始查看 errta sheet, 看到以下相关内容 :
0 w; l6 `6 e$ q9 h$ E# P/ f
微信图片_20231207152900.jpg
# P" N  ^5 f1 e" k* C! Z4 o, _0 ~
' Z* f  [$ N9 A8 _3 y6 l& p+ n+ j
即怀疑问题跟 AXI SRAM 相关. 查看客户的这些变量, 确实是存放在 AXI SRAM 中. 由于任何修改代码都可能导致问题不再出现, 因此所有尝试须建立在不修改代码的基础上, 不然无法说明问题。
- y  O2 E3 Z- z' r
4 J& u4 a/ D2 Y1 m$ }! O3 b于是让客户用 STM32CubeProgrammer 以 hot plug 模式连接 MCU, 按照勘误手册中 2.2.9 节所描述的 workaround 方式将 AXI_TARG7_FN_MOD 寄存器的 READ_ISS_OVERRIDE 位通过地址的方式直接修改 :
% S+ \7 ^( `% |' ]& t! s, w: u! A3 ]" @( ^" O+ T" S7 p; B
微信图片_20231207152856.jpg 3 T) B# x! I, ]' a7 {

* ?1 H7 V8 d6 m# U. p结果发现并没什么效果. 于是排除了这种可能性. ! J& m5 s+ d, w

+ \& }6 T; h: ?$ e+ H: S! d1 u一开始也怀疑问题可能跟 Cache 有关, 于是测试下关闭 Cahce 会怎么样. 通过 KEIL 调试模式下,暂停住 CPU 运行, 然后手动关闭 D-Cache :6 @' H/ g7 u9 R* w
. x9 J) ~6 o6 G: B0 K$ r1 z1 _
微信图片_20231207152853.jpg
. p- |9 O( F) D
  A& }5 ^+ h; Z
结果发现问题消失不见 ! 说明问题肯定跟 Cache 有关. 2 C& U) H* S% D/ ^) S
1 E4 p5 O9 a9 ^3 T7 Y7 C
但客户的代码最终肯定是不能关闭 Cache 的, 想到内核中有一个寄存器可以打开全局 Cache 的write throght 模式, 如下编程手册中的 CACR 寄存器的 FORCEWT 位 :* T& z, v4 K0 }( ~. y" D+ }

. X1 ~- ~# ?' ~; g/ f$ {# m6 D1 n
微信图片_20231207152849.jpg $ D% }( c: c" |* j# D: L

1 Z* l9 p! O$ I7 S  ~9 F" _结果发现, 客户的代码本身就已经打开 :1 ~& w8 A: X% {" {. z9 ^- {8 n
2 z; a4 u5 A# u' D
微信图片_20231207152846.jpg / B$ ^- G: ?. t2 N
; [7 y6 D6 N  c
看样子此模式与此问题无关. 得换个思路. + }$ R8 p, K1 j, q5 k, l; p& f1 X

4 a5 L4 j1 G2 K: p. o- ?考虑到问题跟内存数据有关, 代码又不能动. 但是得想办法让内存中数据的位置动动, 看看会有什么效果 ?
0 c: U; K0 k3 ]7 A& ^7 |+ y+ D9 `" O9 [# I# K6 B- H
通过修改 KEIL 的链接配置文件.sct 文件, 将变量随意动动, 结果发现问题也会消失不见 ! 这说明,数据的地址跟问题绝对有关联.那么具体是哪些数据呢 ?% L8 z( p, I( n4 b* o
; q% m5 r% i6 z! D
为了精确定位到与哪些变量有关, 查看 KEIL 生成的 map 文件, 按地址倒序将每个程序中所用到的.o 的对应变量逐个挪移动 DTCM RAM 中.6 y# m) s2 R' k7 D7 x3 L

$ e9 J7 i( v! x4 P* x$ S: W4 B" Z
微信图片_20231207152843.jpg ; u  V' r( x$ K
9 H$ t& W) `+ Y! c  V
为什么要倒序呢? 主要是因为, 假如先挪低地址的变量, 肯定会导致高地址的变量向低地址移动.这好比, 如果先抽掉下面的砖头, 那么上面的砖头会自动移动下面去. 假如先抽掉上面的砖头情况就不一样了, 下面的砖头还会保持不动. 这就是为什么先挪移上面的砖头的意义, 也就是所谓的倒序.  j& v! ]% E3 q3 m, I& U4 k. H$ T' O

: P. Z$ q) e( G) F, Y$ F$ D; e通过这种方式, 最终定位到问题跟 heap_4.o 文件以及用户使用到的第三方提供的 xx.o 文件中的ZI 数据有关. 只要保持这两种数据位置不变, 那么问题就可以稳定触发, 一旦其中任何一个位置有所变动, 问题就消失不见.+ l: E3 g, y0 \% k8 v

- ?* T" `4 X/ M
微信图片_20231207152840.jpg 6 z$ }" W) I5 ~1 G3 H: m
9 S3 t8 x0 O0 Y! w* G8 Z4 e
现在我们知道规律了, 那么只要固定好这两种 ZI 数据位置不变的情况下, 再去尝试修改代码, 结果发现, 此时修改代码不再会对结果产生影响! 换句话说, 现在可以自由修改代码了. 1 b6 O+ x' ^& L

' W- Y  X: S0 {5 C考虑到此问题与 Cache 有关, 于是接下来通过 MPU 设置将 heap_4.o 所在区域的 Cache 功能关闭, 结果发现问题消失.
3 m; g! A# T9 D- i! t

+ r, E2 H# {# j0 u8 z0 d- x4 \5 ~ 微信图片_20231207152836.jpg 5 q3 Z5 U. a4 K
; T; Y1 _( Q; j6 P7 \+ o9 }, {
微信图片_20231207152833.jpg / B: _9 N/ V$ ?% O/ h

1 K. X% r- T  B- T2 JHeap_4.o 的 ZI 数据是存放在 SRAM2 中的 0x3002 E050 位置.1 O) w  T) @/ T% I1 @

2 g; v( n( S& M7 z" o
微信图片_20231207152830.jpg
9 x( m5 E2 h4 ^+ W 微信图片_20231207152819.jpg
, P, E' G) F% i8 c
% s4 d5 I! ]) e3 x- W! G
现在的现象是,Heap_4.o 的 ZI 数据只需要固定在这个位置, 问题就能稳定重现,只不过将其对应的cache 关闭, 问题则消失.8 ?3 f( a" g* T- X' l4 [

" C& ~0 E6 |+ i+ W3 |- Q那么此区域默认的 Cache 属性是怎么样的呢? 这个在 AN4839 中可以找到其默认属性:. r9 s0 X! u2 l7 j8 K/ }2 s
9 ?) S6 {4 d# D- o0 N
微信图片_20231207152816.jpg & [6 _6 t. }" n4 _7 D! }8 O- k6 o; L

3 ^: Q1 I. V# D- w0 @, A( w7 b: A' I于是我们通过代码, 将其 MPU 属性再次配置其默认属性:9 e0 Z# y0 A( Y% @% L# d8 F4 B
# r0 G* m6 f- l
3 ]& e# U% g7 c
% O' ]6 Q5 l. B7 Z
微信图片_20231207152809.jpg
- @- ?5 `- y, ~$ p! j: R: u7 }3 g' }& I1 ^
结果问题可以重现. 这再次说明, cache 属性对结果有影响.3 u4 f; i" Z7 @
6 S# i$ M+ N2 F. I1 K( h
但是此时还无法对其产生的过程细节进行解释., q  b- k/ r" B4 j

+ K% u; {: b5 f' c与此同时, 尝试关闭客户使用第三方库 xx.o 文件中的数据 cache, 问题也同样会消失。这说明, 此问题跟客户所使用的第三方库是有关系的, 其数据在 cache 中产生了一致性问题.
' |8 W/ S4 G+ m% W5 U0 p
' n& i" o4 X% l  u! \
于是询问客户这个第三方库是如何来的? 他们回复是一家欧洲公司提供的, 且是以 M4 内核编译的.6 [7 R6 \$ _: `' n* i( N6 i

* h) x5 S' |1 ]8 i很明显, 在使用原则上, M4 编译出来的.o 文件, 就不应该用在 H7 工程上.   U3 U0 ?0 A) `7 }; O0 f. [3 w& }. v

+ Z; X2 Q: n& K, f5 P1 [5 k, b  C以 M4 为内核编译的.o 文件放到 M7 工程中会产生什么样的影响? 虽然理论上, M7 内核的指令集是向下兼容的, 但是也需要考虑 M7 内核相关的一些特性, 比如 Cache, memory barrier 等等. 不能完全确保不会出问题, 最保险就是重新以 M7 内核编译这个.o 文件.
* R+ `3 A! C, l& v" K: G4 T6 {8 ]2 _7 x2 R# S% S- s! w
由于这个第三方.o 文件客户自己也是无法知道其内部是如何实现的, 因此, 问题的具体产生过程是没办法进一步调查了. 但定位到这个.o 文件已经是当前能得到的最终结果.: e9 K; j% p9 ~6 c. s4 c+ `
; ~0 d# W, g' G1 G7 c
03小结
3 k' H# M. b) A9 L& a本文最终问题的真相虽有点匪夷所思, 但这正反映了当前国内软件应用上的混乱情况. 本文所描述的问题根本原因虽然很另类, 但所涉及到的方法却对开发者有一定的参考意义, 在不能动代码的情况下, 需要挪动数据的位置, 这就必须对编译器有一定的了解. 虽也不至于太难, 但对很多开发都来说, 对编译器的了解未必很深, 因此, 一开始很多人就会卡住。另外, 对 MPU 的了解也是一大门槛. 因此, 特奉上此文, 以供参考.
. b/ v# v% b0 t  A' U: u; T# a$ l8 E) Y
转载自: STM32单片机) c; F  P8 w6 ?1 i/ @
如有侵权请联系删除0 Y, E1 t+ }" K

" o: Z- m& w; z$ u' _+ o% M3 e0 r
" ~9 ~; w) y. ~
微信图片_20231207152812.jpg
赞 收藏 评论0 发布时间:2023-12-7 15:29

举报

0个回答

所属标签

相似技术帖

官网相关资源

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