ARM中Bus Error的测试
在芯片測(cè)試的時(shí)候,我們有時(shí)候會(huì)碰到Bus Error的情況,這種情況下程序會(huì)進(jìn)到bus error的中斷中,中斷返回的時(shí)候,再次回到原來位置,訪問地址的時(shí)候再次進(jìn)入中斷,這樣就造成程序不停進(jìn)中斷,導(dǎo)致正常測(cè)試被打斷。為了避免這種情況的發(fā)生,我們需要修改程序返回的地址,這里面涉及的東西就有點(diǎn)復(fù)雜了,這里簡(jiǎn)單記錄一下。
問題分析
上面例子中,我們?cè)L問了一個(gè)非法的地址產(chǎn)生中斷,程序會(huì)將必要的寄存器壓棧之后跳轉(zhuǎn)到中斷中執(zhí)行,中斷執(zhí)行完畢之后,從棧中取出之前的程序指針繼續(xù)執(zhí)行。
這個(gè)流程比較簡(jiǎn)單,其實(shí)問題的解決方法也在這個(gè)流程里面,因?yàn)橹袛喾祷刂筮€是回到出問題的地址,再次運(yùn)行引發(fā)連續(xù)中斷,所以我們只需要將程序返回到的地址加一個(gè)偏移,直接讓他到下一條指令就好了(暫時(shí)先不管16位和32位指令,統(tǒng)一認(rèn)為是32位的指令,即使是16位指令,我們可以直接跳過兩條指令)。如果想維持程序運(yùn)行完整性,可以在預(yù)期出現(xiàn)中斷的指令后面加若干NOP指令。
代碼實(shí)現(xiàn)
因?yàn)闋砍兜綄?duì)程序棧的操作,所以一般的C語(yǔ)言是搞不定的,這里我們就必須通過匯編實(shí)現(xiàn):
typedef struct {uint32_t r0;uint32_t r1;uint32_t r2;uint32_t r3;uint32_t r12;uint32_t lr;uint32_t pc;uint32_t psr; } hw_stackframe_t; void default_isr(void) {// set up arguments and call _hardfault_israsm("mov r0, lr\n" // arg 0"mrs r1, psp\n" // arg 1"mrs r2, msp\n" // arg 2"b _default_isr\n"); } static void _default_isr(uint32_t lr, void *psp, void *msp) __attribute__((used)); static void _default_isr(uint32_t lr, void *psp, void *msp) {#define VECTORNUM (*(volatile uint8_t*)(0xE000ED04))hw_stackframe_t *frame;// Find the active stack pointer (MSP or PSP)if(lr & 0x4)frame = psp;elseframe = msp;printf("\r\n** HARD FAULT **\r\n\tpc=0x%x\r\n\tmsp=0x%p\r\n\tpsp=0x%p\r\n",frame->pc, msp, psp);printf("\r\n****default_isr entered on vector %d*****\r\n",VECTORNUM);// add PC by 4frame->pc += 4;return; }上述代碼中的結(jié)構(gòu)體就是描述了一個(gè)堆棧信息,匯編中會(huì)直接將lr,?psp,?msp存入r0~2作為參數(shù),然后跳轉(zhuǎn)到_default_isr中實(shí)現(xiàn)參數(shù)調(diào)用,這樣lr,?psp,?msp就直接成為C函數(shù)的參數(shù),我們也就可以很方便的使用里面的內(nèi)容了,得到這幾個(gè)寄存器的值之后我們判斷當(dāng)前用到的堆棧指針地址,并讓我們定義的結(jié)構(gòu)體指針指向這個(gè)地址,之后就可以通過結(jié)構(gòu)體實(shí)現(xiàn)對(duì)堆棧中內(nèi)容進(jìn)行讀寫操作了。
這里我們就是簡(jiǎn)單的把PC加4就可以了。
總結(jié)
以上是生活随笔為你收集整理的ARM中Bus Error的测试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bss,data,text,rodata
- 下一篇: Cotex-M内核双堆栈指针MSP和PS