解决段错误,系统应用core dump的分析

     解决段错误,系统应用core dump的分析    
这个错误在单片机上往往以hardfault的错误出现,分析思路都是分析堆栈的位置;
单片机的编译软件,如果可以仿真(比如keil或者IAR),复现故障,过程中可以通过在hardfault打断点方式,开启堆栈查看工具,直接定位出错位置;

如果不可以仿真,可以在出错位置(比如hardfault函数内),直接用串口或者其他输出工具,输出寄存器的数值,以方便定位出错的代码位置;比如下方的方式

//1.关于HardFault_Handler 这个函数,一般在stm32_f4xx.s的中断向量表中系统中的代码如下所示
 g_pfnVectors:
  .word  _estack
  .word  Reset_Handler
  .word  NMI_Handler
  .word  HardFault_Handler  //!!!
  .word  MemManage_Handler
  .word  BusFault_Handler
  .word  UsageFault_Handler

//2.实体如下:一般为空,在其中添加如下
void HardFault_Handler(void)
{
    asm("TST LR, #4");//TST 是Bit级别的与操作
    asm("ITE EQ");
/*ITE 是 MRSEQ和MRSNE都是两个命令的合体,分别可以拆开成:MRS,EQ和MRS,NE,分别的意思是如果两者相等,则把MSP的值赋值到R0,如果R0和PSP不等,则把PSP赋植到R0.ITE读为 if-then-else*/
    asm("MRSEQ R0, MSP");
    asm("MRSNE R0, PSP");
    asm("B HardFault_HandlerC"); //在此定义跳转函数 hard_fault_handler_c
}
//不用asm汇编调用,也可以直接在stm32_f4xx.s中定义.cpu cortex-m3
.thumb
.global HardFault_Handler
.extern hard_fault_handler_c

HardFault_Handler:
TST LR, #4
ITE EQ
MRSEQ R0, MSP
MRSNE R0, PSP
B hard_fault_handler_c //在此定义跳转函数 hard_fault_handler_c


//3.实现跳转函数 hard_fault_handler_c
oid 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 ("\n\n[Hard fault handler - all numbers in hex]\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 [R14] = %x subroutine call return address\n”, stacked_lr);
printf (“PC [R15] = %x program counter\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))));
printf (“SCB_SHCSR = %x\n”, SCB->SHCSR);

while (1);
}

//此中,如果没有串口或其他输出途径,根据需要可以加入参数保存进入flash;、

出现异常时的寄存器、堆栈、状态寄存器等信息打印出来,然后根据编译器生成的map 文件,找到出现问题的具体函数:查看方式-->

stm32 HardFault_Handler调试及问题查找方法——飞思卡尔

2.linux--借助crash文件--core文件来查找文件

(1)pc-gdb环境搭建
(2)开发板--gdbserver搭建
(3)pc和开发板的网络正常
(4)开启core dump开关(ulimite -a),然后直接运行程序(如果在线调试需要gdbserver在开发板运行),复现故障,产生core文件(在线调试不需要该文件了),将core文件 通过pc的gdb调试开发查看dump原因
具体如下
1.一般交叉编译已经自带了 gdb 和 gdbserver,因此可以不用移植,直接使用交叉编译器自带
的即可。比如本教程所使用的 arm-linux-gnueabihf-gcc 就自带了主机使用的 arm-linux-gnueabihfgdb 和开发板所使用的 gdbserver。进入 ubuntu 中交叉编译器安装目录中的 bin 文件夹下,比如笔者的就是/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin,此目录中就包含了 arm-linux-gnueabihf-gdb 和 gdbserve
如果交叉编译器没有自带 gdb 和 gdbserver 那就需要自己手动编译了
...此处省略...具体看网上。。。
直接到第四步:|默认在根目录下

arm-linux-gdb /nfsroot/kf-can_app /nfsroot/core输入后
再输入where指令就可以查看堆栈信息了;

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaoxilang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值