• 已解决 73482 个问题
  • 已帮助 5993 位优秀工程师

【机甲大师Q&A】嵌入式、MCU调试技巧大分享!

电子芯吧客 2020-05-11 浏览量:4462

【参与话题讨论,立得200IC币】调试MCU的日常,是不是无尽的debug?日常的开发学习中,你又遇到过什么样的问题或经验呢?

RoboMaster比赛中,常用的是基于Cortex-M3M4内核的MCU。高主频的MCU上有各种通信协议的接口如CAN_BUS UART等,有供弹拨轮电机的驱动电路 DR16接收机专用的取反电路,有用于控制摩擦轮电机的两路pwm输出 etc.作为机器人重要的控制单元之一,MCU的调试对于机器人在运动、射击、云台、控制等电控系统有着很大的意义。自然也是参赛者日常头疼的问题。

今天,看RoboMaster的大疆工程师和大家一起分享Cortex-M3M4内核MCU的调试技巧。

 

Q1:大家在调试MCU时一般是否会遇到各种各样的问题,比如单片机运行着死机了,一般是什么原因呢?

A1MCU死机基本上都是程序运行中触发了异常中断导致的,比如使用了空指针、野指针、访问越界之类的内存访问错误,或者是使用了未初始化的外设,再或者是非对齐访问等等。具体大家可以参阅《CM3CM4权威指南》中的12.2 错误的原因章节。

 

Q2:找到问题的发生位置,但是并不清楚问题的原因,还可以怎么做呢?

A2:我们可以通过查看系统控制块SCB中相关错误寄存器来判断,在Keil的调试模式中打开View -> System Viewer -> Core Peripherals -> Fault Reports查看。比如对指向超出RAM区域的指针进行操作,发现进入HardFault_Handler,这时发现总线错误状态寄存器BRSR中的BFARVALID位被置位,表示访问了一个无效的总线地址。在CM4SCB中还有像CFSRHFSRBFARMMFAR这样的错误寄存器。作为扩展,大家可以阅读内核用户手册《Cortex-M4 Devices Generic User Guide》或《Cortex-M3Devices Generic User Guide》中4.3 System control block章节。

 

Q3MCU在给别人测试时出现很难复现问题,怎么在不复位的情况下接入调试工具进行调试?

A3:这种情况时很常见的,在实际测试时出现了问题,这时候却往往不在调试模式下,而接入调试器进行调试会进行复位,原来的问题现场就被破坏了。这时我们就需要使用Attch的调试方法进行调试,这种方法不会对MCU进行复位。

 

Q4:不想使用Keil全家桶,代码是使用C Make构建系统,该怎么进行调试呢?

A4:除了Keil以外也可以使用其他调试工具,比如OpenOCD+GDB,但是这个配置比较复杂,对新手可能并不友好。我在这里给使用J-link调试器的同学推荐一款调试软件Ozone,这款软件是J-link出品公司的官方免费软件。可以调试gccarmcc编译出来的固件。armccgcc分别编译出axfelf文件,包含了调试信息。在Ozone中载入这些文件就可以进行源码级调试,而且功能不弱于Keil。其中图标数据的显示比J-Scope更易于操作和直观,更适合于调试和整定参数。

 

Q5:在变量的内存地址处定义访问写断点,具体操作步骤是啥呢,有例子吗?

A5:在Keil的调试界面下按住Ctrl + B打开断点窗口,在expression中输入想要设置的全局变量或者地址,在Access中选中Write,点击Define就定义好了哦。局部变量因为是在栈上,地址不固定,所以是不可以的。关于Keil断点的更多信息,我建议大家阅读uVision User Guide手册中的Debugging -> Debug WIndwos and Dialogs -> Breakpoints Windows章节。手册在选项栏中的Help可以找到。

 

Q6:关于局部变量无法仿真,有什么解决方法吗?如果想通过watch窗口观看的局部变量的值的话?

A6:因为局部变量是存放在栈上的,所以局部变量的存放的地址位置每次重新进入函数是都不固定。推荐一个小技巧,定义一个全局变量,在退出函数时将局部变量复制到全局变量上,就可以间接观察了。

 

Q7:像can spi iic总线等通信出现问题时如何排查问题比较快?

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

 

Q8:问一下cubehal会不会存在问题 开始学时学的标准库?网上有人说cube生成的代码问题很多而且代码构架已经固定了一直在用标准库。:

A8:我建议使用HAL或者LL库,ST公司已经对标准库停止维护了,新出的芯片也不再有标准库的支持。对比几年前,现在HALLL已经很完善了,而且HAL库这种硬件抽象层的思想是符合现在嵌入式设备的发展趋势的,使用HAL+CubeMX比标准库开发更快更容易上手,追求性能可以使用LL库。

 

Q9:有没有什么办法可以通过直接改变仿真窗口watch里面的数值,然后就直接答:把程序里面的对应变量的数值也发生相应改变呢?我用的ST-link仿真的,每次发现系数不得,都得程重新退出仿真 然后下载程序 然后继续仿真 感觉这样很麻烦

A9:程序是写在Flash里面的,虽然使用调试器通过memory窗口可以直接修改Flash中的指令,但是这样操作需要对汇编有很深的理解才行。建议你将系数定义在全局变量中,利用watch一次调好参,就不用反复下程序了。或者你可以使用IAP或者E2PROM实现参数修改后断电保存。

 

Q10: 可能是很多人都想知道的秘诀!怎么样才能提升自己的调试能力?

A10: 首先是熟能生巧,解决的BUG越多,经验也就越来越丰富,不仅能提升自己解决疑难杂症的能力,也能避免在编码的过程中写出BUG。第二个是多阅读资料,除了网上的教程和博客以外,也要多阅读官方的芯片和数据手册,这些资料是准确和详实的。

 

日常的开发学习中你遇到过什么样的问题或经验呢?对于RoboMaster机甲大师赛使用的机器人软硬件,又有哪方面想要了解呢?

欢迎和大家一起分享讨论!



声明:部分内容来源于RM论坛,如侵犯到您的权益,请及时通知我们,我们将在第一时间内删除。

0 0 收起

我来回答

上传资料:
选择文件 文件大小不超过15M(格式支持:doc、ppt、xls、pdf、zip、rar、txt)
所有亮答 数量:34

  • 其实任何一个编程调试都有一些经验积累的过程,

    说穿了就是见多识广,大多数问题遇见过了,知道怎么处理啦!

    当然这知道怎么处理大多数时候就是在前人基础上经由研究(搜索)、探讨、实践这样学习得来。

a64a4210e7840ffa 回复了 xdsnet:很有同感。。 回复

  • 现在MCU控制机器人已经过时了,高端的都上Linux了吧,加上激光雷达,目标识别等技术

  • 最开始做底盘驱动时,使用开漏的IO口直接连接普通直流电机驱动器,会在快速转向时发生程序跑飞,建议使用劣质的驱动器时加上IO驱动芯片,或者高速光耦

  • 其实我想了解一下有关mcu用户手册的使用方法?因为是新手,调试的路子经验不多???

相关问题

问题达人换一批

【机甲大师Q&A】嵌入式、MCU调试技巧大分享!