标题:
Flash擦写操作导致USART接收丢数据的话题
[打印本页]
作者:
掘金小分队
时间:
2017-3-29 10:20
标题:
Flash擦写操作导致USART接收丢数据的话题
问题:
该问题由客户提出,发生在
STM32F103VDT6
器件上。据客户工程师讲述
,
在其产品设计中使用了
STM32
片上
Flash
模拟了
EEPROM
的功能,用于存贮数据。在软件调试时,发现开启此功能,会影响到
USART
通信,导致偶尔发生个别数据接收不到的现象。
调研:
检查其软件代码,发现其中对
Flash
上数据的更新操作分为如下几个步骤:
1.
保存
Flash
页上的数到
RAM
中;
2.
擦除
Flash
页;
3.
修改
RAM
中的数据;
4.
将
RAM
中的数据写回
Flash
页上;
对照
STM32
的数据手册,查找到相关的数据:
1.
字写入时间
40uS ~ 70uS;
2.
页擦除时间
40mS;
检查软件代码,找到对
USART
的设置:
1.
波特率
115200BPS
;
2.
帧格式为
1
个起始位,
8
个数据位,
2
个停止位;
检查软件代码,发现其对
USART
的接收数据采用中断的方式进行读取。
结论:
通过计算,
USART
的每个帧的传输时间为:
t=(1+8+2)/115200=95.5uS
该时间大于
Flash
的字写入时间,小于
Flash
的页擦除时间。所以,在
Flash
页擦除期间有可能发生多次字节帧的传输。而在此其间,由于
Flash
接口不可用,
CPU
不能取指令,导致中断得不到及时响应,从而发生接收到的数据未及时读走而被覆盖的现象。
处理:
在内存中建立循环缓冲区,开启
DMA
通道。一旦
USART
有数据收到,
DMA
负责将其传输至循环缓冲区中。软件定期检测循环缓冲区中是否有接收到的数据,如果有则加以处理。
建议:
在只有一个
Flash
模块的
STM32
中,
CPU
对
Flash
接口的使用具有独占性。该接口不能同时进行多个操作,比如,在写操作的同时进行读取操作,或在擦除操作的同时进行读取操作,即便读、写操作的地址不同,或者所读数据不在被擦除的页上也不行。因此,当程序运行在
Flash
上情况下,在对
Flash
进行写入、擦除操作时,往往会因为
CPU
取不到指令而造成程序执行的停顿。这一现象会引发系统对外部事件响应上的不及时,必须采取相应的措施加以避免。
通常,对于通信接收数据这类事件,可以使用
DMA
进行辅助,避免数据被覆盖。对于外部中断、定时事件等必须要软件及时响应的事件来说,可以将中断向量表转移到
RAM
中,同时将中断服务程存放在
RAM
中执行
。
CPU
的
VTOR
寄存器用来存放中断向量表的偏移地址,修改该寄存器的值,可以改变中断向量表在内存空间中存放的地址,详见
Cortex-M3
的技术参考手册。
在
IAR
开发工具
下,定义一个在
RAM
中执行的函数,可以使用其扩展关键字
__ramfunc
,举例如下:
__ramfunc void EXTI9_5_IRQHandler(void)
{
If (EXTI_GetITStatus(EXTI_Line9)!=RESET)
{ /*clearthe EXTI line9 pending bit*/
EXTI_ClearITPendingBit(EXTI_Line9);
……
}
}
在
Keil MDK
中
,可以将相关的中断服务程序单独放在一个
“.c”
文件中,然后通过修改
scatter
文
件
来实现在
RAM
中执行,例如中断服务程序放在
“exti9.c”
中:
LD_ROM 0x8000000 0x10000
{
EX_ROM 0x08000000 0x10000
{
Startup.o(RESET,+FIRST)
ANY(+RO)
}
EX_RAM 0x20000000
{
exti9.o(+RO) ;
将中断服务函数放在
RAM
中
}
RW_RAM +O
{
startup.o(STACK,+ZI)
.ANY(+RW,+ZI).
}
}
话题延伸:
我们再从另一角度来思考和探讨该问题,抛砖引玉吧。
显然,导致程序发生执行停顿的一个关键原因是对
Flash
进行了写或者擦除操作。如果再排除这一原因,也就不会发生程序执行停顿了。所以,要解决这一问题,可以将数据暂存在
RAM
当中,而不是每次修改后都立刻更新
Flash
。可以考虑利用
STM32
的
PVD
功能监控电源电压,发现有掉电倾向立刻启动写
Flash
操作,将
RAM
中暂存的数据写到
Flash
中。这样,在整个
STM32
运行期间,只有到了最后时刻才对
Flash
进行了写操作,而这时也不需要再响应什么事件了(也没时间响应了)。这是一个不错的思路,当然,很多细节需要仔细斟酌。
首先,为节约这最后的每一微秒时间,
Flash
页面的擦除要提前完成。若将这一操作放在
STM32
开始监控各种事情以后自然不妥,因为同样会造成事件响应不及时。看来,最佳时间段只有系统初始化阶段了。
其次,在擦除
Flash
期间发生掉电要如何处置?这时,备份在
RAM
中的数据会来不及写回
Flash
而丢失。为了避免这一情况的发生,可以使用双页交替存贮的方式(传说中的乒乓操作)保存数据。两个
Flash
页上分别存有两个版本的数据,一新一旧,并在最后附有版本号及校验和。系统初始化时,选择的旧版本页面或无效页面进行擦除。这样,既便此时发生掉电,也无须向
Flash
写回备份数据,因为最新数据仍在
Flash
中。而每次向
Flash
更新数据时,都以更新的版本号进行标注,原来的新本数据自然的变成了旧版本。
再次,为了尽量延长最后的可用于写
Flash
的时间,尽量降低系统功耗是非常有必要的。关掉
PLL
,直接使用
OSC
送来的时钟作为系统时钟,可以明显的降低功耗。关掉所有外设的时钟可以进一步降低系统的功耗。根据片外电路的特性,调整
I/O
的输出状还能进一步降低系统功耗。
融创芯城(一站式电子元器件,PCB,PCBA购买与服务,项目众包、方案共享平台)
19W 120V TRIAC调光
LED
驱动
智能插座电源方案
基于STM32F103的BACNET 控制模块
STemWin智能手表UI设计
15 W无线充电发射器解决方案
智能手机3.5mm耳机数据传输解决方案
以上是平台免费方案,有需要可前去下载哦!
http://www.digiic.com/Solution/Index
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0