郭春柱
在編寫、調試系統軟件的過程中,往往會出現這樣的情況:編程時只注重每一條指令的執行結果而忽略指令執行后相應標志位狀態的變化;或是MCU系統投入運行后,由于外界干擾使MCU內核三總線上的地址信號錯亂而導致程序運行的失控,這些都將導致程序跑飛,而更有甚者將程序引入死循環使得整個系統完全癱瘓。如何攔截失去控制的程序流向?如何盡可能無擾動地恢復系統正常運行狀態呢?筆者通過實踐,提出了一種在不增加系統制作、調試的硬件投資和設備基礎上,能夠有效防止程序跑飛軟件容錯的設計方法。
1.軟件陷阱的設計 當單片機的CPU受到干擾后,往往會誤將一些操作數當作指令碼來執行,而導致程序運行的混亂。例如當程序跑飛到某一雙字節指令上,就可能落到其操作數上而將操作數當作指令碼來執行;當然,若程序跑飛到三字節指令上,因三字節指令有兩個操作數,那么出錯的概率就更大了。因此在MCS-51 系統中,在對程序流向起決定作用的雙字節或三字節指令(如LCALL、ACALL、LJMP、AJMP、SJMP、JZ、JNZ、CJNE、DJNZ、JC、JNC、JB、JNB、JBC、RET、RETI等)之后,需增加一段軟件陷阱程序,才能使得跑飛的程序很快被納入程序的正常軌道。這個軟件陷阱程序可由三條指令構成,具體程序代碼如下:
NOP
NOP
LJMP WRONG
其中WRONG為出錯處理程序的標號。這段軟件陷阱程序可依據實際的系統軟件編程情況相應安排在未被使用的中斷向量區(例如未使用串行口中斷,就在ORG 0023H指令之后設陷阱)、未被使用的ROM空間中、讀取數據表格或散轉表格指令之后、關鍵的程序區(如RET、RETI、LJMP、AJMP、SJMP等指令之后)等位置上。
2.出錯處理程序的設計 以上的軟件陷阱程序只解決了如何發現系統被干擾和如何捕捉住失控的程序。當然,我們重點考慮應當是如何讓MCU根據被破壞的現場殘留信息使程序段自動恢復到正常的工作狀態。在此我們可應用一系列的指令來模擬硬件復位功能,在這種軟件復位方法中可根據系統編程的實際需要,對程序涉及到的各專用寄存器在主程序初始化過程中進行復位;而對于硬件復位方法中能夠自動清除原先被激活的中斷標志位的功能,可以通過以下程序段的設計來模擬完成。這部分程序代碼如下:
WRONG: CLREA;關中斷(軟件復位程序)
MOV DPTR,#ERR ;準備返回地址
PUSHDPL
PUSHDPH
RETI;清除高級中斷激活標志
ERR:CLRA ;準備復位地址
PUSHACC ;壓入復位地址
PUSHACC
RETI;清除低級中斷激活標志
這段程序先執行關中斷,以便后續復位工作能順利地進行,然后用兩個RETI指令清除了所有可能存在的已被激活的中斷標志位。對于軟件陷阱捕捉來的程序只激活一個中斷標志位的情況也不會妨礙程序復位后的執行。
采用防止程序跑飛的“熱啟動”方法可以有效地提高系統運行的可靠性,還可用于PIC、AVR等其它類型的MCU應用系統中,具有實用性、通用性等優點。并且,只通過簡單改變這段程序,還可作為其它系統程序模塊的一種容錯設計方案。