日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

定位ARM Hard Fault 的方法

發布時間:2025/4/5 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 定位ARM Hard Fault 的方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1,??用Keil的話,可以做如下操作:

先將fault中斷函數的內容改為:

HardFault_Handler\

????????????????PROC

????????????????;EXPORT??HardFault_Handler?????????[WEAK]

????????????????;B??????????????????.

????????????????????????????????IMPORT hard_fault_handler_c ?

????????????????????????????????TST LR, #4??

????????????????????????????????ITE EQ??

????????????????????????????????MRSEQ R0, MSP??

????????????????????????????????MRSNE R0, PSP??

????????????????????????????????B hard_fault_handler_c??

????????????????ENDP

************************************************insert start*************************************************

摘抄自Triton.zhang——eeworld

1. MSP和PSP 的含義是Main_Stack_Pointer 和Process_Stack_Pointer,在邏輯地址上他們都是R13

2. 權威手冊上說的很清楚PSP主要是在Handler的模式下使用,MSP主要在線程模式下使用(當然你在線程模式下也可以調用PSP,需要你做特殊的處理).
3. 這意味著同一個邏輯地址,實際上有兩個物理寄存器,一個為MSP,一個為PSP,在不同的工作模式調用不同的物理寄存器。舉一個簡單的例子,很多MCU的的UART只有一個BUFF,TXBUFF和RXBUFF都是一個地址,當你寫BUFF時寫入的是TXBUFF, 讀操作時調用的是RXBUFF。基本原理就是這樣。
4. 至于為什么這么設計,我想是為了在進行模式轉換的時候,減少堆棧的保存工作。同時也可以為不同權限的工作模式設置不同的堆棧。

************************************************insert end***************************************************

然后在源程序里添加下面的函數代碼:

// hard fault handler in C,??

// with stack frame location as input parameter??

void hard_fault_handler_c(unsigned int * hardfault_args)??

{??

unsigned int stacked_r0;??

unsigned int stacked_r1;??

unsigned int stacked_r2;??

unsigned int stacked_r3;??

unsigned int stacked_r12;??

unsigned int stacked_lr;??

unsigned int stacked_pc;??

unsigned int stacked_psr;??

stacked_r0 = ((unsigned long) hardfault_args[0]);??

stacked_r1 = ((unsigned long) hardfault_args[1]);??

stacked_r2 = ((unsigned long) hardfault_args[2]);??

stacked_r3 = ((unsigned long) hardfault_args[3]);??

stacked_r12 = ((unsigned long) hardfault_args[4]);??

stacked_lr = ((unsigned long) hardfault_args[5]);??

stacked_pc = ((unsigned long) hardfault_args[6]);??

stacked_psr = ((unsigned long) hardfault_args[7]);??

printf ("[Hard fault handler]\n");??

printf ("R0 = %x\n", stacked_r0);??

printf ("R1 = %x\n", stacked_r1);??

printf ("R2 = %x\n", stacked_r2);??

printf ("R3 = %x\n", stacked_r3);??

printf ("R12 = %x\n", stacked_r12);??

printf ("LR = %x\n", stacked_lr);??

printf ("PC = %x\n", stacked_pc);??

printf ("PSR = %x\n", stacked_psr);??

printf ("BFAR = %x\n", (*((volatile unsigned long *)(0xE000ED38))));??

printf ("CFSR = %x\n", (*((volatile unsigned long *)(0xE000ED28))));??

printf ("HFSR = %x\n", (*((volatile unsigned long *)(0xE000ED2C))));??

printf ("DFSR = %x\n", (*((volatile unsigned long *)(0xE000ED30))));??

printf ("AFSR = %x\n", (*((volatile unsigned long *)(0xE000ED3C))));??

???

while(1)

{

????????;;

}

}??

如果使用調試器,則可以在第一個printf處設置斷點.沒有的話看串口打印結果

通過查看stacked_lr的內容可以知道程序運行到哪個位置出現fault

然后查看編譯后匯編代碼,可以知道源程序是哪個函數哪一步出現問題,

配合其它寄存器的內容來分析找出原因

2.用IAR的話,把startup_ewarm.c文件中的FaultISR()函數的內容改為:

volatile unsigned int stacked_r0;??

volatile unsigned int stacked_r1;??

volatile unsigned int stacked_r2;??

volatile unsigned int stacked_r3;??

volatile unsigned int stacked_r12;??

volatile unsigned int stacked_lr;??

volatile unsigned int stacked_pc;??

volatile unsigned int stacked_psr;??

//unsigned long cc;

