如何调试nRF5 SDK
Posted iini
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何调试nRF5 SDK相关的知识,希望对你有一定的参考价值。
本文将讲述Nordic nRF5 SDK的主要调试手段,以帮助大家快速定位问题,并解决问题。
1. 通过打log方式进行调试
nRF5 SDK支持UART和SWD J-Link两种底层通信方式来打印日志,其中UART使用串口助手来查看日志,SWD J-Link使用J-Link RTT Viewer来查看打印日志。由于UART日志打印方式会占用一个UART口,而大部分nRF5芯片都只有一个UART口,从而导致资源冲突,为此推荐大家使用RTT方式来打印日志,从而可以将UART口留给正常应用。J-Link RTT Viewer配置方式如下所示:
RTT viewer日志打印窗口如下所示:
串口助手配置方式如下所示:
- Baud rate: 115.200
- 8 data bits
- 1 stop bit
- No parity
- HW flow control: None
随便选择一款你熟悉的串口助手,比如Putty或者ClearTerminal,ClearTerminal打印窗口如下所示:
Putty打印窗口如下所示:
为了使能日志打印功能,每个版本的SDK配置稍有不同。
1.1 nRF5 SDK v11.0.0及以前版本
你需要到options for target->C/C++->define里面定义一个宏,如果定义“NRF_LOG_USES_UART=1”选择UART日志打印;如果定义”NRF_LOG_USES_RTT=1” 则选择RTT日志打印,如下:
1.2 nRF5 SDK v12.0.0及以后版本
从SDK12开始,使能日志打印功能,就不需要到Keil的C/C++页面,所有关于日志打印的配置都在sdk_config.h文件中,一般来说,你需要配置三个选项:一打开还是关闭log功能,二后端使用UART还是RTT,或者同时选择二者(从SDK14开始,可以同时通过UART和RTT把日志打印出来),三日志的级别以及SDK各模块日志单独控制。如下:
2. 使用调试界面进行调试
Nordic产品支持单步,断点,寄存器查看,内存查看,call stack查看等所有常规调试手段。需要注意的是,由于softdevice在底层要处理大量的中断,一旦蓝牙跑起来后,只能用一个断点进行全速跑,也就是说,执行完一个断点后,程序内部逻辑和时序已经紊乱,此时不能再继续全速跑第二个断点。如果要看第二个断点的内容,只能删掉第一个断点,重新开始执行。
通过以下方式打开nRF5 SoC内部寄存器查看窗口:
用得比较多的几个Keil窗口:
3. nRF5 SDK自带的APP_ERROR_CHECK函数
APP_ERROR_CHECK是nRF5 SDK定义的一个用来检查API返回值是否正确的函数,在nRF5 SDK中,NRF_SUCCESS(0)为正确返回值,其它返回值皆为错误值。nRF5 SDK所有协议栈API调用,以及SDK库函数调用,都会用APP_ERROR_CHECK去检查调用的返回值。当出现非法调用时,比如传入的实参不对,API返回值就不会为NRF_SUCCESS,此时APP_ERROR_CHECK就会派上大用场。通过查看APP_ERROR_CHECK函数定义,你会发现APP_ERROR_CHECK受宏DEBUG控制,当没有定义DEBUG宏时,系统将直接产生软复位;当定义了DEBUG宏时,系统将把错误信息显示在call stack中,比如是哪个文件哪一行出错,返回的错误码是什么,如下所示:
默认情况下,nRF5 SDK是没有定义DEBUG宏的,所以一旦函数返回值不对,系统就会复位。这里要特别指出的是,在你开发调试过程中,经常会碰到复位的情况,这其中大部分都是由APP_ERROR_CHECK引起的。针对这种情况的复位,你只需要在options for target->C/C++->define里面定义一个宏:DEBUG,就可以快速找出是哪一个文件哪一行代码引出的复位,以及复位原因是什么,如下:
最后附上APP_ERROR_CHECK函数体代码:
__WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) { __disable_irq(); NRF_LOG_FINAL_FLUSH(); #ifndef DEBUG NRF_LOG_ERROR("Fatal error"); #else switch (id) { #if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT case NRF_FAULT_ID_SD_ASSERT: NRF_LOG_ERROR("SOFTDEVICE: ASSERTION FAILED"); break; case NRF_FAULT_ID_APP_MEMACC: NRF_LOG_ERROR("SOFTDEVICE: INVALID MEMORY ACCESS"); break; #endif case NRF_FAULT_ID_SDK_ASSERT: { assert_info_t * p_info = (assert_info_t *)info; NRF_LOG_ERROR("ASSERTION FAILED at %s:%u", p_info->p_file_name, p_info->line_num); break; } case NRF_FAULT_ID_SDK_ERROR: { error_info_t * p_info = (error_info_t *)info; NRF_LOG_ERROR("ERROR %u [%s] at %s:%u PC at: 0x%08x", p_info->err_code, nrf_strerror_get(p_info->err_code), p_info->p_file_name, p_info->line_num, pc); NRF_LOG_ERROR("End of error report"); break; } default: NRF_LOG_ERROR("UNKNOWN FAULT at 0x%08X", pc); break; } #endif NRF_BREAKPOINT_COND; // On assert, the system can only recover with a reset. #ifndef DEBUG NRF_LOG_WARNING("System reset"); NVIC_SystemReset(); #else app_error_save_and_stop(id, pc, info); #endif // DEBUG }
以上是关于如何调试nRF5 SDK的主要内容,如果未能解决你的问题,请参考以下文章
nRF52832 改变ATT_MTU提高蓝牙数据发送速率(nRF5_SDK_14.2.0)
解决方法:nRF5_SDK_12.3.0工程编译报错nrf_erratas.h(39):error
谷歌浏览器调试jsp 引入代码片段,如何调试代码片段中的js