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

在STM32中一个跟Cache有关的通信应用异常话题

[复制链接]
yumeii 发布时间:2020-1-6 15:32
曾经有STM32用户反馈如下情况:
$ w* S& S6 t2 A7 |5 A  p9 E1 K5 f8 a" h3 }" b3 j8 W

  X2 X4 ]9 N* w1 `选择STM32F7芯片开发产品,使用了USART1的DMA接收和发送,并开启了USART1的IDLE中断,IDLE中断正常,能成功接收到数据。通过仿真能看到接收缓冲区数组中的数据,但就是不能访问它。如果不访问,重新开启DMA接收能正常接收,并且在仿真状态下也能查看。只要访问一次这个接收数组,下一次开启DMA接收就不能接收数据了。2 Q, I( R# z8 {4 R; S& u$ p

$ }. J/ l; {, |! j8 {  l5 k' q! p

. m0 b+ P8 q# ^0 u/ J; A' @客户还补充说,之前使用STM32F1芯片时实现同样功能没有任何问题。
' V0 \, y( i" p2 |9 v3 n4 i* \+ q5 s* b" i8 T8 F3 d8 p4 `& E

# [/ R8 q! b/ _从客户的反馈来看,他是说不能对接收到的数据进行读取访问,读取之后就再也不能接收后续数据了。这样说听起来有点玄乎。; _- R* t7 v& n7 r8 q
1 i5 {  U8 m8 \+ n
" F* w) A/ M- c* D0 z
随便找块STM32F7的nucleo板进行验证测试,反复验证确认,没有发生客户所说的现象。我在程序代码中也加了对接收数组数据的读取操作。使用循环模式不停让DMA进行UART的收、发,并不时修改发送缓冲区的数据,接收端一直能正常接收,收、发端数据完全一致。【如下图所示】7 ]7 H4 W: D0 M0 m) H8 E

6 ]# z/ N% i  n) d) m  q) Y
7 J# z2 d# G+ G" a4 z1 G
1.png + |2 c$ I- j- q: x6 r
0 _) f4 z2 M; @) ~$ }7 L

