摘要 介绍一种能及时发现系统处于非正常运行状态,利用系统在线自行跟踪与监控CPU,对各种系统运行状态进行在线实时监控的方法。
关键词 MCU系统 自行跟踪 监控CPU 实时监控
1.目前MCU系统监控中的问题
对于单片机系统,一般都需要监控电路来提高系统的可靠性。包括用电压比较器对电源的监控和看门狗对程序的监控。为防止系统程序受干扰“飞掉”,常用看门狗定时器,这种方式对于系统进入死循环时很有效,而程序“飞掉”时极有可能跳过一段程序,正好进入另一条指令的开头。尤其在RISC系统中,绝大部分是单周期指令,容易遇到这种情况,此时程序会继续运行下去,使看门狗失效。跳过的这段程序,可能包括一些接口控制执行指令,或某些数据的输入输出,或条件判断,整个系统会因此而运行紊乱,或直接产生故障。系统出现这类故障时很难立即察觉。
1.在运用极其广泛的一类MCU系统,如分段定时控制系统中,象家用电器的电脑控制微波炉、洗衣机、电饭煲;电力行业的发电机转速控制;冶金行业的连铸、焊管及流水线系统等,都可能会在系统运行中遇到分段定时控制或某一区域内运行状态与前段运行状态密切相关的情况。此时简单地用看门狗电路作系统监控,一旦出现系统死锁而复位,将会使启动以后的整个运行过程失效,这种方法显然是行不通的。
2.对于分时多任务系统,其中的某个或几个任务出现死锁,而又有一个或多个任务仍正常运行的情况下,看门狗定时器可能会被“蒙蔽”而失去监控作用。
3.在一个程序运行周期很短,或系统根据不同运行状况的程序处理时间相差很大的情况下,看门狗定时周期难以定得合适,此时若出现干扰死机可能因难于及时发现并解决而造成故障。
如果有一种方法,使系统在运行过程中能够自行感知程序运行状况,出现问题能够随时察觉;发现故障立即报警、停止运行或复位,甚至可以自动纠错,使程序恢复正确的运行,以实现对程序的最佳监控,那将是比较理想的。
2.系统在线自行跟踪基本方法
系统在线运行过程中,如果能够随时将系统运行的过程即系统当前程序的实际流程路线自动记录下来,就有办法将预期的运行路线与之比较,从而避免程序出现不可预测的死锁。打个比方,设想有一辆在公路上行驶的汽车,只要知道该汽车在各个岔路口的走向,就可以描绘出这辆汽车整个的行驶路线,但是难以保证汽车可能会在一条单一路线上行驶时抛锚。如果每隔一定距离以及重要路段设上“哨卡”,就能更加细致地了解到汽车的行驶情况,一旦出现问题就能立即知道事故出现的具体路段。同理,在程序运行过程中也可以通过人为设置的“哨卡”来记录程序当前的运行路线。在多数情况下,这些“哨卡”对系统运行并没有太大的影响。
实际上,这些“哨卡”就是可以任意插入流程中的简短程序段,每一个“哨卡”有一个特定的“标志码”以使我们能够知道程序到底运行到何处。将这些标记按出现的顺序记录在存储器中,就能依此知道CPU“行驶”的具体路线。当然,对系统的运行状态了解得越细致,程序的运行时间会越长。应将它们设置在重要的数据读写或接口操作处,各分支路口和相对独立的程序块入口处,尽量减小对系统的影响。
下面以GMS97C51单片机构成的MCU系统为例说明系统对自身运行路线的跟踪记录方法。
如图1所示,设系统CPU为97C51,外接一片SRAM6116来作运行记录,为防止掉电和死机的影响,将RAM用后备电池保护起来(系统上电初始化程序应包括将6116清零,清零程序在此略去)。
图1自行跟踪系统接口
在系统原来程序段中需要设“哨卡”的地方插入语句:
MOV | SIGN,#MARK | ;#MARK为标志号,SIGN定义 |
LCALL | GUIDE | ;为存放标志号的寄存器地址 |
这样,仅插入6个字节对原来程序的存储空间并无多大影响,所有的“哨卡”共用一个子程序。
GUIDE: | PUSH PSW | ;保护原来程序可能用到的寄存器,如有必要也可 |
PUSH ACC | ;将DPTR压栈保护 | |
INC ADDR | ;ADDR为标志号存放单元,上电后需清零 | |
MOV A,ADDR | ;假设只用RAM中的256个单元来做记录 | |
JZ OUT | ;若存储空间用完则停止存储记录 | |
MOV DPL,ADDR | ;设6116存储地址为7F××H | |
MOV DPH,#7FH | ||
MOVX @DPTR,A | ||
OUT: | POP ACC | ;存储记录 |
POP PSW | ||
RET |
假设总共“哨卡”数量少于256个,用一个字节来作标志,每一个“哨卡”都会有一个独立的标志号,通过查询RAM记录内容就可知道程序的实际运行路线了。这里我们还发现程序自行跟踪的一个额外的作用,即只需一个读RAM的简单装置,此方法就可用来作程序开发过程中的仿真调试而无须PC机及仿真器。
若系统无法用到并行总线,可将6116换成串行存储器,如美国XICor公司的非易失性RAMX24C45,程序则应作相应改动。插入“哨卡”后应考虑对原系统运行时间上的影响。
3.利用自行跟踪方式对系统的实时监控
在作系统监控的应用中,系统必须对自身运行状况作实时监控。利用上面的方式,在系统中加上监控程序,系统对自身运行情况亦可作自行监测。但这样一来,不仅会对原来程序造成较大影响,而且会因为系统本身可能受到干扰或其它原因而瘫痪,因而是不可靠的。对于高可靠性要求的系统,有必要另加一套监控系统来对原系统及监控系统自身作专门监护,从后面的讨论中可知,这外加的系统可以是廉价、小巧、安全可靠和高效的。
在实时监控过程中,可以省掉对程序运行路线的存储记录而直接判断。系统电路如图2所示。它进一步减小了对原系统的影响而又提高了运行效率。在监控系统运行过程中,应从以下三个方面来考虑:
图2自行跟踪监控系统电路
1.监控系统对原系统的精确跟踪;
2.利用软件狗防止主系统死锁;
3.对监控系统自身的监控。
系统非正常运行除硬件与电源系统的问题之外,难以琢磨的主要是软件系统。程序受到干扰产生故障有两种情况:
一是CPU没有按既定程序运行,系统指针“飞”到其它指令代码地址处,好象非法执行了一个跳转语句。这种情况存在很大的潜在危险性,利用看门狗技术难以察觉,可能带来难以预料的事故,且无论哪一类结构的指令系统都无法排除。此时利用在线跟踪技术发挥其监控作用是一个有效方法。可以在程序运行的各个路口和重要的操作前后插入“哨卡”,并将“哨卡”在系统程序中均匀分布,用专门的监控CPU实时跟踪,与已预存在监控系统中的正确路线比较,可及时排除原系统软件产生的故障,有时还可以使系统从其产生误操作之前的一个“哨卡”处恢复系统的正常运行。
二是CPU没有按既定程序运行,系统指针“飞”到非指令代码地址处。此时最易产生死机,程序完全失去控制。用看门狗可以最终发现此问题,但若不及时排除故障有可能因时间的延误或程序执行无法预知的操作扰乱数据和信号,产生故障。
在多任务系统中,其中某一个任务死锁,用看门狗可能无法感知,因为其它任务仍在不时发出“喂狗”信号。
在采用监控CPU自行跟踪的系统中,监控CPU可以对每一个任务分别设置软件看门狗,利用“哨卡”发出“喂狗”信号。因“哨卡”可人为地依时间均匀设置,一旦系统死锁,或下一个“哨卡”信号未到而超时,即可及时发现故障在哪一“哨卡”附近发生,并可能及时排除故障,继续按原路线运行正确的系统程序。
对于以上两种情况,若CPU监控系统本身出现故障。又有以下两个方面:
(1)在主系统中的监控配合程序(即“哨卡”程序)自身出现问题,此时监控系统会认为是原系统程序的问题,包括在上述两种情况之中,逃不出对原系统程序的监测,可用同样的方法在监控程序中同时解决。
(2)监控CPU的监控程序出现问题,又分别有两种可能:
①监控程序代码执行顺序错误。即监控系统指针未按预定程序运行。此时监控CPU会认为是主CPU而非自身程序出现了问题。监控程序会很快循环一周而处于等待状态,程序本身不会混乱。此时监控系统会将原系统或整个系统强行复位,或将原系统程序从前一“哨卡”处恢复运行。
②监控系统程序指针“飞入”非程序指令代码处而造成死机。由于监控系统是可以预知的单一任务系统,此时可用CPU片外的硬件看门狗作监控CPU的硬件监控,而将整个系统复位,或根据主系统情况恢复监控系统本身的运行。在设计过程中应使这种情况尽可能少发生。
虽然监控系统可能出现问题,但从以上讨论来看,所有问题都可得到解决。整体而言采用监控系统的自行跟踪方式可以大大提高整个系统的可靠性。然而也要求监控系统本身具有高的稳定性与可靠性,以提高整个系统的性能。另外,监控系统最好要有独立稳定的供电电源。
4.自行跟踪监控系统的实现
接口电路参见图2,将安插在原来程序的“哨卡”所发出的信号称作“路标特征码”或“路标码”。监控CPU可以直接从与主系统的接口处得到这些“路标码”,而不必将它们存入存储器中。对于并行总线结构可以方便地用锁存器,如74HC273,将“路标码”传送给监控CPU。对于片内总线结构的CPU,可以用串口或移位寄存器,甚至单一的I/O口线来传送信号。这里以并行总线结构的MCS-51系列单片机GMS97C51为例说明。
4.1监控系统的软件准备棗数据结构
设主系统有如图3所示的部分程序结构,它包括了大部分程序可能出现的结构。在程序中插入“哨卡”的“路标码”如图中数字所标,程序经过这些“哨卡”时会将相应的“路标码”实时反映在接口处,监控CPU收到“路标码”信息后将其与系统固有的程序结构进行比较。
图3主系统程序结构举例 |
图4由“哨卡”信息反映出的 |
图3结构可以简化成图4形式。为了比较这些代码出现的位置,这里考虑一种数据结构,将原系统的整个流程图通过这种数据结构存放在监控CPU的ROM中,形成一个存放原来程序结构的数据库。从某段程序的入口开始,一直到遇见分支,设置一个连续数据区。不同的连续程序段形成的连续数据区之间,由这种数据结构中的地址字节来连接。自然每个“路标码”还会有一个绝对存放地址。在这个数据结构中给每个“路标码”后带一个字节的相对转移地址,用来存放当前“路标码”出现后下一个“路标码”在此数据库中的相对地址。假设原系统程序设置的“哨卡”少于256个,数据区之间的地址不会相距太远,则每一个数据项由“路标码”与相对地址码两个字节组成,转移地址在-128~+127字节范围内可以找到。在散转或判断语句中,可能并列出现的下一“哨卡”数据项连续排列在一起,以立即数#0作为结束,它们之间表示“或”的关系,在程序的某一次运行之中只有其中的一个数据项对应的语句会被遇到,数据项结构如图5所示。256个“路标码”所形成的数据库最大可有768字节。图3所示程序结构可以图6形式存于数据库中。对于多任务系统必须在每一数据项中增加一个字节的“任务号”,以便于识别不同任务的程序结构。由于多任务系统的数据库会比较庞杂,可用增加的这个字节的高四位表示任务号,低四位与另一字节作为用12位表示的转移地址,作用范围可扩大到4KB。
路标码 |
相对跳转地址 |
#00H |
单任务系统的一个数据项
路标码 |
任务号 |
跳转地址高四位 |
跳转地址低八位 |
#00H |
多任务系统的一个数据项
图5数据项的数据结构
有了这样的数据库,监控程序的实现就变得方便得多了。
(a)作为示意,图中字母表示每一个数据区的首地址,数据区中的相对跳转地址指向其相应的地址位置。在实际数据区中地址字节应为相对量。
01 |
03 |
00 |
02 |
03 |
00 |
03 |
09 |
04 |
0F |
05 |
15 |
06 |
18 |
00 |
08 |
02 |
07 |
03 |
00 |
06 |
10 |
00 |
|||||||
09 |
03 |
06 |
0A |
04 |
85 |
00 |
||||||||
0A |
0D |
0B |
0B |
00 |
||||||||||
0C |
03 |
00 |
0D |
×× |
0E |
×× |
00 |
|||||||
06 |
88 |
00 |
(b)实际数据区中的数据。图中假设这些数据为连续排列
图6“路标码”数据区示意图
4.2监控系统的程序实现
监控系统的主要程序流程见图7所示。在程序正常运行的情况下,唯一能够打破此数据结构图而出现例外的只有一种情况,即主程序运行过程中出现了中断服务程序。而在每一个中断服务程序起始后即会有一“哨卡”提供其特征码,以使监控程序在当前数据区找不到对应的数码时,能为中断服务程序的跟踪提供一个入口。但监控程序一定要将中断入口前的“路标码”数据库地址压栈。以使中断服务程序结束时能接上前面的“连环套”。
监控系统设置定时器作为主系统的软看门狗。监控CPU每接收到一次被刷新的“路标码”,就将软定时器复位一次,若定时器溢出则表示“路标码”已经有过长时间未被刷新。可认为原系统出现了故障。对于多任务系统,可以设置一个公共时基,在每一次时基定时中断中给每一任务的定时时钟加1(每一个任务有一个独立的时钟寄存器,存放累积的时基个数),并判断每一任务的时基数是否大于设定的数值,若大于即表示该任务已超过看门狗定时周期,该任务出现了故障需要处理。依此可弥补硬件定时器数量上的不足,也简化了程序。在每一次刷新“路标码”时会将相应任务的时钟寄存器清零,即将此看门狗复位。
另外,路标码在数据库中的转移范围若超出了相对寻址范围,例如程序在完成一个大循环后的“哨卡”地址,可由专门的长转移标志提供相应的入口地址。
图7监控系统核心程序流程图
分析监控程序的流程图,会发现实现监控程序并不困难。在此基础上,在不同的系统开发中还可有许多应用,例如将主系统重要寄存器与程序指针在“哨卡”处作刷新保存,监控程序将“哨卡”状态缓存一步,并保存前一“哨卡”地址。一旦出现问题,可将程序返回该“哨卡”处恢复原来状态继续运行。具体实现方法在此不作详述。
5.监控系统的完善
前面以一种简单的情况和工作方式说明了监控系统的运行过程。然而在实际运行过程中,由于监控过程全部自动完成,监控系统工作的稳定性和严密性有重要的意义。主系统在运行过程中发生数据突变或者出现程序在相邻“哨卡”之间的非法跳变,此时用以上的简单跟踪方式难以直接察觉。因此,在监控CPU与主系统之间的数据信息交流是必要的。另外,要保证“哨卡”设置得严密,必须保证监控CPU有比主CPU快得多的运行速度。下面简要探讨一下对监控系统的完善方案。
5.1对寄存器数据的监控
在程序运行过程中的数据突变和程序计数指针的非法跳变最终影响的是寄存器的数据值。在相邻“哨卡”之间不会有分支、循环语句,仅会涉及到置数、传送、运算、接口操作,对这些流程的破坏也最终反映到寄存器数据的改变上。监控系统要探知这些寄存器数据的变化只有通过主系统与监控系统的信息交换。提高系统可靠性是以降低原系统实际运行速度为代价的,在“哨卡”程序中输出相关寄存器内容,过程如下:
在每个哨卡数据传送过程中,由于监控系统是与主系统配合设计的,并不是独立可脱离的控制模块,因此监控系统在特定的各个标志号的“哨卡”所接收到的数据,监控系统已可预知该数据来源,可以作相应的灵活处理,或是为下一“哨卡”要得到的寄存器数据作准备,或是与上一“哨卡”储备的相关寄存器数据作比较,因此寄存器数据的传送数量也是灵活可变的。开发人员在作系统设计时,可以对原系统的数据内容作严密处理,还可将有关寄存器数据作预先运算后输出给监控CPU,以保证寄存器内容的准确性并简化步骤。相应于监控系统数据结构的改变,每一“哨卡”数据项中增加了一个字节,作为该“哨卡”传送数据的RAM存放区地址代码。由于寄存器内容在监控CPU的RAM中只作暂存,可互相覆盖,并不需消耗多大RAM空间。
简略地说,监控系统针对主系统从各“哨卡”传送的数据以中断方式所作出如下的响应:
(1)一旦有数据刷新#0标志,即表示有新的“哨卡”标志数据从主系统输出,在对标志号进行判断无误之后,即准备进行寄存器数据的判断。
(2)监控CPU捕捉到接口的刷新数据信号后(在图8中,可由MSP430的10脚TA0判别刷新信号;图2中可由C2051的6脚判别刷新信号),在其中断程序中,将接口传送数据存于该“路标码”数据项所确定的RAM地址,依次存放。监控系统对这些数据进行简单的运算或比较。在处理结果与预期不符时采取相应的恢复或拯救措施。
有了对寄存器数据的监控,可不必对原系统设置过密的“哨卡”,并可防止不是由程序计数指针的变化造成的寄存器数据值的突变。
5.2监控过程中运行速度的配合
数据的传送过程中,主系统程序相当于在作延时操作,并没有额外加重监控系统负担,只影响了主系统运行速度,在设计时应作考虑。如果有中断在此过程中发生,监控系统亦能判别(参照图7的中断部分)。
为保证监控CPU在主系统下一“哨卡”标志号发出之前将当前“哨卡”程序全部处理完,对“哨卡”的设置间隔是有限制的。主系统程序中“哨卡”的设置应考虑到监控CPU的程序负担。必要时如果系统允许,甚至可为监控系统作延时操作,以安置“哨卡”程序。
可以看出,完成系统监控的监控CPU需要有足够快的速度,一般来说,监控程序的一个循环需要二十多条语句或稍长。应用于低电压系统,这里推荐一种性能好、速度快、低价格、低功耗的RISC处理器?/FONT>TI公司最新推出的MSP430。其指令周期仅125ns,片内4KB+256BFLASH ROM(MSP430F112)。假设主系统采用MCS-51系列,使用6MHz晶振时,指令周期为2μs,则主系统一条指令的执行时间监控系统可至少执行16条指令。而且MSP430自带硬件看门狗,另外仅需一片电压监控芯片即可简单地设计出整个监控硬件系统如图8所示。
图8低压系统监控电路举例
6结语
可见,利用自行跟踪的方法来提高系统可靠性,只适用于对速度要求不高的系统。需要注意的是要提高系统的可靠性,需要在硬件、软件和外部条件上作整体考虑。对于随机数据和运算处理数据,更多的应从主系统本身的程序处理来考虑。抗干扰处理没有绝对可靠的方法,这一切都建立在以整个系统本身已有一定的抗干扰能力,与环境干扰强度差距不大为基础,并从软硬件设计整体考虑的前提下作为高可靠性系统的监测才有意义。本文所介绍的方法仅作为一种可行性探讨,以期各位同行在实践中不断完善。
参考文献
1MSP430F11×混合信号微控制器数据手册,武汉:武汉力源电子股份有限公司,2000.1