iot-fan

联系: iotfan123#163.com
注意:
1,本博客之内容来源于网上收集以及相关技术人员提供,如果有侵犯到您的权益,请电邮我沟通;
2,本博客之内容乃分享,交流,学习,研究之目的,作者不对内容的真实性,有效性,及时性负责,也不对因本博客的任何内容导致的任何后果负责;
3,本博客之内容禁止转发到CSDN网站,转到别的网站请保留出处.

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

本文目的

本文将记录如何在沁恒的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);
}
posted on 2022-03-25 11:41  iot-fan  阅读(2501)  评论(0编辑  收藏  举报