有時,在寫ARM時會遇到經(jīng)常死機(jī)的情況,莫名其妙,在這里我總結(jié)了一些單片機(jī)/ARM死機(jī)或者跑飛的一些常見的查找方法和我對此的一些拙見希望對大家有幫助。 “死機(jī)”和“跑飛” 隨著單片機(jī)在能源領(lǐng)域中的廣泛應(yīng)用,單片機(jī)的抗干擾問題越來越突出,煤礦井下環(huán)境一般比較惡劣,這便會為單片機(jī)控制系統(tǒng)帶來各種干擾,以致系統(tǒng)不能正常工作。單片機(jī)應(yīng)用系統(tǒng)的抗干擾性能主要取決于硬件的抗干擾設(shè)計,但軟件抗干擾設(shè)計作為硬件抗干擾的完善和補(bǔ)充,作用也非常重要,因為大量的干擾通常并不能影響系統(tǒng)內(nèi)硬件的運作,卻常會使系統(tǒng)的軟件無法正常運行,單片機(jī)應(yīng)用的一個突出問題,便是單片機(jī)運行過程中經(jīng)常出現(xiàn)的程序跑飛現(xiàn)象。 在單片機(jī)系統(tǒng)中,因為干擾的原因,在非預(yù)期的情況下,使得程序計數(shù)器PC 的值發(fā)生隨機(jī)的變化,從而使得程序的流向指向不確定區(qū)域,這便是程序的跑飛。程序跑飛后或者會使指令的地址碼和操作碼發(fā)生改變,PC 把操作數(shù)當(dāng)作指令來執(zhí)行;或者PC值指向一條不合邏輯關(guān)系的指令甚或是非程序區(qū),運行結(jié)果常常會使單片機(jī)進(jìn)入死循環(huán)———便是大家常說的“死機(jī)”。為確保在無人當(dāng)值的情況下,單片機(jī)“死機(jī)”后能自動恢復(fù)過來,通常采用軟件陷阱,外部WDT 電路,以及軟件控制的WATCHDOG 等方法,使系統(tǒng)恢復(fù)正常(后兩種俗稱“看門狗”)。 出錯原因分析 那在程序運行出現(xiàn)這些錯誤時,我們要從哪些方面進(jìn)行分析呢? 1、意外中斷。 確認(rèn)下是否打開了某個中斷,但是沒有響應(yīng)和**中端標(biāo)志,導(dǎo)致程序一直進(jìn)入中斷,造成死機(jī)假象。 2、 中斷變量處理不妥。 若定義某些會在中斷中修改的全局變量,這時要注意兩個問題:首先為了防止編譯器優(yōu)化中斷變量,要在這些變量定義時前加 volatile,其次在主循環(huán)中讀取中斷變量前應(yīng)該首先關(guān)閉全局中斷,防止讀到一半被中斷給修改了,讀完之后再打開全局中斷;否則出現(xiàn)造成數(shù)據(jù)亂套。 3、地址溢出,常見錯誤為指針操作錯誤。 我要著重說的是數(shù)組下標(biāo)使用循環(huán)函數(shù)中循環(huán)變量,如果循環(huán)變量沒控制好則會出現(xiàn)數(shù)組下標(biāo)越界,意外修改系統(tǒng)的寄存器造成死機(jī),這種情況下如果死機(jī)說明運氣好,否則后面不知道發(fā)生什么頭疼的事。 4、 無條件的死循環(huán)。 比如使用while(x);等待電平變化,正常情況下x都會變成0,就怕萬一,因此最好加上時間限制; 5、看門狗沒有關(guān)閉。 有的單片機(jī)即使沒使用看門狗開機(jī)時也有可能意外自動開啟了最小周期的看門狗,導(dǎo)致軟件不斷復(fù)位,造成死機(jī),這個要看芯片手冊,最好在程序復(fù)位后首先應(yīng)該顯式**看門狗再關(guān)閉看門狗; 6、 堆棧溢出。 最難查找的問題,對于容量小的單片機(jī),盡量減少函數(shù)調(diào)用層級,減少局部變量,從而減少壓棧的時候所需的空間。當(dāng)你把以上幾條都試過不能解決問 題,試一試把你的被調(diào)用少函數(shù)直接內(nèi)置到調(diào)用的地方并且把占用RAM大的局部變量改成全局變量,試一試說不定就可以了。 處理方法 找出原因后,我們要怎么處理呢? 死機(jī)是指CPU的程序指針進(jìn)入一個死循環(huán),無法執(zhí)行正常的程序流程。其外在表現(xiàn)常常是:正常功能喪失,按鍵無響應(yīng),顯示凝固。單片機(jī)死機(jī)后,只有復(fù)全才能走出死循環(huán),執(zhí)行正常的程序流程。眾所屬知,克服死機(jī)的最有效手段是加看門狗(WatchDog)。 目前用得最廣泛的看門狗實際上是一個特殊的定時器DogTimer。DogTimer按固定速率計時,計滿預(yù)定時間就發(fā)出溢出脈沖使單片機(jī)復(fù)位。如果每次在DogTimer溢出前強(qiáng)行讓DogTimer清零,就不會發(fā)出溢出脈沖。清零脈沖由CPU發(fā)出,在單片機(jī)程序中每隔一段語句放一個清DogTimer的語句——FeedDog語句,以保證程序正常運行時DogTimer不會溢出。一旦程序進(jìn)入一個不含F(xiàn)eedDog語句的死循環(huán),DogTimer將溢出,導(dǎo)致單片機(jī)復(fù)位,跳出這個死循環(huán)。本文稱這種看門狗為典型看門狗,典型看門狗已被集成比,如MAX706、MAX791等[1];還有許多單片機(jī)本身集成了這種看門狗,如PIC16C57、MC68HC705等, 有一個錯誤觀點:加了看門狗,單片機(jī)就不會死機(jī)。實際上,看門狗有時間會完全失效。當(dāng)程序進(jìn)入某個死循環(huán),而這個死循環(huán)中又包含F(xiàn)eedDog語句,這時DogTimer始終不會溢出,單片機(jī)始終得不到復(fù)位信號,程序也就始終跳不出這個死循環(huán)。針對這一弊端,筆者設(shè)計了雙對限看門狗和定時復(fù)位看門狗。 雙時限看門狗有兩個定時器;一個為短定時器,一個為長定時器。短定時器定時為T1,長定時器定時為T2,0 。這樣,當(dāng)程序進(jìn)入某個死循環(huán),如果這個死循環(huán)包含短定時器FeedDog語句而不包含長定時器FeedDog語句,那么長定時順終將溢出,使單片機(jī)復(fù)位。巧妙安排長定時器FeedDog語句的位置,可保證出現(xiàn)死機(jī)的概率根低。 目前幾乎所有的看門狗都是依賴于CPU(依賴于CPU FeedDog)。這可以比作:一個保險設(shè)備能否起到保險作用還依賴于被它保護(hù)的對象的行為。顯然,依賴于CPU的看門狗是不能保證單片機(jī)在分之百不死機(jī)的。 在絕對不允許死機(jī)的裝置中,筆者設(shè)計了一種完全不依賴于CPU的看門狗——定時復(fù)位看門狗。定時復(fù)位看門狗的主體也是一個定時器,到預(yù)定時間就發(fā)出溢出脈沖,此溢出脈沖使單片機(jī)強(qiáng)行復(fù)位。定時復(fù)位看門狗不需要CPU FeedDog。 簡言之,定時復(fù)位看門狗就是定時地讓單片機(jī)強(qiáng)行復(fù)位。這樣,即使裝置死機(jī),其最大死機(jī)時間也不會大于定時器定時時間。顯然,只要硬件完好,這種看門狗百分之百地保證了單片機(jī)不會長時間死機(jī)。在智能電表(包括IC卡電能表、復(fù)費率電能表、多功能電能表)中采用了定時復(fù)位看門狗,每1秒讓CPU強(qiáng)行復(fù)位,迄今數(shù)十萬電表運行了近五年,無一例死機(jī)報告。 電路設(shè)計注意事項 雖然解決的方法有很多種,但是在設(shè)計電路時我們需要注意哪些方面以便盡量的避免這些錯誤,以減少開發(fā)和調(diào)試所需時間呢? 1、電源穩(wěn)定,因為電源電壓 的 不穩(wěn)定會造成瞬間負(fù)電壓導(dǎo)致單片機(jī)故障程序無發(fā)運行 |