无限循环并不是防止程序“跑飞”的,而是防止main()返回 | 您所在的位置:网站首页 › FLASH编程挂起和擦除挂起 › 无限循环并不是防止程序“跑飞”的,而是防止main()返回 |
Flash存储器已成为嵌入式系统中数据和程序最主要的载体。但是在对Flash进行
编程或
擦除的操作过程中,如果
单片机需要处理一些紧急的情况(如中断、数据存储等等),就需要暂停相对比较消耗时间的Flash编程/擦写过程,优先处理这些紧急情况。这对Flash存储器的工艺水平及控制技术提出了更高的要求。
瑞萨公司推出的R8C/1B单片机采用改进的Flash存储器工艺,大大缩短了编程/擦除挂起的时间,使其能够更加及时地响应中断或进行其他操作。 Flash编程/擦除挂起功能 所谓挂起功能,是指当Flash模块正在执行编程或擦除操作时,CPU改写模式可以暂停当前的Flash操作,将编程或擦除挂起的功能。在编程/擦除挂起的过程中,用户ROM区的内容可通过程序来读取。 瑞萨R8C/Tiny单片机在R8C/18以后的产品中(如R8C/1B),较之以前的产品(如R8C/15),Flash存储器在编程/擦除挂起功能上有了很大改进,其具体功能的比较请参见表1,编程/擦除挂起操作时序请参见图1。 由表1可以看出,R8C/1B单片机所采用的Flash模块工艺在以下方面拥有明显的优势。 挂起时间延迟最长为97μs+6个CPU时钟周期,最长的挂起重新启动时间延迟为3μs+4个CPU时钟周期;R8C/15单片机Flash模块只能在擦除时挂起,但改进Flash工艺的R8C/1B单片机在编程时也可以实现挂起功能;擦除时可以编程。 图1为编程/擦除挂起的简单示意图,在编程/擦除开始之后,如果发生了某个中断请求,在等待一段挂起延迟之后,CPU转向中断子程序的处理。中断处理子程序执行之后,Flash存储器继续执行编程或擦除过程,直至操作结束。 Flash编程/擦除挂起功能的实现 ● EW0模式与EW1模式 CPU改写模式是通过固化在单片机程序存储器中的软件命令对Flash存储器进行编程的形式,适合对单片机进行在应用中编程(IAP)的场合,即能够在不使用Flash编程器,且将单片机安装在电路板的状态下实现对Flash的改写。 CPU改写模式分为擦除/编程0模式(EW0模式)和擦除/编程1模式(EW1模式)。 这两种模式的根本区别在于改写控制程序的执行区域不同。如图2所示,EW0模式中,改写控制程序在Flash存储器以外的区域执行,因此在这种模式下可以改写所有的用户ROM区。EW1模式中,改写控制程序依然存放在用户ROM区的某一个块中,并在此区域执行,因此在这种模式下,除了存有改写控制程序的块以外,其他的用户ROM区都可以被改写。 在执行擦除/编程的过程中,在EW0模式下CPU处于正常运行的状态,而在EW1模式下CPU处于保持状态。 ● Flash编程/擦除挂起的设定 相关的寄存器 与Flash编程/擦除挂起相关的寄存器是闪存控制寄存器4(FMR4),FMR4有6个位均与编程/擦除挂起功能相关,请参见表2。
EW0模式的擦除挂起设定 对于EW0模式转移到擦除挂起时,首先需要将FMR40位置“1”(允许挂起)、FMR41位置“1”(请求擦除挂起),然后延迟一段时间(97μs+CPU时钟周期×6),在确认FMR46位为“1”(允许读)后才能对用户ROM区进行存取。如果将FMR41位置“0”(重新启动擦除),就重新开始自动擦除。设定过程如图3所示。注意,在EW0模式,请将所使用中断的中断向量表和中断程序存储在RAM区中。 EW1模式的擦除挂起设定 对于EW1模式,首先需要将擦除挂起功能设定为有效,即将FMR40位置“1”(允许挂起),并预先将需要响应的可屏蔽中断设定为中断允许状态。这样在执行块擦除命令后,如果该中断产生,经过一段时间延迟后(电气特性推荐值为:97μs+CPU时钟周期×6),就能执行擦除挂起,并接受中断请求。如果发生中断请求,FMR41位就自动变为“1”,执行擦除挂起。在结束中断处理后,如果自动擦除还没有结束(FMR00位为“0”),就必须将FMR41位置“0”,重新开始自动擦除。设定过程如图4所示。 在EW1模式下执行擦除指令进行Flash擦除时(典型值为200ms/1K字节块),CPU虽处于HOLD状态,但可以接受中断响应,实现分时擦除。利用这个工作原理,下面给出一个R8C/1B单片机的应用实例,利用Timer(定时器)中断和Flash擦除挂起功能实现对擦除时间的估算。 使用TimerX定时1ms,Flash擦除过程中每1ms挂起一次,进入中断处理程序并调整计时变量g_Timers。在擦除结束后,g_Timers所存储的就是擦除时间的估算值。 例程如下。 #include "sfr_r81b.h" unsigned int g_Timers;//总擦除时间计数变量 /* 定时器X中断处理函数 */ #pragma interrupt timerX_ISR void timerX_ISR(){ g_Timers++; } /* 检查Data Flash状态寄存器 */ unsigned char checkStatusRegister(){ return fmr07|fmr06; } /* 清除DataFlash状态寄存器 */ void clearStatusRegister(){ *((unsigned char *)0x2400) = 0x50;//执行清除状态寄存器软件命令 } /* 块擦除 */ unsigned char eraseBlock(unsigned int adr){ unsigned char result="1"; asm("FCLR I");//关中断 fmr01 = 0; fmr01 = 1;//进入CPU改写模式 fmr11 = 0; fmr11 = 1;//设置为EW1模式 fmr40 = 0; fmr40 = 1;//允许中断擦除挂起 asm("FSET I");//开中断 g_Timers = 0;//计数值清零 prex=0x32-1;tx=0x32-1;//定时值1ms txs=1;//定时器X开始计数 *((unsigned char *)adr) = 0x20;//执行块擦除软件命令 *((unsigned char *)adr) = 0xD0; while(fmr00 != 1){//判断擦除是否结束 fmr41 = 0;//中断返回后继续擦除 } txs=0;//定时器X停止计数 fmr01 = 0;//退出CPU改写模式 if(!checkStatusRegister()){//查看状态寄存器 result = 0;//擦除成功 } else //擦除失败 clearStatusRegister();//清除状态寄存器 return result; } /* 对MCU进行初始化 */ void initMCU(){ unsigned char i="0"; asm("FCLR I");//关中断 //将CPU时钟切换为主时钟20MHz prcr = 1;//解除对cm0,cm1,ocd寄存器的写保护 cm13 = 1;//接通 Xin-Xout cm15 = 1;//Xin-Xout驱动能力:高 cm05 = 0;//Xin-Xout启动 cm16 = 0;//无分频模式 cm17 = 0; cm06 = 0;//使CM16,CM17有效 while(1){//等待主时钟振荡稳定 if(!ocd3){ if(i>=10) break; else ++i; } } ocd2 = 0;//选择主时钟 prcr = 0;//设定对cm0,cm1,ocd寄存器的写保护 //设置定时器 txmr=0x00;//定时器X设为定时器模式 tcss=0x11;//选择计数源为f8 txic=0x07;//定时器X中断优先级为7 asm("FSET I");//开中断 } /* 主函数 */ void main(void) { unsigned char flag; initMCU();//对MCU进行初始化 flag = eraseBlock(0x2400);//擦除大小为1kB的块A,块首地址为2400H while (1); } |
CopyRight 2018-2019 实验室设备网 版权所有 |