嵌入式系統如何解決死循環類掛起

今天要說的,是系統掛起問題。許多作嵌入式軟件的團隊其實並不瞭解嵌入式軟件的特色,在他們的眼裏,只有軟件問題;所以出了問題的時候,纔開始抱怨這個沒有,那個也沒有,總之,能在電腦上用的工具方法都沒有。其實這些只能怨本身,嵌入式系統不能是個黑盒子,不然創建在上面的應用程序早晚會出問題。併發

先說說系統掛起有哪些特徵。函數

  1. 系統crash,但由於沒使能狗,系統未復位。
  2. 硬件故障,一樣沒使能狗,系統陷在某個中斷處理中,未復位。
  3. 軟件代碼死循環,多是局部的低級編碼錯誤,也多是任務某個判斷條件失敗致使的異常分支。
  4. 軟件設計不合理致使某些處理過程,連續佔用太多CPU時間,致使系統假死,卡死。

Case 1適用Coredump方法解決,Case 2比較複雜,須要根據實際狀況處理。我要說的,是針對Case 3 & 4的通用解決方法。工具

 

開始以前,得先說說多任務系統的切換。因此能切換,離不開兩個條件:當前任務主動棄權;當前任務被剝權而強制切換。測試

主動棄權,就是執行系統調用,好比msgq_send,sendto,malloc,fread等函數,這類函數會涉及系統核心或是信號量處理,所以CPU會在用戶態和系統態間切換。調用發生時,系統從用戶態轉爲系統態,當前任務即被掛起,放回調度隊列;當CPU離開系統態時,調度就可以檢查調度隊列,激活任務等待隊列最前面的任務。而這個最前面的任務,不少時候並非原來的應用。最典型的,就是msgq_send調用。日常作功能測試時,不會有併發的消息,整個處理過程都是線性化的,一個任務處理完,發消息給下一個任務處理,就這樣,一個任務接着一個任務,直處處理結束。這時候的系統,任務優先級其實沒什麼用的,由於任務運行的觸發事件就一個,除了那個正在作事的,你們都在等,也只能等。編碼

強制切換,須要系統中斷來實現,能夠是外部硬件中斷,也能夠是CPU內部的時鐘中斷。外部硬件中斷,好比網口接收到新的數據,就會以中斷方式通知CPU接收。中斷髮生後,當前應用就被被掛起,送回調度隊列。中斷處理完成後,CPU轉入系統模式,而不是回到用戶模式,此時天然能夠執行調度處理。固然,凡事沒有絕對,好比快速中斷就不必定是這麼作,且各個OS對細節有本身的權衡。時鐘中斷,包括提供給應用程序的定時器時鐘和Tick時鐘。定時器時鐘是涉及比較多的,通常微小系統裏,會不做封裝,直接使用。Tick時鐘,就是這裏要講的關鍵了。spa

Tick中斷是提供給OS進行任務調度切換用的,以免某些任務長期佔據CPU,實現軟件任務間的切換。要知道,中斷並非總有的,主動棄權也不該總髮生,總之,OS調度還得給本身留一手,在每一個Tick到來的時候,睜眼看看要不要作點啥。設計

好了,哥掏出個大盒子,打開一層又一層,如今,終於到最後火柴盒。如今,回到怎麼解決系統掛起問題。對象

 

嵌入式系統OS通常都會提供TickAnnounce這樣的接口或是鉤子。沒有也不要緊,直接掛Tick中斷,不過別忘記在自定義的TickAnnounce裏面調用原系統的TickAnnounce。TickAnnounce是OS任務調度睜眼後必作的,固然還作什麼,就是TickAnnounce決定的了!接口

咱們要讓TickAnnounce作什麼呢?計數。
總共有三組數據須要統計:系統態計數,中斷態計數,以及用戶任務計數。準確點說,就是TickAnnounce每次運行的時候,先判斷Tick發生時的模式,並將對應的計數+1。固然,每一個用戶任務都是一個獨立的計數,TickAnnounce直接取當前任務的TCB得到對應的計數器。嵌入式系統TCB老是開放給用戶可見的,且裏面總會提供幾個用戶自定義字段。咱們要作的,就是將其中一個用戶自定義數據字段,做爲咱們的計數器使用。
這裏有兩點須要注意:計數器是須要初始化和重置的,正常狀況下,千萬別在應用任務棧上對其進行修改,而應該是用一個簡單的0/1開關通知TickAnnounce來完成;TickAnnounce裏不能夠出現任何打印,必要時能夠有極少發生的msgq_send,計數器的讀出,也應該儘可能由TickAnnounce寫入特定的內存後,應用從對應內存塊獲取。隊列

作完上面的工做,咱們就有了個CPU Utilization工具了。接着,咱們須要定義一個策略,讓系統自動按期檢測高負載任務或是中斷處理。哥喜歡用過載門限來決定是否有異常,就是額外增長一個總TickAnnounce計數,在總TickAnnounce進入一個門限區間時,連續檢查每次Tick計數對象,當達到過載門限時,TickAnnounce即記錄當前模式及任務堆棧信息。跟coredump所不一樣的是,不能只抓一次現場,而須要抓不少次。固然,還有處理超過統計區間後,從新開始統計,不然由於時間跨度變大後,峯值數據就不明顯了!

這時候,咱們又要用SRAM了。嗯,SRAM真的是過重要了,哥作的不少嵌入式系統都離不開它!
爲啥不能用RAM呢?TickAnnounce確定不能寫flash,不解釋,不懂的回頭看上面。寫內存是挺好的,但那樣又有什麼用呢,系統都掛起了,RAM裏的內容,也無法看啊,最後只能是白忙活了!寫SRAM就不同了,系統只有不掉電,總仍是在那,系統重啓後,想怎麼讀出來都成。

哦,好像忘記說,抓n屢次現場後,記得觸發CPU復位!固然,若是系統有狗,那就在被狗咬死前,儘量多的抓取現場信息。


後記:
1,SRAM老是頗有限的,才數K空間,記得這個和coredump不會同時發生,要重用那個空間;
2,堆棧完整信息,一次就能填滿SRAM,這固然不行,抓取時,應該只關注頂部的數個函數調用,通常3~4個(一次現場大概16~20個字節)就足夠勾畫出程序調用關係了!

 

下次,要講講內存泄漏或是動態加載、動態不定等問題。

相關文章
相關標籤/搜索