博客專欄

EEPW首頁 > 博客 > 見鬼,過年回來后板子就 hardfault 了?

見鬼,過年回來后板子就 hardfault 了?

發(fā)布人:魚鷹談單片機 時間:2022-03-19 來源:工程師 發(fā)布文章

快一個月沒有更新了,回家之前給自己安排了很多任務,然后回到家之后電腦就沒有打開過,啥也沒干,不知道有多少人回家后的狀態(tài)和魚鷹是一樣的~~


回來之后,準備搞個腳本,自動讀取芯片 ID、修改頭文件 ID、自動編譯、下載。


折騰了一晚上,讀取 ID 是搞定了,但是發(fā)現有個板子讀取 ID 后下載進去發(fā)現直接 hardfault 了,可自己年前的時候明明代碼沒動、板子沒動,年前都是沒問題的啊。


想不通,反正還有其他板子,直接換一塊,下載進去,完全運行正常。因為太晚了,就暫時不管它。


第二天晚上,還是沒想明白,本想不管的,想想反正沒事情,不如深入研究一下,萬一下次遇到這種問題,那不是很快就能定位了嘛。


第一步,打開錯誤窗口(怎么打開的,自己看往期系列文章吧):

圖片

可以看出,總線錯誤,IMPRECISERR 、STKERR 置位(下面的是 BKPT 是人為給出, FORCED 是因為本來是總線錯誤,但因為沒有開啟該中斷,直接上訪成了 Hardfault,所以真正來說,這次異常應該由總線異常中斷處理的)。


突然想起年前好像也發(fā)生類似的事情,因為當時程序能正常運行,換板子后不能運行,立馬就想到了是芯片差異導致,改了代碼就好了;而現在時間過去太久,把這事情忘記了,就鬧了這一出(當時解決問題太快,也沒深入研究,就沒有多少印象了)。


其實這種事情很多工程師估計都遇到過,本來一個程序需要內存 RAM 40 K,在一塊板子運行的好好的,換一塊就不行,然后發(fā)現芯片實際只有 20K。


一般建工程選芯片型號的時候,就會規(guī)定好 ROM、RAM大小,只要能正常編譯通過,問題都不大,但萬一搞錯了,就可能遇到魚鷹的情況了。

圖片


工程選擇 STM32F103RET6,實際芯片 STM32F103RCT6,內存一個 64 K,一個 48K,偏偏我這個工程內存用量接近滿了(如果 RAM 在 48  K 以內即使下載了也是沒有問題的),程序也能正常下載,但運行之后立刻 Hardfault 伺候。


很多人遇到這個錯誤,束手無策,實際上掌握方法,并不是很難的事情。今天魚鷹教大家一步步排查定位這個錯誤,大家遇到了其他錯誤,也可以按魚鷹的思路解決。

首先,《權威指南》肯定要有,然后就是在線調試了。


從前面的錯誤信息可以了解到這是一個總線錯誤,但是我們看到地址這一欄,發(fā)現并不像有效地址(是否有效可以看 BFARVALID 是否置位),所以先不管它:

圖片


就看那兩個打鉤的位置啥意思了??纯础禖ortex-M3 權威指南》咋說的:

圖片


了解這些就差不多了。


此時,我們就要通過在線調試的方式定位錯誤代碼的位置了,畢竟上面的內容只是給我們一個排查方向,但具體怎么解決還看代碼情況。


通過單步運行(代碼量大的話,可以用二分法排查),并且追蹤到匯編級別的代碼發(fā)現,在即將運行下面代碼時 LDR,[pc, #76],直接跳轉到了 Hardfault:



PUSH {r4,lr}   // 執(zhí)行完成LDR,[pc, #76]  // 未執(zhí)行

執(zhí)行 PUSH {r4,lr}  前,未報錯(黃色光標位置代表即將執(zhí)行但未執(zhí)行的代碼

圖片


執(zhí)行后報錯,但是還沒有運行到 hard fault (單步調試,芯片可能還沒反應過來 -_-):

圖片


當想單步執(zhí)行 LDR,[pc, #76] 時,直接進入了 Hardfault 中斷:

圖片


這樣問題就很明確了,PUSH {r4,lr}  執(zhí)行有問題,這個和前面從權威指南中得到的信息是一致的。


那么為什么壓棧操作會導致問題?


此時我們可以看左邊的寄存器,壓棧前 0x2000F338 ,壓棧后 0x2000F330。


如果對這個數據不敏感,可能不知道這個值超出了 48 K (49152,0xC000)范圍,沒那么快定位。


沒關系,我們可以繼續(xù)看右邊魚鷹給出的內存窗口,壓榨后 0x2000F330 和 0x2000F334 的值應該和 R4、LR 值一一對應,實際上并沒有(先減 4,再賦值,圖片打開后很清晰,認真分析)。


于是很容易可以得出壓棧失敗的結論,進而得出內存訪問問題,從而發(fā)現芯片型號不對導致。


后面魚鷹又查了英文版《Cortex M3與M4權威指南.pdf》,更詳細了一些:

圖片

IMPRECISERR   bit 解釋了:訪問無效內存空間。

圖片


如此一來,hardfault 問題就順利解決了 ^_^ ^_^


工作時間久了,這種問題很容易遇到,那么我們的代碼是否能自動根據某個寄存器來識別芯片型號,從而確定大小,繼而拒絕運行呢?


魚鷹發(fā)現在用 MDK 更新  ST-LINK 固件的時候,它居然知道我芯片型號的準確容量大小(RAM 不行),從而拒絕下載,ST-LINK Utility 也是,就不知道它是通過讀取哪個寄存器得到這些信息的了,有知道的道友不如留言分享一下。


圖片


*博客內容為網友個人發(fā)布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。

萬能遙控器相關文章:萬能遙控器代碼


波段開關相關文章:波段開關原理


電容式接近開關相關文章:電容式接近開關原理
電機保護器相關文章:電機保護器原理
接近開關相關文章:接近開關原理


關鍵詞: 單片機

相關推薦

技術專區(qū)

關閉