NRF52832调试方法1——HardFault_Handler问题定位

一、遇到问题

在运行官方SDK(V17.0.2)的examples: bsp例程时,此例程时钟使用了32.768kHz的低速时钟。我碰到了硬件错误,下面随我一起来找一下原因。

在keil的debug模式下,直接点击全速运行(Run)发生程序卡死,debug显示停到了HardFault_Handler位置,如下图所示。

此时使用navigate backwards(蓝色左箭头)是找不到C代码卡在了何处,毕竟让keil记住整个代码的执行过程,太过于为难它了。

二、解决办法

1.此时首先观察register窗口,观察Stack是否为MSP.

2.栈中定位函数

若Stack为MSP,则复制R13(SP)的值到memory观察窗的地址搜索栏。在我的keil中,每一行显示连续的28个地址上的存储信息,每个地址上存有一个字节的数据。

从第21个位置起的连续四个字节是LR的值,LR( link register)是用于保存函数调用的返回地址. 如上图所示:LR = 0x00001A37. 有了这条地址我们基本上可以找到导致程序卡死的函数。

3.反汇编中找到确切语句

在Disassembly栏中空白处点击右键,选择show disassembly at address,输入LR的值,此时C代码栏已经可以定位到该语句处(蓝色箭头所指的430行处)。

三、问题解决

  既然已经定位到了错误代码,那就去go to definition看一下。找到上图中timestamp_func()的函数定义,该函数的作用是:timestamp_func Function for getting a 32-bit timestamp,即debug时用于输出调试信息的时间。

经过查找发现:timestamp_func函数是通过函数指针传入nrf_log_init函数。nrf_log_init的第一个形参是timestamp_func,而该函数的第二个形参为timestamp_freq(时间戳的频率)。而恰恰是因为log初始化函数的第二个参数与实时性有关,导致log函数无法完成初始化,这又是为什么呢?

答案是:我的板子上52832并没有32.768kHz的晶振,因此log函数无法进行时间戳的操作,请看下图。

这段代码是在nrf_log_ctrl_internal.h头文件中的起始处。定义了宏:#define NRF_LOG_LFCLK_FREQ 32768,从图中的几行宏中我们可以发现:NRF_LOG_LFCLK_FREQ 和时间戳的操作紧密相关,因此可以得出结论:如果debug时需要打印时间戳,一定要让32.768kHz的晶振起振。

解决办法:在sdk_config.h头文件中将时间戳的宏不使能后,并注释掉main函数的clock_initialization函数后,J-Link RTT Viewer可以成功打印出调试信息。

 

四、总结

此篇blog记录了一次hardfault的调试过程,此次造成hardfault的根本原因是:缺少低速晶振,纯硬件问题。但在调试中得出了一个结论:timestamp_func函数(log的时间输出)需要配合32.768kHz晶振一起使用,也算是收获了一个NRF52832的调试经验。

 

 

 

 

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值