2016年4月7日 星期四

debug 的奧秘(2): ISR Debug 方法蒐集

哪種類型程式最難除錯?ISR(Interrupt Service Routine)絕對可以排進前三名

因為 ISR 對 timing 非常要求,程式必須短小精幹,於是即使花了大筆鈔票買 ICE,也很難用傳統設定中斷點、單步執行等方式進行除錯。

但 ISR 又是 firmware 必須面對的一環,沒有他絕大多數的週邊無法正常工作!

妙的是這樣重要的東西,居然很少有書本/網站提到(或許是站長孤陋寡聞,還請各方先進指正),於是站長興起一個念頭,何不把多年來蒐集到的各種 ISR 除錯技巧分享給大家,也算功德一件 :)



1. LED 法

站長不是在開玩笑,站長真的在某大廠看過這種作法,就是用四顆 LED,表達 2^4 = 16 種狀態,扣除掉沒什麼用的 4 顆 LED 全滅狀態,還有  15 種狀態可用。這種作法看似最笨最普通,但是他有一個好處就是低延遲(low latency),因為讀寫 GPIO 的速度通常很快。

2. RS232 法

這個大概不用特別介紹了,可說是人人都會。站長以前服務過的某幸福企業,乾脆在產品背後裝個小門,用個 RS232 轉板(把 RS232 標準 +/- 12V 電壓轉成 3.3V 或 5V 位準)就可以 debug。這種方式常常夢碰到一種莫名其妙的狀況,比方說拿掉 debug code 就不正常了。因為 RS232 本身種非常慢的週邊,就算有 FIFO 緩衝區,這種 debug 方式還是很有問題,因為還是要等前一筆資料被 FIFO 消化掉才能送下一筆,而且就算 baudrate = 115200bps,現代任何一顆 32bits ARM 指令執行速度還是他的數十倍乃至於百倍快。所以這種方式只能做一般 debug 用途,ISR debugging 還是忘掉他吧。

3. SPI /移位暫存器法


站長最早在林伸茂先生寫的 8051 單晶片徹底研究實習篇還是經驗篇看到這個除錯法,不過印象中只有一副照片,詳細線路似乎沒有提供,後來林伸茂先生主持的旗威科技乾脆把這個做成產品來賣。各位看官如果想要 DIY,用 "shift register" + "seven segment display" 去 Google 可以找到不少資訊。

這個作法的核心精神就是用「移位暫存器+七段顯示器」,CPU 把 clock & data 送到移位暫存器上,然後用七段顯示器觀察。可以想見這是一種介於 RS232 跟 LED 之間的作法。

因為 clock 是自己送的,只要 clock 在移位暫存器的規格內,想當然爾傳送的速度會比 RS232 快很多(快到 Mega Hz 應該都有可能)。因此,用這樣的方法除錯 RS232、I2C ISR(s) 應該是可行的。

4. 計數器法

最後一招由嵌入式系統資深專家 Jack Ganssle 提供,這個方法主要的構想是用一個外接計數器來量測中斷發生的次數或頻率:


比方說您現在正在開發 Ethernet driver,照理說打進 1000 個封包應該就有 1000 中斷(實務上可通常會用 DMA 而不太可能完全靠中斷,這邊只是為了解說方便),這時計數器上就應該顯示 1000,如果沒有那代表哪邊出了問題。

這個方法有兩個優點:

  1. 非常省 IO,只要目標板保留一個 GPIO Pin 即可。
  2. 如果計數器提供外部訊號 reset ,某種程度可以取代 SPI/移位暫存器法,不過需要多一個 GPIO Pin。例如我們可以用觸發的次數來標記 ISR 中程式碼的位址。
站長學會這招後免不了手癢實驗一下:


之所以中間用個 photocoupler (光耦合器)的原因是因為目標板電壓是 3.3V,而用來計數的 PLC 高速計數器輸入是 24V(手邊剛好只有這種東西):


不過這裡要注意一下 photocoupler 的切換速度,如果中斷的週期短於 photocoupler 的切換速度,那結果肯定有問題。不過,若是一個系統的中斷頻率過高,恐怕 CPU 的計算時間也會被吃掉光,所以這種狀況是不正常的,一般來說就算是極普通的 UART 也會有 FIFO + waterlevel 的設計,讓資料累積到一種程度再通知 ISR。或者有些 RTOS 有 DSR(Deferred Service Routine)的設計,ISR 先立刻把資料搬出來再慢慢處理,避免在 ISR 內處理大量資料。

4. 你的作法是?


沒有留言:

張貼留言