【RM2020 圆桌】第七期 嵌入式调试技巧分享

稿定设计导出-20200409-171323.png




【圆桌时间】:2020年4月10日(周五) 20:00-21:00
【圆桌主题】:嵌入式调试技巧分享
【圆桌嘉宾】:@Elecheart RM技术攻城狮
【主持人】:@RoboMaster赛务
【圆桌流程】:20:00-20:20 主题内容对话(主持人与嘉宾)
20:20-21:00 实时问答环节 (嘉宾与论坛网友)温馨提示:
在直播期间,大家可以直接移步至论坛活动版块 https://bbs.robomaster.com/forum-club-1.html直播墙会自动实时更新内容。


主题内容对话
主持人:
欢迎大家来到第七期圆桌,本期主题是嵌入式调试技巧分享今天的圆桌流程会是分两个部分:1.主持人与嘉宾对话,共同分享攻城狮小哥的bug调试小技巧;2.自由提问环节~
让我们掌声欢迎本期嘉宾DJI嵌入式工程师@Elecheart!让他给大家打个招呼吧
嘉宾:
Hi~ 大家好

主持人:
那么就进入今天的第一个环节,对话环节~此环节大家如果有问题可以先提问,我们会在之后问答环节统一回答
那么首先,请攻城狮小哥给大家介绍一下本期圆桌背景内容吧
嘉宾:
大家使用的MCU基本是基于Cortex-M3和M4的内核,本期主要给大家分享Cortex-M3和M4内核MCU的调试技巧。

主持人:
好的,那么第一个问题来了。@Elecheart 大家在调试MCU时一般是否会遇到各种各样的问题,比如单片机运行着死机了,一般是什么原因呢?
嘉宾:
MCU死机基本上都是程序运行中触发了异常中断导致的,比如使用了空指针、野指针、访问越界之类的内存访问错误,或者是使用了未初始化的外设,再或者是非对齐访问等等。具体大家可以参阅《CM3与CM4权威指南》中的12.2 错误的原因章节。

主持人:
@Elecheart 那遇到这些问题要怎么解决呢?可以跟大家说一说吗
嘉宾:
这个可以从定位问题发生的位置来入手,当异常发生时,MCU内核会将R0~R3、R12、LR、PC、XPRS寄存器按顺序压入栈,其中LR寄存器为异常发生时将要执行的下一条地址。在Keil的调试界面中,我们可以通过以下两个方法找到它。
方法一:
打开Call Stack Window,选中最顶上的异常处理函数,右键Show Caller Code跳转到异常发生时的代码处。有的时候这种方法可能无法使用,大家可以使用另外一个方法。
方法二:
1.打开View -> Registers Window,找到SP,它的值为当前的栈顶地址。

2.打开Memory Window,在Address中输入栈顶地址显示栈的内容,按照压栈顺序其中21~24字节即为压入的LR,记下对应的值(注意大小端 “E1 E2 00 08” 在小端机器上表示为0x0800E2E1)。

3.在Dissassembly汇编窗口中单击右键,在弹出的菜单中选择ShowDissassembly at Address,将压入LR的值输入并点击Go To,就可以跳转到异常发生时的代码处。

主持人:
回归正题,@Elecheart 那还有同学遇到这样的问题是:找到问题的发生位置,但是并不清楚问题的原因,还可以怎么做呢?
嘉宾:
我们可以通过查看系统控制块SCB中相关错误寄存器来判断,在Keil的调试模式中打开View -> System Viewer -> Core Peripherals -> Fault Reports查看。比如对指向超出RAM区域的指针进行操作,发现进入HardFault_Handler,这时发现总线错误状态寄存器BRSR中的BFARVALID位被置位,表示访问了一个无效的总线地址。在CM4的SCB中还有像CFSR、HFSR、BFAR、MMFAR这样的错误寄存器。作为扩展,大家可以阅读内核用户手册《Cortex-M4 Devices Generic User Guide》或《Cortex-M3Devices Generic User Guide》中4.3 System control block章节。

主持人:
@Elecheart 那MCU在给别人测试时出现很难复现问题,怎么在不复位的情况下接入调试工具进行调试?
嘉宾:
这种情况时很常见的,在实际测试时出现了问题,这时候却往往不在调试模式下,而接入调试器进行调试会进行复位,原来的问题现场就被破坏了。这时我们就需要使用Attch的调试方法进行调试,这种方法不会对MCU进行复位。在Keil中的操作方法给大家推荐一篇Keil的官方文档进行阅读:http://www.keil.com/support/docs/3697.htm

主持人:
@Elecheart 那还有经常在调试过程中,发现变量的值会被莫名奇妙的改变,该怎么寻找问题呢?
嘉宾:
这种情况一般是访问越界导致的,我们可以用访问断点来定位是在哪里被修改的。在变量的内存地址处定义访问写断点,这样在程序写入这个变量时就会停下程序供我们分析。

