在移植公司的實時作業系統到一款國產 risc-v 架構晶元時,為了測試 systick 中斷是否有效,在此中斷 isr 中對乙個靜態變數加一,打斷點觀察變數的變化來確定中斷是否正確執行了!
中斷 isr 的主要內容如下:
isr_handler
(void
)
在除錯的過程中發現,進入到這個函式後確實給變數加 1 了,但是下一次再進入時變數值又會變為 0,除錯了下彙編沒發現問題。多執行幾次發現效果相同,問題能夠不斷【復現】。
變數的值被意外修改這樣的問題之前也已經遇到過,直接的方法就是 watch 這個變數的位址,在修改的時候程式會停下來,這樣就能看到**進行了非法操作。
可是在此款晶元上上面的方法卻不太適用。雖然可以 watch 乙個變數的位址,但是 watch 之後程式執行非常非常慢,可能要等非常久才能定位到問題,而我有不能減少中間執行的過程,這是乙個常識性的問題,因此這中方式只能棄之不用。
有沒有更好的方式呢?
我仔細的想了想,立刻就想到了一種非常簡單的方式。我可以把這個變數設定為常量,常量一般都儲存在**段,而在我使用的這個晶元上,**段是放在 flash 上面的,要通過普通的訪存指令修改 flash 上面的資料會進入異常,這樣我只需要檢視異常發生的位置就能夠成功定位到出問題的地方。
這樣的方式果然好用,我立刻就發現了問題,可是讓我不解的是它指向了乙個不在**區域內的位置,這可出乎我的意料了。
當我發現問題發生的地方是一段程式區域外的位置,我覺得可能在中斷處理流程中棧幀被修改了,這樣恢復的時候才恢復到了乙個錯誤的位址,這樣的懷疑比較合理。我再回去看了看中斷處理的彙編**,發現我在中斷中切換到了系統棧,將需要儲存的現場儲存到了系統棧中,而我的使用者程式也使用了系統棧,這樣舊的棧幀就被中斷處理過程破壞了,恢復之後就表現出了乙個異常的行為。
其實我切換棧指標這樣的設計是正確的,只是我不應該在非任務環境下測試它。當第乙個任務排程執行之後,中斷打斷的任務與系統棧有不同的棧指標,在這種條件下切換棧指標是正確的。我按照這樣的思路建立了任務,啟動實時作業系統,再次測試便沒有問題了!
在實際的測試中,對一些必要條件的忽略可能會造成嚴重的問題,我們不僅要關注程式執行的流程,更要關注程式執行的環境及程式執行對這一環境帶來的改變
嵌入式的gdb除錯
在開發過程中有很多問題如果用gdb進行除錯跟蹤會大大提高效率,但是我發現不少同事對於gdb除錯概念比較模糊,特別是跨平台的除錯,以至於放棄用gdb除錯而影響排除bug的效率。因此我這裡主要對跨平台除錯做乙個簡要的說明。我們對機頂盒上的軟體進行除錯主要有兩種方式,本地除錯和遠端除錯。遠端除錯還有乙個問...
嵌入式Linux的除錯技術
嵌入式linux的除錯技術 對於複雜的linux驅動及程式庫,需要使用各種方法對其進行除錯。如 設定斷點 逐步跟蹤 輸出除錯資訊等。本章將主要介紹如何利用開發板 android模擬器以及一些函式 工具除錯嵌入式linux核心模組 可執行程式和共享庫。列印核心除錯資訊 printk。該函式的用法與pr...
嵌入式Linux的POLL SELECT 方式
版本 日期作者 說明v1 2020 韋東山摘自 嵌入式linux應用開發完全手冊 簡單地說,它們就是 定個鬧鐘 在呼叫 poll select 函式時可以傳入 超時時間 在這段時間內,條件合適時 比如有資料可讀 有空間可寫 就會立刻返回,否則等到 超時時間 結束時返回錯誤。用法如下。事件型別 說明p...