CH57x/CH58x/CH32V wch risc-v 芯片hardfault問題追蹤&程序卡死追蹤


本文目的

本文將記錄如何在沁恆的risc-v芯片上進行hardfalt問題追蹤,以及找出程序卡死的地方

適用芯片

  • CH573/CH571
  • CH583/CH582/CH581
  • CH565/569
  • CH32V series

說明

hardfault 問題追蹤

人為制造hardfault

(下面使用CH582為例)
這里我們寫了個能夠的產生hardfault中斷的代碼,調用下面函數即可

//對非4字節對齊的地址取uint32_t
void hardfault_test(void) {
    printf("hardfault test\r\n");
    DelayMs(100);
    for(uint32_t i=0;i<16;i++) {
        printf("test:%08X\r\n",*(uint32_t *)(0x500+i));
    }
}

修改hardfault中斷函數,加入一些打印信息

在官網默認例程的下面路徑文件
EXAM/SRC/StdPeriphDriver/CH58x_sys.c
里面有個hardfault的handler函數,默認情況下是復位,當開發過程中發現代碼容易異常復位時候,
我們可以考慮是不是產生了hard fault中斷,我們可以修改該代碼如下:


__attribute__((section(".highcode")))             //put in ram
__attribute__((interrupt("WCH-Interrupt-fast")))  //disable soft push/pull
void HardFault_Handler(void) {
    uint32_t v_mepc,v_mcause,v_mtval;
    printf("hardfault\n");
    
    v_mepc=__get_MEPC();
    v_mcause=__get_MCAUSE();
    v_mtval=__get_MTVAL();

    printf("mepc:%08x\n",v_mepc);
    printf("mcause:%08x\n",v_mcause);
    printf("mtval:%08x\n",v_mtval);
    while(1);
}

獲取打印結果

hardfault
mepc:0000090c
mcause:00000004
mtval:00000501

上面我們加了 mepc mcause 和mtval 三個參數的打印,
這個實際上是分別對應 產生hardfault前的指令運行的地址,產生該異常的原因,和產生該異常時候存取的地址

mepc

這個我們可以在編譯輸出的lst文件打開查看即可:
ch58x_hardfaut_catch_test.lst
很明顯就在我們人為造的函數里面,我們可以找到0x90c地址對應的行:

000008dc <hardfault_test>:
     8dc:	1141                	addi	sp,sp,-16
     8de:	00001517          	auipc	a0,0x1
     8e2:	56e50513          	addi	a0,a0,1390 # 1e4c <_sbrk+0x54>
     8e6:	c606                	sw	ra,12(sp)
     8e8:	c422                	sw	s0,8(sp)
     8ea:	c226                	sw	s1,4(sp)
     8ec:	c04a                	sw	s2,0(sp)
     8ee:	2ecd                	jal	ce0 <puts>
     8f0:	06400513          	li	a0,100
     8f4:	20000097          	auipc	ra,0x20000
     8f8:	9d6080e7          	jalr	-1578(ra) # 200002ca <mDelaymS>
     8fc:	50000413          	li	s0,1280
     900:	00001917          	auipc	s2,0x1
     904:	55c90913          	addi	s2,s2,1372 # 1e5c <_sbrk+0x64>
     908:	51000493          	li	s1,1296
     90c:	400c                	lw	a1,0(s0)
     90e:	854a                	mv	a0,s2
     910:	0405                	addi	s0,s0,1
     912:	2c45                	jal	bc2 <iprintf>
     914:	fe941ce3          	bne	s0,s1,90c <hardfault_test+0x30>
     918:	40b2                	lw	ra,12(sp)
     91a:	4422                	lw	s0,8(sp)
     91c:	4492                	lw	s1,4(sp)
     91e:	4902                	lw	s2,0(sp)
     920:	0141                	addi	sp,sp,16
     922:	8082                	ret

mcause

這里我們不是正常的中斷,而是hardfault,所以折了的mcause對應的是Load address misaligned

Interrupt Exception Code Description
1 0 User software interrupt
1 1 Supervisor software interrupt
1 2 Hypervisor software interrupt
1 3 Machine software interrupt
1 4 User timer interrupt
1 5 Supervisor timer interrupt
1 6 Hypervisor timer interrupt
1 7 Machine timer interrupt
1 8 User external interrupt
1 9 Supervisor external interrupt
1 10 Hypervisor external interrupt
1 11 Machine external interrupt
1 ≥12 Reserved
0 0 Instruction address misaligned
0 1 Instruction access fault
0 2 Illegal instruction
0 3 Breakpoint
0 4 Load address misaligned
0 5 Load access fault
0 6 Store/AMO address misaligned
0 7 Store/AMO access fault
0 8 Environment call from U-mode
0 9 Environment call from S-mode
0 10 Environment call from H-mode
0 11 Environment call from M-mode
0 ≥12 Reserved

mtval

mtval:00000501
這里我們正是對0x501地址取uint32_t 才產生的hardfault

代碼卡死的地方追蹤

待編輯

其他

串口發送放到RAM里面

有時候出現hardfault可能比較特殊,比如flash讀取異常,這時候我們可能需要把hardfault以及相關調用放到ram里面
下面我們在CH582上直接通過查表法,使用串口1直接輸出對應值的字符串,方便我們用串口調試工具觀看

uint8_t char_mapping[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
__attribute__((section(".highcode")))
void uart1_send_uint32(uint32_t num){
    for( uint32_t i=0; i<8; i++ ) {
        while(R8_UART1_TFC == UART_FIFO_SIZE);
        R8_UART1_THR = char_mapping[(num>>28)&0xf];
        num <<=4;
    }
}
__attribute__((section(".highcode")))
void uart1_send_newline(){
        while(R8_UART1_TFC == UART_FIFO_SIZE);
        R8_UART1_THR = '\n';
}

__attribute__((section(".highcode")))             //put in ram
__attribute__((interrupt("WCH-Interrupt-fast")))  //disable soft push/pull
void HardFault_Handler(void) {
    SetSysClock(CLK_SOURCE_PLL_60MHz);
    DelayMs(1);
    uint32_t v_mepc,v_mcause,v_mtval;

    //v_mepc=__get_MEPC();
    //v_mcause=__get_MCAUSE();
    //v_mtval=__get_MTVAL();

    __asm volatile("csrr %0,"
                   "mepc"
                   : "=r"(v_mepc));

    __asm volatile("csrr %0,"
                   "mcause"
                   : "=r"(v_mcause));

    __asm volatile("csrr %0,"
                   "mtval"
                   : "=r"(v_mtval));

    uart1_send_uint32(v_mepc);
    uart1_send_newline();


    uart1_send_uint32(v_mcause);
    uart1_send_newline();
    uart1_send_uint32(v_mtval);
    uart1_send_newline();

    while(1);
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM