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

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

[复制链接]
攻城狮Melo 发布时间:2023-12-7 15:29
01问题描述
. @+ s# u% P4 ?3 A用户使用的 MCU 型号是 STM32H750VB。
; M" ?- C2 j! u/ L  E1 {8 B2 c+ E& b7 U7 N. \3 X' Q
在客户的代码中有多个条件语句,在条件里面的变量数值没有变化的情况下执行了条件里面的逻辑。有点类似如下 C 语句 :$ }5 z  {  R0 v# B" i, m1 U
% I3 t5 Z% Z8 |  [) q
微信图片_20231207152903.jpg 4 a2 `1 `" |% _
% J' P8 [. Z! |- t
即变量 A 在明明没有变化且条件不满足的情况下, 程序运行时偏偏执行了条件内部的代码. 很奇怪的现象。一时很难判断是编译器的问题还是芯片问题., r7 @' R# @  ^* K
% I- N" J0 x% {) K$ J  _* B
了解到客户的代码中使用了第三方库, xx.o 文件, 像这样的条件有 80 多个, 每次出现问题的具体变量并不是固定哪一个, 但是在大概 10 分钟内肯定会有其中一个出现执行逻辑问题。随意动一下代码问题就不出现, 或者出现的位置发生变化 ; 用 KEIL 编译器去设置断点, 想看该变量信息, 也会导致问题不再出现。% V* {8 h# Y& h! {4 ]0 k

0 A  `! S2 `) q- q# z" ?% t$ q02问题分析
. R& h" L- q, g# x! x( k) M一开始查看 errta sheet, 看到以下相关内容 :
2 `$ u4 T+ S  t7 t2 G% n, T  Q
微信图片_20231207152900.jpg
4 t, m6 g) y( }% _8 j" o
7 A( e  N8 w0 z6 J  c+ i* E) F* I, \
即怀疑问题跟 AXI SRAM 相关. 查看客户的这些变量, 确实是存放在 AXI SRAM 中. 由于任何修改代码都可能导致问题不再出现, 因此所有尝试须建立在不修改代码的基础上, 不然无法说明问题。
( Y8 u4 J1 g# D* g3 L# a
8 O/ u7 x; l  W于是让客户用 STM32CubeProgrammer 以 hot plug 模式连接 MCU, 按照勘误手册中 2.2.9 节所描述的 workaround 方式将 AXI_TARG7_FN_MOD 寄存器的 READ_ISS_OVERRIDE 位通过地址的方式直接修改 :# k0 y  Y$ {8 R

! \7 ~5 ?' D2 i' X. @6 l4 X* e8 _
微信图片_20231207152856.jpg
4 e  m* k: ?: G+ u5 A$ ~. _

/ `) K* ]% Q: h9 J, o% P结果发现并没什么效果. 于是排除了这种可能性. - j  Z; b3 M2 U

