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

【经验分享】对 Flash 操作导致 USART 接收丢数据

[复制链接]
STMCU小助手 发布时间:2022-2-19 17:16
问题:
, k. N9 ^& d* a+ W1 O) T3 G" H该问题客户提出,发生在 STM32F103VDT6 器件上。据其工程师讲述:在其产品设计中,使用了 STM32片上 Flash 模拟了一个 EEPROM 的功能,用于存贮数据。在软件调试时,发现开启此功能,会影响到USART 通信,导致偶尔发生个别数据接收不到的现象。
* f+ ]% I# [6 D! b% J, t( Y调研:
! h, Q6 [8 a2 h检查其软件代码,发现其中对 Flash 上数据的更新操作分为如下几个步骤:
/ @- [/ X* B% L2 F1 S0 S( G0 t" F1. 保存 Flash 页上的数到 RAM 中;
7 k; a* H0 h; X. S3 f2. 擦除 Flash 页;
) G: }. @4 P; O3. 修改 RAM 中的数据;
) u% M/ n& R: \- S  u* S7 @4. 将 RAM 中的数据写回 Flash 页上;
9 o# K$ W- L: R   对照 STM32 的数据手册,查找到相关的数据:
# y3 B7 z0 d" x9 G) Q: m1. 字写入时间 40uS ~ 70uS;
$ P4 l" }2 n: N2 Y! C& `2. 页擦除时间 40mS;
' u4 E2 c3 o% z/ ^, _$ t( a   检查软件代码,找到对 USART 的设置:
/ T; z" ^2 P( l! e" ]: P1. 波特率 115200BPS;
  n! w7 w" O; R# x& G2. 帧格式为 1 个起始位,8 个数据位,2 个停止位;2 j# L: b( m9 b) {0 S
   检查软件代码,发现其对 USART 的接收数据采用中断的方式进行读取。5 ?, a7 G% ^/ n, f% Q

. f/ a! W& _3 B* S8 d* x  e 结论:9 \* l' V2 t/ a
   通过计算,USART 的每个字节帧的传输时间为:7 q3 r- Q, P/ L
  Z- H0 f- a! f  o9 w% U4 l
P_[PBNS69U_TBPX8JE~)HHI.png % G; p9 @8 L: L9 P; A0 n
1 n$ e: p) V# B* ]8 ~! c
   该时间大于 Flash 的字写入时间,小于 Flash 的页擦除时间。所以,在 Flash 页擦除期间有可能发生多次字节帧的传输。而在此其间,由于 Flash 接口不可用,CPU 不能取指令,导致中断得不到及时响应,从而发生接收到的数据未及时读走而被覆盖的现象。
( Y2 h3 ~2 D* q, m( p- Q$ h' }* |  A$ x  ^( T* h; \/ w" J
   处理:
# g* `4 x4 p. n6 E   在内存中建立循环缓冲区,开启 DMA 通道。一旦 USART 有数据接收到,由 DMA 负责将其传输至循环缓冲区中。软件定期检测循环缓冲区中是否有接收到的数据,如果有则加以处理。5 S* H, b: E9 ~4 r- S

4 h! L8 n1 `5 o7 @! o   建议:
/ F0 q- e  ]6 H& }9 l+ w   在只有一个 Flash 模块的 STM32 中,对 Flash 接口的使用具有独占性。该接口不能同时进行多个操作,比如,在写操作的同时进行读取操作,或在擦除操作的同时进行读取操作,既便读、写操作的地址不同,或者所读数据不在被擦除的页上。因此,当程序运行在 Flash 上情况下,在对 Flash 进行写入、擦除操作时,往往会因为 CPU 取不到指令而造成程序执行的停顿。这一现象会引发系统对外部事件响应上的不及时,必须采取相应的措施加以避免。通常,对于通信接收数据这类事件,可以使用DMA 进行辅助,避免数据被覆盖。对于外部中断、定时事件等必须要软件及时响应的事件来说,可以将中断向量表转移到 RAM 中,同时将中断服务程存放在 RAM 中执行。CPU 的 VTOR 寄存器用来存放中断向量表的偏移地址,修改该寄存器的值,可以改变中断向量表在内存空间中存放的地址,详见Cortex-M3 的技术参考手册。在 IAR 开发工具下,定义一个在 RAM 中执行的函数,可以使用其扩展关键字__ramfunc,举例如下:% z; I+ l: ~; N9 s2 [7 ]

8 h$ y& }8 \% C8 T8 W$ n/ j J0R5FXJL5[VVQ8SMP}20{L6.png
! e  u! D% g( R0 @' \8 S/ u( Y" E: m% @) n: f' f- d1 J
   在 Keil RMDK 中,可以将相关的中断服务程序单独放在一个“.c”文件中,然后通过修改 scatter 文件来实现 RAM 中执行,例如中断服务程序放在“exti9.c”中:, _8 B4 G# w, @3 _2 L. _

# h6 R, q$ B4 ~4 p8 P0 n; U 9I7@IN@~_LIE0I7UEPH$WW9.png ; A& _- K& }( t0 B4 f/ B) L, @
1 A8 P: l  N( f% t9 l
   再从另一个方面考虑该问题,导致程序发生执行停顿的一个关键原因是对 Flash 进行了写或者擦除操作。如果在排除这一原因,也就不会发生程序执行停顿了。所以,要解决这一问题,可以将数据暂存在 RAM 当中,而不是每次修改后都立刻更新 Flash。可以利用 STM32 的 PVD 功能监控电源电压,发现有掉电倾向立刻启动写 Flash 操作,将 RAM 中暂存的数据写到 Flash 中。这样,在整个 STM32 运行期间,只有到了最后时刻才对 Flash 进行了写操作,而这时也不需要再响应什么事件了(也没时间响应了)。这是一个不错的思路,然而很多细节需要仔细斟酌。首先,为了节约这最后时刻的每一个微秒的时间,Flash 页面的擦除操作是要提前完成的。将这一操作放在 STM32 开始监控各种事以后自然不妥,因为这同样会造成对事件响应不及时。看来,最佳时间段只有系统初始化阶段了。其次,在擦除 Flash 期间发生掉电要如何处置?这时,备份在 RAM 中的数据会来不及写回 Flash 而丢失。为了避免这一情况的发生,可以使用双页交替存贮的方式(传说中的乒乓操作)保存数据。两个 Flash页上分别存有两个版本的数据,一新一旧,并在最后附有版本号及校验和。系统初始化时,选择的旧版本页面或无效页面进行擦除。这样,既便此时发生掉电,也无须向 Flash 写回备份数据,因为最新数据仍在 Flash 中。而每次向 Flash 更新数据时,都以更新的版本号进行标注,原来的新本数据自然的变成了旧版本。再次,为了尽量延长最后的可用于写 Flash 的时间,尽量降低系统功耗是非常有必要的。关掉 PLL,接直使用 OSC 送来的时钟作为系统时钟,可以明显的降低功耗。关掉所有外设的时钟可以进一步降低系统的功耗。根据片外电路的特性,调整 I/O 的输出状还能进一步降低系统功耗……! e- G! C. Q* ]! s6 |4 ]$ D

$ P* Z% v8 X8 q3 L3 C
赞 收藏 评论0 发布时间:2022-2-19 17:16

举报

0个回答

所属标签

相似技术帖

官网相关资源

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