主持人:
@Elecheart 还收到一些同学反馈说,不想使用Keil全家桶,代码是使用C Make构建系统,该怎么进行调试呢?
嘉宾:
除了Keil以外也可以使用其他调试工具,比如OpenOCD+GDB,但是这个配置比较复杂,对新手可能并不友好。我在这里给使用J-Link调试器的同学推荐一款调试软件Ozone,这款软件是J-Link出品公司的官方免费软件。可以调试gcc和armcc编译出来的固件。armcc和gcc分别编译出axf和elf文件,包含了调试信息。在Ozone中载入这些文件就可以进行源码级调试,而且功能不弱于Keil。其中图标数据的显示比J-Scope更易于操作和直观,更适合于调试和整定参数。

主持人:
@Elecheart 那还有最后一个问题,可能也是很多人都想知道的秘诀!怎么样才能提升自己的调试能力?
嘉宾:
首先是熟能生巧,解决的BUG越多,经验也就越来越丰富,不仅能提升自己解决疑难杂症的能力,也能避免在编码的过程中写出BUG。第二个是多阅读资料,除了网上的教程和博客以外,也要多阅读官方的芯片和数据手册,这些资料是最准确和详实的。


实时问答:
1.(Ozone调试)Keil编译出的axf也可以吗?
答:可以的,其他编译器生成的固件只要携带有符合DWARF标准的调试信息,就可以使用Ozone进行调试

2.在变量的内存地址处定义访问写断点,具体操作步骤是啥呢,有例子吗?
答:在Keil的调试界面下按住Ctrl + B打开断点窗口,在Expression中输入想要设置的全局变量或者地址,在Access中选中Write,点击Define就定义好了哦。局部变量因为是在栈上,地址不固定,所以是不可以的。关于Keil断点的更多信息,我建议大家阅读uVision User Guide手册中的Debugging -> Debug WIndwos and Dialogs -> Breakpoints Windows章节。手册在选项栏中的Help可以找到。

3.请问一下,关于局部变量无法仿真,有什么解决方法吗?如果想通过watch窗口观看的局部变量的值的话?
答:因为局部变量是存放在栈上的,所以局部变量的存放的地址位置每次重新进入函数是都不固定。推荐一个小技巧,定义一个全局变量,在退出函数时将局部变量复制到全局变量上,就可以间接观察了。

4.局部变量,如果想看到连续变化的情况呢?
答:和之前那位同学问的一样,将局部变量在函数内复制到全局变量中。

5.像can spi iic总线等通信出现问题时如何排查问题比较快
答:我喜欢的方法是自低向上从寄存器开始,有时候用的硬件中间层很复杂,对着自顶向下去排查反而效率低。直接拿着MCU的用户手册对着寄存器排查,确保配置相关的寄存器是正确的,在步进时多关注一些关键状态位的变化情况,比如中断标志位,错误标志位。保证寄存器这边能work了,上面的问题就好排查了。

6.有没有什么办法可以通过直接改变仿真窗口watch里面的数值,然后就直接答:把程序里面的对应变量的数值也发生相应改变呢?我用的ST-link仿真的,每次发现系数不得,都得程重新退出仿真 然后下载程序 然后继续仿真 感觉这样很麻烦
答:程序是写在Flash里面的,虽然使用调试器通过memory窗口可以直接修改Flash中的指令,但是这样操作需要对汇编有很深的理解才行。建议你将系数定义在全局变量中,利用watch一次调好参,就不用反复下程序了。或者你可以使用IAP或者E2PROM实现参数修改后断电保存。

7.问一下cube和hal会不会存在问题 开始学时学的标准库?网上有人说cube生成的代码问题很多而且代码构架已经固定了一直在用标准库。
答:我建议使用HAL或者LL库,ST公司已经对标准库停止维护了,新出的芯片也不再有标准库的支持。对比几年前,现在HAL和LL已经很完善了,而且HAL库这种硬件抽象层的思想是符合现在嵌入式设备的发展趋势的,使用HAL库+CubeMX比标准库开发更快更容易上手,追求性能可以使用LL库。

8.小萌新能弱弱的问一下 帮助手册是在哪下载的吗?
答:如果你使用Keil且安装了对应芯片的DFP包,在Keil内直接可以找到手册,在软件界面上方选项栏中选择Help->OpenBooks Windows,打开的页面中包含Keil的使用手册,芯片数据手册和用户手册等等,非常详细。除此以外手册可以直接上对应公司的网站下载,比如STM32的手册可以在ST公司的官方网站上下载,关于CM内核的手册可以在ARM公司官方网站上下载。

9.对于调参软件,像J-scope这种,有什么办法可以在软件界面直接调参吗?
答:J-Scope这个软件功能太少,建议使用Ozone,这两个都是Segger公司出品的免费软件。Ozone使用Timeline + DataSampling可以像J-Scope一样查看曲线。而且附带类似于Keil的全套调试功能,可以代码断点,变量Watch

请问这篇文章对你有用吗?
【RM2020 圆桌】第七期 嵌入式调试技巧分享
所有评论
暂无更多
暂无更多
关于作者
RoboMaster 高校赛务
RoboMaster 高校赛务
8 关注Ta
0 文章
4 经验值
0 获赞