0 Q" |+ {+ N9 o既然不存在客户反馈的读取接收数组后就无法继续接收数据的问题。那客户的真实问题到底是什么呢?要表达什么呢?后来进一步得知,客户的代码中有如下语句,它会读取接收缓冲的数据。
. D% T- L/ C& Z& \: `) m2 M5 v
( X# H  C0 A0 W/ d& p- f7 z
7 D2 U+ @) U( [) c6 U4 ]* P
2.png % S+ p* ~! E9 K- z9 r! O

; n" ~# \; X5 {% m
7 {3 K7 s5 c! d/ G( w+ J( D
客户补充说,程序不能执行上面代码,否则就不能再接收后续数据了。屏蔽掉这条语句在仿真状态下能观察到aRxBuffer接收正常。0 z, }0 w8 j* q( U
/ l( g* c' }) G6 ^4 _) w' `
* o- b6 [; {4 a
现在事实上并非他所表述的那样,他真正要表达的是自从读取该接收数组数据之后,不管后续的收发数据怎么变化,他从这个函数里都没法从接收缓冲区读到新数据并显示出来。4 H5 f& I, _0 C+ n5 g8 i9 ~4 q7 T

- j. r( `' l6 m4 R* M
6 X  M% W# I. v- M" a
我在测试代码里也写了类似代码,顺便瞧瞧结果。我在测试代码了建了个临时观察数组temp[],从接收数组aRxBuffer里读取几个数据存放进去。
' A+ q9 w! r0 x" ^" @
; |$ _* k3 L9 z; J/ x% z& ^( |: v: ]& n
4 f* f. c# J9 r% `& ?7 O  a
3.png 3 P9 E9 o0 e3 N5 p- ^" K

( H; c' w9 w! B' x+ Z$ {9 L* q
) N! t6 L$ Q" i
测试中可以发现,无论怎样修改发送缓冲区aTxBuffer的数据,接收数组aRxBuffer的数据都会同步变化,但这个temp[]数组里的数据永远都保持第一次发送/接收到的数据。/ r) p2 f' M8 Q/ L. `, d) ~+ |; l8 j
. w; n; o& Y; w
) s  O5 K5 q: O7 W/ R. j
4.png % a0 F; ?1 e$ f2 Z0 m3 x
3 U+ i' n6 C: ^0 W2 \* K( n
3 z9 [1 d2 _& i
看到这里,结合测试现象大致得知原因了,问题应该跟D-cache数据与实际存储区数据一致性问题有关。
& r3 ^  s$ G! {- i7 B3 Y2 Y
3 p8 r. o: a* h, [/ ?+ D# A
) j: c3 e3 l: w8 y. B7 ^8 B
STM32F7系列芯片支持高速I-Cache和D-CACHE,接收数组aRxBuffer内存区数据默认可以使用D-cache,使用它可以大大提高CPU的访问速率。不过,使用D-Cache要注意实际物理存储区与高速缓存区的数据一致性问题。
+ A" E9 [; m2 E, |- s8 z- Y  H8 c# p+ M) q- u( \6 t

' g; E7 W4 s3 y5 e. p具体结合本案例,发送缓冲区的数据通过UART发送出去后,UART数据寄存器接受到数据后,DMA将数据写入接收缓冲区RxBuffer[],CPU从RxBuffer[]将数据读进Temp[]数组。5 [; ^7 k5 `# y$ C% f7 l
0 _4 u4 F* a+ S$ r

9 ?9 N- W* w0 w, o9 u在使能D-Cache的前提下,CPU第一次读取接收数组的数据到Temp[]数组后,并将相应数据放入D-cache进行缓存。之后,CPU再来读接收数组的数据时,并没有前往接收数组实际物理存储区去读取数据,而是直接去D-cache里读取数据了。由于Cache数据没有做更新,这样的话,即使接收数组Rxbuffer数据变化了,D-Cache里的数据并未相应改变,所以就出现了CPU从Cache里读到的数据总不变的情况,给人一种后续数据没有接收进来的错觉。8 W1 W$ ~8 O- y

% e2 C$ T( h# F, P5 [2 y
! m: f! p- {# O' w7 p5 l5 m
5.png " I) T- H% D! Q

5 A( L! i) L: h

. M: R- S2 W0 M0 |& p那如何解决这个问题呢?方法较多,可以根据具体应用情况而定。这里介绍两种方法:
9 v5 Z, q" ]1 d1 R0 A# Z  u; ~
: }9 B+ g, r/ {
1 g; D9 t# Q7 Q
1、每次读取接收数组的数据之前先对D-cache做个清除操作或者说刷新操作,让实际物理存储器里的数据与Cache里的数据先做同步更新。相应的STM32库函数代码为:SCB_CleanDCache ( );! R- o/ N9 s5 `  u# G2 e

1 N* C5 [# V# s0 S( j

8 G7 z  }$ n- ^5 ^8 G* M* J6 m+ \2、在读取接收数组的数据之前先做个D-cache失效操作,这样让CPU无视D-Cache而直接去实际物理存储器区读取数据。相应的库函数代码是SCB_InvalidateDCache();
, |3 R9 Z7 H- R0 {$ b
/ P+ L) L7 y" x

4 f3 t% B! _" H+ H7 R% P经过验证测试,两种办法都可行,也不再出现客户反馈的异常现象。; f3 {5 w6 A8 K5 u; l6 e

/ B' ~2 x: ?* h" ?1 R7 e

2 R) m# \7 ^& e3 ?; q 6.png
3 d* S" j5 D5 [
+ K; D! u! j4 M8 Q1 E

& F- T6 D* x+ m0 @关于带D-Cache的多主存储访问过程中的数据一致性问题,既可能发生在CPU对某可缓存存储区进行写操作,DMA对相应存储区进行读操作时,也可能发生在DMA对某可缓存存储区进行写操作,CPU对相应区域进行读操作的情形。本案例就是后面第二种情形,在该情形下,为了保证SRAM与D-Cache里数据的一致性,在CPU对SRAM区数据读操作之前,须针对D-Cache进行失效操作。
  l8 ?/ D$ j7 q- M3 j  \: R: l2 ]
; D6 V! Y9 j: K, z( \: j8 G
关于STM32 D-Cache及数据一致性问题,已经不少文章介绍,这里不再赘述。在此分享该实际案例,一方面是为了加深相关知识的了解,另一方面是为了多引起应用工程师对相关问题的关注。毕竟因D-Cache一致性导致问题时也是相对比较隐蔽的,加上以往低端MCU也没有这类东西,缺乏经验积累,应用中容易被忽视而找不到原因。
! x' t# V7 @' I  \5 T4 c# i) W0 Z3 G- [  o1 X% v
赞 收藏 评论0 发布时间:2020-1-6 15:32

举报

0个回答

所属标签

相似技术帖

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