在進行CortexM系列MCU開發(fā)時,大家應該都或多或少觸發(fā)過不可屏蔽中斷,例如人見人愛的Hardfault。
對于嵌入式工程師來說,能夠穩(wěn)定復現(xiàn)的Bug最好解決,再不濟挨個打斷點也能定位到問題代碼位置。
可是異常如果是不定時,無規(guī)律的發(fā)生在日常的運行中,那打斷點的方式無異于守株待兔。
本篇將提供小技巧簡述CortexM的異常壓棧機制,教大家如何寫出一個現(xiàn)場保存函數(shù)以及如何調用該函數(shù)。
如下圖所示,觸發(fā)中斷的時候,CortexM?系列芯片會按照該排列將相關現(xiàn)場數(shù)據(jù)進行地址偏移壓棧,N即此時的SP數(shù)值,通過SP中存放的地址,我們可以獲取到如圖所示的數(shù)據(jù)。
而要知道觸發(fā)異常的地址則需要關注LR(Link Register)的數(shù)值,它存放著異常觸發(fā)點的函數(shù)地址。
那么按照壓棧的排列,我們可以編寫一個結構體以及相關的記錄現(xiàn)場函數(shù),如下圖所示,結構體的成員完全是按照上圖的壓棧順序排列,那下一步就是在哪里調用這個接口來獲取到案發(fā)時的第一手資料
?要想獲得第一手數(shù)據(jù),就要去中斷函數(shù)的執(zhí)行處,很多廠商的SDK都會在名為XXX_it.c文件里為開發(fā)者們寫好各個中斷的Handler,由于S文件中都是弱定義(弱定義即在C文件中有同名的函數(shù),則以C文件中的函數(shù)優(yōu)先編譯,則可能造成觸發(fā)中斷時并不會運行S文件處的函數(shù))所以建議可以將其屏蔽或者自己重新編寫一個新的函數(shù)名。
由下圖可見,通過IMPORT的形式調用外部現(xiàn)場保存函數(shù),將SP寄存器賦值給R0寄存器是因為R0通常時作為函數(shù)的第一個參數(shù)進行調用的,可看作是將SP數(shù)值作為參數(shù)傳入StackSave函數(shù),BL的意思是帶返回的跳轉,即使跳轉運行完成StackSave函數(shù)后還返回此處。
完成上述函數(shù)編寫以及調用后,即可進行測試了。本次范例通過SPI初始化時傳入錯誤的外設寄存器地址來觸發(fā)HardFault中斷,由下圖可看出,此時記錄到的LR數(shù)值為0x8000e83
?查詢后可知,0x8000e83的位置為SPI初始化函數(shù)中,符合預設的異常觸發(fā)位置。在非仿真環(huán)境下可通過map文件找到大致的函數(shù)地址。
綜上,我們就知道了如何獲取到觸發(fā)異常中斷時的程序運行地址,通過將獲取到的信息存入到片上Flash指定地址的形式將此時的現(xiàn)場信息進行保存,并通過固件和map一一對應管控。
這樣在漫長運行過程中,如果不慎觸發(fā)異常異常中斷,通過對應的map文件即可迅速定位BUG所在大致位置?
-
寄存器
+關注
關注
31文章
5336瀏覽量
120230 -
仿真器
+關注
關注
14文章
1017瀏覽量
83721 -
串口中斷
+關注
關注
0文章
64瀏覽量
13882 -
Flash單片機
+關注
關注
0文章
111瀏覽量
9401 -
MCU芯片
+關注
關注
3文章
250瀏覽量
11437
發(fā)布評論請先 登錄
相關推薦
評論