Cortex-M3開發經驗(二):肯定發生HardFault的地方

Cortex-M3開發經驗(二):肯定發生HardFault的地方

咱們在調試時,最懼怕就是出現HardFault錯誤了。由於咱們不知道是從哪一個地方跳到這裏的?單步調試起來太過於麻煩,特別在代碼量大的時候,更是費時間。函數

那麼有沒有一種方法,能夠快速定位到發生HardFault錯誤的代碼位置(函數)呢?工具

Cortex-M3中斷/異常的響應過程

咱們知道,HardFault實質上是一箇中斷,中斷的過程以下圖:指針

FUNC1->IRQ_Handler:發生中斷
Note right of IRQ_Handler:中斷處理函數
IRQ_Handler->FUNC1:中斷返回

在這裏我就有一個疑問了:既然FUNC1和IRQ_Handler之間不存在調用關係,那IRQ_Handler運行完以後怎麼返回到FUNC1中去的呢?調試

中斷/異常響應原理:當Cortex-M3響應一箇中斷時,會在它體內奔涌起三股暗流:code

1.入棧:吧8個寄存器(R0~R3,R12,LR,PC,xPSR)的值壓入棧中;blog

2.取向量:從向量表中找出對應的中斷服務程序入口地址(函數指針的原理);開發

3.更新PC指針,堆棧指針SP,鏈接寄存器LR的值。編譯器

摘自《ARM Cortex M3權威指南》編譯

明白原理後,就好辦了。那麼咱們在HardFault函數中打一個斷點,在他剛進入中斷時,內核寄存器的值,就是保存發生中斷那一刻的值。咱們就能夠經過這些值,獲得發送錯誤的位置。table

下圖是出現錯誤時狀態:

咱們關注SP寄存器的值:0x2000FFAC,咱們再查看SP地址附近所對應的值。

address value
0x2000FFAC 0x2000FFD0
0x2000FFB0 0x0000000D
0x2000FFB4 0x00000000
0x2000FFB8 0x00000000
0x2000FFBC 0x0001F204
0x2000FFC0 0xA5A5A5A5
0x2000FFC4 0x0001F239
0x2000FFC8 0x0001F204
0x2000FFCC 0x00000000
0x2000FFD0 0x8000000C

咱們須要的是PC和LR的值,由於這兩個寄存器表明的是:PC表明當前執行位置,LR表明返回地址。

從棧空間咱們能夠得知:PC的值爲0x0001F204, LR的值爲0x1F239。

怎麼找的?

很簡單,咱們知道進入中斷處理函數後,內核依次將xPSR,PC,LR,R12,R3,R2,R1,R0的順序入棧。(至於爲何是這個順序,請看Cortex-M3權威指南)。而後咱們須要知道棧的操做方式(滿減,空減,滿增,空增),而Cortex-M3屬於滿減棧,就是堆棧指針指向最後一個被壓入堆棧的32位數值;PUSH壓棧時,SP先自減4,再存入新值,POP出棧時相反,先從SP指針處讀出上次被壓入堆棧的值,SP再自增4。

因此咱們要從0x2000FFD0開始看起,PC跟LR是第二跟第三入棧的。因此就是0x2000FFC8和0x2000FFC4對應的值。

發生HardFault時,PC正在執行0x1F204地址的指令,LR是準備返回的地址0x1F239。

怎麼看這兩個地址所在的函數?

有兩個方法:

1.看編譯器生成的map文件。

2.使用編譯工具鏈的addr2line,以下:

arm-none-eabi-addr2line 1f204 -f -e xxxx.elf    (燒錄文件)
>fp_test    (函數名)
>..../main.c:129    (對應文件及行號)

arm-none-eabi-addr2line 1f239 -f -e xxxx.elf
>test
>..../main.c:142
相關文章
相關標籤/搜索