C8051Fxxx 程序丢失问题的分析1 C8051Fxxx 单片机简单介绍和 Flash 结构C8051Fxxx 系列器件是 Silicon Labs 推出的一个高速单片机系列这款单片机是完全集成的混合信号片上系统型 MCU 芯片,具有高速、流水线结构的 8051 兼容的 CIP51 内核;70%的指令的执行时间为 1 个或 2 个系统时钟周期;片上有丰富的片内外设,根据型号的不同,包括 ADC、DAC、UART 、捕捉/ 比较模块的可编程计数器/定时器阵列、SPI、SMBus 等C8051Fxxx 单片机有大容量的 Flash 存储器,用于程序代码和非易失性数据存储,可在系统编程Flash 的结构是以扇区为单位组织的(128 KB 系列以 1 024 字节为 1 个扇区,64 KB 系列以 512 字节为 1 个扇区)非易失性 Flash 可以用来存储系统的参数,如软件版本、生产日期等Flash 可以使用编程器擦写,也可以在程序中使用 MOVX 指令来修改,从而使 Flash 存储器具有在系统重新编程能力,允许现场更新 8051 固件程序Flash 的写和擦除操作由硬件自动定时,以保证操作正确通过。
C8051Fxxx 的 Flash 保存下载的程序,在系统上电后,单片机从 Flash 读出代码数据到 RAM,之后程序开始运行2 程序丢失问题的出现和原因在一些实际应用中,系统重新上电后会出现程序不能正常运行的问题,常表现为“程序丢失”通常是由于程序代码被损坏或被修改造成的造成程序丢失问题的原因很多,可以归结到一个基本原因,即对 Flash 的访问失败而造成 Flash 保存的代码出现错误对于所有包含有 Flash 写/ 擦除子程序的系统,当 CPU工作在规定的 VDD、温度、系统时钟频率范围之外时,对 Flash 进行写/擦除操作,都有可能出现 Flash 数据错误的现象2.1 Flash 数据错误的硬件原因C8051Fxxx 单片机的 Flash 操作由硬件控制,所以硬件上的不稳定可能造成 Flash 操作错误硬件原因主要是能影响 CPU 正常运行的因素,以及能影响 Flash 操作环境的因素这些因素包括操作电压、温度以及外部干扰脉冲等,具体如下:① 能影响 CPU 运行可靠性的参数有系统时钟源如果系统时钟由外部晶振提供,外部的电磁干扰引起尖脉冲,并耦合到系统时钟上,则会导致不可预知的操作。
② 系统在单片机的工作电压没有稳定(VDD 上升时间低于规定的 1 ms)时就已经完成复位,由于系统复位时需要从 Flash 读出代码数据,Flash 电压不稳定会出现不可预测的错误③ 在对 Flash 的操作过程中,如果温度、电压不稳定,也可能造成 Flash 数据错误2.2 Flash 数据错误的软件原因代码设计的缺陷是程序丢失的主要原因,因为单片机的 Flash 是由硬件来控制的,不能由软件来控制操作的细节,所以程序的不完善可能造成 Flash 的访问出错,从而使Flash 数据出现错误 这些操作包括: 在 PSWE 位(PSCTL.0)置 1 时 CPU 执行中断服务程序中的 MOVX 写操作,该中断服务程序要使用 xdata 或 pdata 的易失性存储区单元,这样可能导致向 xdata 或 pdata 存储区写的数据写到 Flash 中了,从而出现问题另外,如果使用外部晶振作系统时钟,在时钟没有稳定时就对 Flash 进行写操作,也可能造成程序丢失3 程序丢失问题的解决方法针对以上可能的原因,可以从软硬件两个方面来解决程序丢失问题在硬件方面,主要是给系统提供稳定的工作环境,并避免外部干扰对 CPU 运行环境的影响;在软件方面,主要是规范对 Flash 的操作。
3.1 从硬件方面预防程序丢失注意,以下的方法不是对所有的器件都适用,要根据具体的硬件情况选择相应的方法:① 在 RST 引脚安装 VDD 监测电路,并将 VDD 监视设置为一个复位源(置RSTSRC.1 为 1)这样如果系统电压不稳定,系统将自动复位,从而避免在电压不稳时访问 Flash② 对外部晶振时钟 2 分频,更好的方法是使用内部振荡器,这样能提高系统时钟的抗干扰能力③ 如果使用外部晶振提供系统时钟,信号线应尽量靠近单片机的输入端,同时晶振外壳接地④ 对于使用外部晶振作时钟源的系统,应尽量增强晶振的驱动能力,这样也能在一定程度上预防程序丢失3.2 从软件方面预防程序丢失程序丢失的主要原因是程序设计的缺陷,所以合理的程序代码设计能极大地预防该问题的出现在代码中可以用多种方法来预防 Flash 数据丢失:① 在 PSWE=1 下禁止中断,使得程序中的 MOVX 写指令是对 Flash 而不是对XRAM② 在 PSWE=1 下尽可能少地访问变量在 PSWE=0 下执行地址译码操作,并用间接寻址方式执行 MOVX 写操作例如,向 Flash 写多个字节,间接寻址和写 PSWE 过程如下: unsigned char xdata * idata pwrite;//使用 idata 指针指向 Flashunsigned char *source;unsigned char mydata;for (addr = 0; addr < 100; addr++) {//PSWE =0 时获取要写入的数据mydata = *source++;//PSWE =0 时修改写入数据的目标地址pwrite = (unsigned char xdata *) addr;PSCTL = 0x01;//PSWE=1//赋值方式写入数据,此时不执行目标地址的修改操作*pwrite = mydata;PSCTL = 0x00;//PSWE=0}以上代码中,当 PSWE = 1 时只执行写 Flash 操作(*pwrite = mydata);其他操作,如修改 addr 的值、获取源数据和目的地址,都是在 PSWE = 0 时执行的。
③ 将 Flash 写/擦除指针指向 data 或 idata 区④ 减少将 PSWE 置 1 的指令操作理想的情况是只有两个操作将 PSWE 置 1,即写1 个 Flash 字节和擦除 1 个 Flash 字节⑤ 在 Flash 写/擦除函数中,使能 VDD 监视并设置复位源使能和设置操作必须在实际的写操作发生之前,置 PSWE=1 之后完成⑥ 代码中所有的对 RSTSRC 的写操作均用直接赋值方式完成(如 RSTSRC = 0x02) ,不能用读 /写指令(如 ORL 或 ANL)来完成例如,代码 “RSTSRC |= 0x02”是非法的⑦ 对于能用 PORSF 位来设置 VDD 为复位源的器件,保证在写 RSTSRC 时置PORSF=1,即先使能 VDD 为复位源,再使能其他复位源的操作,如时钟丢失监测(missing clock detector)、比较单元和软件复位4 一个实际应用方案在有的应用场合,由于需要较快的执行速度,不能使用单片机的内部时钟作系统时钟源,所以使用外部晶振来提供时钟在这种情况下,首先要在硬件上确保系统工作参数正常在软件上,由于最常见的 Flash 丢失原因是程序问题,所以可以在代码中用多种方法来预防 Flash 数据丢失。
首先,在初始化单片机时,使能 VDD 检测,并设置 VDD 和时钟丢失为复位源如果程序中有写/擦除 Flash 的代码,则在写 /擦除操作前切换系统时钟,将系统时钟切到内部时钟或对外部时钟 2 分频;写/擦除操作完成之后,再恢复系统时钟,通过增加 Flash 修改操作时的时间开销来实现系统的稳定[2]以下以 C8051F126 为例,给出了系统时钟切换的程序清单: void SYSCLKAdjust(unsigned char select) {EA_Save=EA;SFRPAGE=0x0f;switch(select) {case 0x01:OSCICN_Save = OSCICN;CLKSEL_Save = CLKSEL;OSCICN = 0xc3;//内部时钟,不分频CLKSEL = 0x00;break;case 0x02:OSCXCN_Save = OSCXCN;OSCXCN |= 0x70;//外部时钟 2 分频break;default://选择内部时钟OSCICN_Save = OSCICN;CLKSEL_Save = CLKSEL;OSCICN = 0xc3;CLKSEL = 0x00;break;}}要恢复系统时钟到 Flash 操作前的状态,只需将CLKSEL_Save、OSCICN_Save 、OSCXCN_Save 重新写回到CLKSEL、OSCIN 、OSCXCN。
C8051F126 的系统时钟(SYSCLK)可以在内部时钟和外部时钟之间自由切换,切换时的操作要求如下:① 在切换过程中,先设置所选时钟的属性,再用 CLKSEL 将其设置为 SYSCLK② 在还原过程中,先用 CLKSEL 选择时钟源,再设置其属性③ 如果切换过程中关闭外部晶振,要再恢复外部时钟,启动后至少要等 1 ms,再去读 XTLVLD(OSCXCN.7)来判断晶振时钟是否稳定否则,可能读到错误值④ 在外部时钟稳定运行后,再对其分频,不必插入等待周期⑤ 在切换过程中,可以保持外部时钟继续运行,这样在还原过程中就不必等待外部时钟稳定,从而节省时间开销,代价是系统功耗有所增加5 总结程序丢失会带来各种不良的后果,最严重时致使程序无法正常运行,从而造成整个系统崩溃,给产品的应用带来麻烦在系统的硬件设计和代码编写过程中,通过对以上问题的注意,可以有效地防止程序丢失问题的出现另外,由于系统时钟的切换只发生在Flash 的写 /擦除过程中,操作结束后又恢复成原来的设置,因而对系统运行速度的影响很小,从而保证了系统其他功能的实现。