12.Ubuntu下开发STM32--HardFault,div0

16 篇文章 1 订阅
6 篇文章 0 订阅

看了creep发的一篇帖子https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=602444&highlight=hardfault,讲解的是如何找出程序中的HardFault。creep的帖子中提到了一个老外的链接http://blog.feabhas.com/2013/02/developing-a-generic-hard-fault-handler-for-arm-cortex-m3cortex-m4/,讲解的是如何使用keil mdk找出因除0导致的HardFault。keil mdk自然是挺好用的,可是linux下开发调试和windows下开发调试稍有不同。下面就在linux环境下讲解一下如何进行调试。

工程使用的是硬件浮点。要注意的是,如果是小数除法,不管是不是打开了DIV_0_TRP,结果在使用printf输出的时候都是inf。只有整数除法在开启DIV_0_TRP的时候,才会触发HardFault。下面是main函数的测试代码:


int main(void)
{
        int a=3,b=2;
        printf("Try test div0 before set CCR:%d\n",a/0);
        
        printf("\nSet SCB->CCR |= 0x10\n");
        SCB->CCR |= 0x10;
        
        printf("Try test div0 after set DIV_0_TRP,the result is:");
        printf("%d\n",a/0);
        
        return 0;
}

void HardFault_Handler(void)
{
        __asm__ __volatile__ ("mrs r0,MSP");
        __asm__ __volatile__ ("bl print_sp");
        
        while(1) ;
}

void print_sp(unsigned int *sp)
{
        printf("the sp address is :%x\n",(unsigned int)sp);
        for(int i=0;i<9;i++)
                printf("sp[%d]=%x\n",i,sp[i]);
}

将代码编译好之后,使用gdb进行调试。先在HardFault_Handler处点一个断点:之后输入continue。使代码继续运行。这时候,在开启

DIV_0_TRP之前,进行除0运算的结果是0。没有引发HardFault。当开启了DIV_0_TRP之后,进入了HardFault。这时候可以使用info reg查看一下相关的寄存器。

img

查看reg发现LR寄存器的数值是0xFFFF_FFF9。具体为什么是这个值,可以查看creep的原帖。

img

进入中断之后,需要知道是什么原因导致了HardFault。有两个相关的寄存器。分别是SCB->HFSR, SCB->CFSR.他们的地址分别是0xE000_ED2C,0xE000_ED28.使用x命令查看这两个地址:(从0xE000_ED28出查看了两个字)。关于这两个寄存器的详细解释请参考网址:HFSRCFSR。说明问题是由除0导致的。具体导致这个HardFault的地址在入栈的PC处。

img

img

从info reg的信息中,我们可以找到进入HardFault的时候栈的地址。同样,使用x命令从sp的地方读取几个字看看:ARM在发生异常的时候会在SP中将R0-R3,R12,LR,PC,PSR进行压栈。只要我们找出栈中的PC,这个值也就是导致异常的代码处。你可能会从0x2000_FFF0开始数,认为他是R0。但是在ARM GCC中,这样是不对的。

img

使用disasseble查看当前位置的汇编代码:发现在当前的位置(也就是图中=>指向的位置)之前,已经发生过一次push了。因此sp中最新的一个数据应该是push的R7。所以x/10xw读出来的第一个数据是进入HardFault之后push的R7。从0x30处开始的数据才是进入中断之前自动压栈的。这样说,读出的PC也就是0x0800_2686.

img

对elf文件进行反汇编,查看0x0800_2686处的指令:从这个地方可以找到我们的硬件除法的指令。因为除0导致的HardFault。

img

img

整个Makefile的工程在附件中可以下载。
另外,感到ARM GCC比较任性。看HardFault_Handler的代码,因为代码最后是一个死循环,代码索性连之前push的R7也不pop了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值