0 ~) F( M  R8 S% j' v) k* y4 X) p一开始也怀疑问题可能跟 Cache 有关, 于是测试下关闭 Cahce 会怎么样. 通过 KEIL 调试模式下,暂停住 CPU 运行, 然后手动关闭 D-Cache :: \- g& ?5 n' F0 S4 z$ ?

! M4 k: [8 A. S% j/ D8 i
微信图片_20231207152853.jpg 3 y; y0 \' v( m
/ \! @& _4 N6 i/ L
结果发现问题消失不见 ! 说明问题肯定跟 Cache 有关.
! K; k1 l3 e- p8 \% O2 b8 O
! J# a) X( H( L2 \但客户的代码最终肯定是不能关闭 Cache 的, 想到内核中有一个寄存器可以打开全局 Cache 的write throght 模式, 如下编程手册中的 CACR 寄存器的 FORCEWT 位 :
* L, B( s" a" n6 H( y, @% c  ?3 @" E4 N" M2 Y" \
微信图片_20231207152849.jpg
: O1 t, b% h' h! C+ A3 ~0 \; W5 Z/ u* ?) j
结果发现, 客户的代码本身就已经打开 :1 [& q% z' J% X/ O0 b% n2 ^
. j0 M7 B' f+ ?" O' b3 ^7 L4 V: }# G
微信图片_20231207152846.jpg
; d" I% _$ _1 o& X; R# }3 i$ e- a  b# C! M! H( N* [% X
看样子此模式与此问题无关. 得换个思路. . a( I, E. L9 T) S) X
4 l% j2 \' F+ n" P" X
考虑到问题跟内存数据有关, 代码又不能动. 但是得想办法让内存中数据的位置动动, 看看会有什么效果 ?
1 b: A- x2 ~' e1 i3 I2 d9 E9 d3 C. V
8 \* I5 P( _; _2 w& A/ h0 y通过修改 KEIL 的链接配置文件.sct 文件, 将变量随意动动, 结果发现问题也会消失不见 ! 这说明,数据的地址跟问题绝对有关联.那么具体是哪些数据呢 ?
" V/ U3 F) z, `
. L6 b1 M% |# s
为了精确定位到与哪些变量有关, 查看 KEIL 生成的 map 文件, 按地址倒序将每个程序中所用到的.o 的对应变量逐个挪移动 DTCM RAM 中.
% r5 c& Z* u2 c4 q% a
7 s+ E. x$ G9 i2 t: w% Y5 K
微信图片_20231207152843.jpg 4 @; p# @2 n& O

  b* G, g. ~9 `. ?为什么要倒序呢? 主要是因为, 假如先挪低地址的变量, 肯定会导致高地址的变量向低地址移动.这好比, 如果先抽掉下面的砖头, 那么上面的砖头会自动移动下面去. 假如先抽掉上面的砖头情况就不一样了, 下面的砖头还会保持不动. 这就是为什么先挪移上面的砖头的意义, 也就是所谓的倒序.3 e! H2 k- M' b5 f* B& y* J

$ }# I% R' t/ {, q( a; \9 Y" `6 o通过这种方式, 最终定位到问题跟 heap_4.o 文件以及用户使用到的第三方提供的 xx.o 文件中的ZI 数据有关. 只要保持这两种数据位置不变, 那么问题就可以稳定触发, 一旦其中任何一个位置有所变动, 问题就消失不见.) i; |/ U3 p/ ^( |

3 H" H! t9 Y1 w+ k4 g! e
微信图片_20231207152840.jpg 1 h$ X* m9 n5 V# O
6 k% Q- q& h+ I  @$ a. ?
现在我们知道规律了, 那么只要固定好这两种 ZI 数据位置不变的情况下, 再去尝试修改代码, 结果发现, 此时修改代码不再会对结果产生影响! 换句话说, 现在可以自由修改代码了. 4 p/ n4 B; Q. U! n1 u" {
' s$ x4 X& H  s; c; L
考虑到此问题与 Cache 有关, 于是接下来通过 MPU 设置将 heap_4.o 所在区域的 Cache 功能关闭, 结果发现问题消失.8 h2 R+ w4 g' N6 D* s
3 ~: a6 p2 H  w
微信图片_20231207152836.jpg / c6 _# g* Z: a
3 n- I* e- ~1 ~. h; I& z, n
微信图片_20231207152833.jpg
' e( h9 E" {3 o+ Y2 k  ?( W6 }5 m

1 f1 V5 U) @; f, D5 pHeap_4.o 的 ZI 数据是存放在 SRAM2 中的 0x3002 E050 位置.
; I2 w6 C! W/ q% V" J: E- b6 U: V/ V( k3 @3 O
微信图片_20231207152830.jpg . P, E  _4 N4 |# ~
微信图片_20231207152819.jpg 4 ]" o4 z& _( R* g! {/ S  M

( A) w* n* ]! r% ^* K" Q9 @现在的现象是,Heap_4.o 的 ZI 数据只需要固定在这个位置, 问题就能稳定重现,只不过将其对应的cache 关闭, 问题则消失.( K( a8 ^" V' r4 o& K) {
& \$ o1 W+ f2 @- f6 @2 m
那么此区域默认的 Cache 属性是怎么样的呢? 这个在 AN4839 中可以找到其默认属性:) ?2 k9 ~8 b3 U7 K4 T