stacked_r0 = ((unsigned long) hardfault_args[0]);??

stacked_r1 = ((unsigned long) hardfault_args[1]);??

stacked_r2 = ((unsigned long) hardfault_args[2]);??

stacked_r3 = ((unsigned long) hardfault_args[3]);??

stacked_r12 = ((unsigned long) hardfault_args[4]);??

stacked_lr = ((unsigned long) hardfault_args[5]);??

stacked_pc = ((unsigned long) hardfault_args[6]);??

stacked_psr = ((unsigned long) hardfault_args[7]);??

printf ("[Hard fault handler]\n");??

printf ("R0 = %x\n", stacked_r0);??

printf ("R1 = %x\n", stacked_r1);??

printf ("R2 = %x\n", stacked_r2);??

printf ("R3 = %x\n", stacked_r3);??

printf ("R12 = %x\n", stacked_r12);??

printf ("LR = %x\n", stacked_lr);??

printf ("PC = %x\n", stacked_pc);??

printf ("PSR = %x\n", stacked_psr);??

printf ("BFAR = %x\n", (*((volatile unsigned long *)(0xE000ED38))));??

printf ("CFSR = %x\n", (*((volatile unsigned long *)(0xE000ED28))));??

printf ("HFSR = %x\n", (*((volatile unsigned long *)(0xE000ED2C))));??

printf ("DFSR = %x\n", (*((volatile unsigned long *)(0xE000ED30))));??

printf ("AFSR = %x\n", (*((volatile unsigned long *)(0xE000ED3C))));??

???

??while(1)

??{

??????????;;

??}

如果使用調試器,則可以在第一個printf處設置斷點.沒有的話看串口打印結果

通過查看stacked_lr的內容可以知道程序運行到哪個位置出現fault

然后查看編譯后匯編代碼,可以知道源程序是哪個函數哪一步出現問題,

配合其它寄存器的內容來分析找出原因

另一種方法:
? ? 默認的HardFaudler 處理方法不是死循環么?將它改成BX LR直接返回的形式。然后再這條語句打個斷點,一旦在斷點中停下來,說明出錯了,然后再返回,就可以返回到出錯的位置的下一條語句哪里。
_asm void wait()
{
? ? BX lr ?//BX無條件轉移指令
}


void HardFault_Handler(void)
{
? ? wait();

}

【ARM 匯編基礎速成6】ARM匯編之條件執行與分支 - 簡書

ARM 指令舉例

  • SWI_Exception:
  • STMFD SP!, {R2-R3,LR} //把R2,R3,LR值入棧
  • #0號軟中斷的處理程序
  • CMP R0, #0 //將R0和0比較
  • //以下4行帶EQ條件的代碼均為當R0為0時應該執行的語句
  • MRSEQ R2, SPSR //把SPSR讀入到R2中
  • STREQ R2, [R1] /把R2的值存入到[R1]中
  • ORREQ R2, R2, #0x80 //把R2的Bit7位置1
  • MSREQ SPSR_c, R2 //把R2的值寫入到SPSR_c中,即禁止IRQ
  • #1號軟中斷的處理程序
  • CMP R0, #1 //比較R0值和1
  • LDREQ R2, [R1] //相等則把[R1]中的數據存入R2中
  • MSREQ SPSR_c, R2 //相等把R2的值寫入到SPSR_c中,恢復IRQ
  • #11號軟中斷的處理程序
  • CMP R0, #11 //比較R0的值和11
  • MRSEQ R2, SPSR //相等則把SPSR的值轉存入到R2中
  • BICEQ R2, R2, #0x1F //相等則把R2的Bit0~Bit4全部清零
  • ORREQ R2, R2, #Mode_SYS //相等則把R2與#Mode_SYS相與再存入R2
  • MSREQ SPSR_c, R2 //相等則把R2的值存入SPSR_c中,即進入系統模式
  • #12號軟中斷的處理程序
  • CMP R0, #12 //比較R0的值和12
  • MRSEQ R2, SPSR //相等則把SPSR的值存入R2
  • BICEQ R2, R2, #0x1F //相等則把R2的Bit0~Bit4清零
  • ORREQ R2, R2, #Mode_USR //相等則把R2與#Mode_USR相與再存入R2中
  • MSREQ SPSR_c, R2 //相等則把R2存入SPSR_c,即進入用戶模式
  • LDMFD SP!, {R2-R3,PC} //恢復R2、R3、PC值,返回
  • .END //匯編代碼段結束
  • 總結

    以上是生活随笔為你收集整理的定位ARM Hard Fault 的方法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。