# B$ O* q. x+ P- y4 V3 `" n
微信图片_20231207152816.jpg
+ L8 W. E, `8 d: Z; f- Z9 v: ?" M" H1 `0 Z, J" @8 D
于是我们通过代码, 将其 MPU 属性再次配置其默认属性:# p* I* N5 `% _. I" [5 X3 [7 j
4 h5 \& y- G: n2 |: s- d
' X7 Z4 a% x2 d; ~! S* ?+ Z" {

5 ]: X6 S8 U5 x0 u 微信图片_20231207152809.jpg $ ~8 ~: K- o7 H. V7 s" {
3 U1 v' ?0 U7 Y# [$ Z2 B2 z
结果问题可以重现. 这再次说明, cache 属性对结果有影响.
- w* S8 L7 ^& W- Q+ P, L
( x/ Z# Y" ?2 `, z# n5 I8 r
但是此时还无法对其产生的过程细节进行解释.6 V5 _/ D# T( c
: D1 V) P8 r7 W. f6 j$ D
与此同时, 尝试关闭客户使用第三方库 xx.o 文件中的数据 cache, 问题也同样会消失。这说明, 此问题跟客户所使用的第三方库是有关系的, 其数据在 cache 中产生了一致性问题.
7 y1 S. ~, O& e7 @- F% `5 K4 a

' t+ N! {; E7 F& r于是询问客户这个第三方库是如何来的? 他们回复是一家欧洲公司提供的, 且是以 M4 内核编译的.) J, l& k9 D! P
. S7 J, U1 I; u+ i  t$ _6 u- c
很明显, 在使用原则上, M4 编译出来的.o 文件, 就不应该用在 H7 工程上. % x" n8 A, Z) x% k9 |3 I

1 ^1 ^1 \6 M. b) e5 N以 M4 为内核编译的.o 文件放到 M7 工程中会产生什么样的影响? 虽然理论上, M7 内核的指令集是向下兼容的, 但是也需要考虑 M7 内核相关的一些特性, 比如 Cache, memory barrier 等等. 不能完全确保不会出问题, 最保险就是重新以 M7 内核编译这个.o 文件. , U; J# q- c2 _! p- v3 z. ]$ I7 A

3 i% F8 t$ l( d' ~7 D# M* j) C由于这个第三方.o 文件客户自己也是无法知道其内部是如何实现的, 因此, 问题的具体产生过程是没办法进一步调查了. 但定位到这个.o 文件已经是当前能得到的最终结果.
. i7 B) b: h+ N
& y" E- `; h) D& _: @. r03小结( V  x3 n( S9 Q) v/ |; s+ c
本文最终问题的真相虽有点匪夷所思, 但这正反映了当前国内软件应用上的混乱情况. 本文所描述的问题根本原因虽然很另类, 但所涉及到的方法却对开发者有一定的参考意义, 在不能动代码的情况下, 需要挪动数据的位置, 这就必须对编译器有一定的了解. 虽也不至于太难, 但对很多开发都来说, 对编译器的了解未必很深, 因此, 一开始很多人就会卡住。另外, 对 MPU 的了解也是一大门槛. 因此, 特奉上此文, 以供参考.
- d; C1 _. t2 V
4 Q! {, T* _5 u9 v7 i' p5 g转载自: STM32单片机
5 P0 ~6 L3 }2 S, M- X1 A) {如有侵权请联系删除. V% B- X" K( [

  f% o2 o9 \, R3 C9 y0 T" Z5 o- H4 e/ b1 u' d
微信图片_20231207152812.jpg
赞 收藏 评论0 发布时间:2023-12-7 15:29

举报

0个回答

所属标签

相似技术帖

官网相关资源

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