Forums

调试嵌入式系统-常用的工具,策略,最佳实践...

开始于 斯蒂芬布 3 years ago 11回复 最新回复3年前 2571意见

我们都可能同意嵌入式(软件)工程师通常在调试上花费大量时间。

该讨论线程的目标是为您提供一个与他人分享您最喜欢的工具,策略,技巧,最佳实践,个人故事等的地方。基本上,与#debugging嵌入式系统相关的任何事情您都认为可能会带来潜在的好处对嵌入式工程师社区的其他人来说,也许您已经学到了很难的方法。该线程将成为新的#FAQ部分的一部分。

一如既往,非常感谢您的宝贵时间!

[-]
回覆者 纳德勒 2017年11月17日
1)尽可能不要在嵌入式目标上进行调试。

最好在主机上开发和调试算法代码,
然后将其与嵌入式测试用例一起移植到嵌入式目标。
通常,对于每个C ++类,我都会添加一个QwikTest()成员来验证
类功能,仅在调试版本中内置,以及
从测试命令甚至在启动时运行。

2)规划您必须执行的操作,以及如何在目标上进行调试。

最好在PCB上预先计划一些事情:

  • PCB测试板甚至插头,对于今天的小尺寸组件尤其重要,它适用于:
    • 电源
    • 任何SPI或I2C总线
    • 您需要访问的任何重要信号
  • 我喜欢将插头条粘贴到板的边缘,以便于与示波器/逻辑分析仪的轻松连接,以及从测试垫到插头的焊线。
  • 用于诊断的LED。万一您需要闪烁SOS或数字状态代码,或者以其他方式使内部状态可见。
  • 测试板与GPIO相连,用于触发示波器或测量持续时间。
  • GPIO与RC绑定到测试板。用它来衡量在关键例程(例如ISR)中花费的时间百分比;用电压表可直接读取。

并计划 提前 for your software:

  • 输出诊断流,例如:
    • 简单的UART,
    • 封装在主机通信协议中的诊断消息会发送到主机上的专用诊断控制台
    • 至少大多数开发IDE都支持某种形式的输出控制台(半主机)。
  • 内置测试数据,例如用于模拟传感器输入的测试命令(并禁用传感器读数)。这使您可以轻松地重现测试用例,并在没有传感器和/或在测试期间无法轻松控制传感器输入的情况下进行测试(例如,在拥有最终硬件之前使用评估板)。
  • 时间测试:
    • 您将如何检查ISR延迟和运行时间?
    • 其他加工性能如何?
  • 堆栈和其他内存使用情况:您将如何检查?我通常会提供一个诊断命令,以检查和报告所有任务的堆栈使用情况以及免费的存储状态(尤其是在某些旨在检查此错误的工具中给出的错误,grrr ...)
3)防御性编码

尽管这并不特定于嵌入式,但它尤为重要,因为调试比在主机上更难。例如,使用大量断言!在发现逻辑错误之前,您可以节省很多时间。

4)从下向上验证

在尝试验证其他功能之前,请检查所有时间!
您可以避免在间歇性工作中发疯的一些示例:

  • 每个外设的SPI和I2C速度是否在允许范围内?
  • 控制脉冲和时序是否也在范围内(在转换触发之后您是否经过足够的等待时间,然后才通过SPI询问ADC的结果)?

等待PCB时,您将为上述所有内容编写测试计划。在测试期间,我想记录每个测试的结果,例如,以下屏幕截图显示了SPI正确时钟在15MHz,并且与其他信号具有适当的相位关系:

adc spi0 detail_46580.png

5)哦,还有不错的工具...

劣质的工具会浪费您很多时间。我最喜欢的一些工具:

  • 适用于ARM SWD调试接口的Segger J-Link。过去,我在功能失调的OCD和可怕的越野车评估板内置调试器上浪费了太多时间(我在为您看Freescale)。节省麻烦和时间!体面的SWD / JTAG适配器将下载得更快,工作更可靠。
  • 体面的示波器/逻辑分析仪非常重要。我用 是德科技的MSOX3054T具有串行解码选项,可轻松查看SPI,RS-232,CAN等。
  • 网格连接CAN-USB分析仪,用于CAN总线监视和激励


希望对您有所帮助!
最好的问候,戴夫

[-]
回覆者 trmittal24 2017年11月25日

你好戴夫,
您能否详细说明第一点?
还有什么是QwikTest()?

谢谢!

[-]
回覆者 纳德勒 2017年11月25日

您能否详细说明第一点?
还有什么是QwikTest()?

当然:在测试驱动的开发中,测试被编码为类的一部分,包括测试数据,并断言结果是否与预期不符。我通常将此代码编码为名为QwikTest()的成员函数以运行测试(仅在调试版本中定义/构建)。首先让类在主机上工作,然后至少通过验证基本功能的冒烟测试将类移至目标。

希望这很清楚!
最好的问候,戴夫

[-]
回覆者 trmittal24 2017年11月26日

这确实清除了一些疑问。

谢谢戴夫

[-]
回覆者 基因型 2017年11月16日

正是在这里,优秀的嵌入式编程技能应运而生,比如开发新板或调试现有板。在调试嵌入式系统过程中,我的第一个也是最好的工具是阅读和理解主板上零件的数据表。在使用在线编程器/调试器设备确认控制器正常工作之后,我开始编写底层函数,以确保对设备的理解是正确的。我希望首先使中断起作用,并验证关键进程是否正常运行(ADC /定时器/ UART等)。正确收集数据后,我将致力于使用数据并驱动输出的功能或算法过程。

就工具而言,这是我的最爱:

  • 电压表-我想先验证设计的功率部分。这些必须是正确的,否则其他所有事情都将受到影响。
  • 示波器-这是我要去的设备。在这里,您可以真正了解一切是否正常。对于大多数嵌入式设备,所有有趣的事情都在零件内部发生,如果几乎没有外部设备,您将需要一些帮助来查看此处发生的一切,因此我使用未使用的引脚来触发内部事件,所以我有一些东西在尝试监视设备功能时查看。

作为此技术的一个示例,下面是一个在中断处理期间加载度量处理器的示例:

f0013tek_16005.png

下部(青色)迹线连接到我为此测量重新分配的LED驱动器。在进入定时器中断时,该信号被驱动为低电平,而在退出时,该信号返回为高电平。 “低”时间表示中断的处理时间,而“高”时间表示后台任务可用的时间。上(黄色)迹线是中断处理生成的信号。该信号是一条通道选择线,可寻址四个MUX通道之一。每隔四个中断此信号切换到下一个通道。使用这种技术,我能够优化每个阶段并平衡中断过程不同阶段之间的负载。

  • 在线编程器/调试器-能够更改和加载代码是调试过程的基础。拥有修改代码,读取/修改EEPROM和检查寄存器的好工具非常重要。好的调试器对于设置断点也很有帮助,允许您跟踪代码的功能也很有帮助。
  • 逻辑分析仪-使用逻辑分析仪可以轻松追踪多个数字波形。对于查看往返于微处理器与外部设备的通信非常有用。复杂的触发功能使您可以放大并找到大量数据时所需的信息。
  • 信号发生器和额外的电源-对于具有外部传感器和设备的嵌入式系统,能够以受控方式模拟信号是验证功能和测试传感器范围极限的好方法。
  • 焊接工具和显微镜-如果事情不顺利并且发现问题,能够修复它们很重要。我发现能够维修/更换/修改电路板非常有帮助。  

就最佳实践而言,我喜欢始终尝试重用尽可能多的代码。在设计新的电路板/产品时,我希望尝试使用与以前的设计相同的微处理器。通过能够利用现有项目作为新项目的起点,我发现自己可以上路了。在做了一些(或在某些情况下是很多)重做代码以匹配当前项目所需的功能之后,我可以真正专注于更改和新代码,并假定未改动的代码主要可以正常工作。

我希望这个对你有用。

[-]
回覆者 慕尼黑2017年11月18日
最喜欢的工具 :

-以太网(TCP / IP)分析仪-Wireshark
-USB分析仪-Ellisys和TotalPhase
-CAN TotalPhase科莫多
-用于编辑,开发,调试的VisualStudio
-Saleae示波器/逻辑分析仪
-J-Link和P&E Micro BDM / J-Tag / SWD调试器,用于硬件调试
-用于调试的IAR(它有时会崩溃,但仍比笨拙的调试器在基于Eclipse的工具中使用时更好,更快,更有效,更强大)
-Com0Com虚拟com端口环回
-用于代码存储库的Git服务器
-大量的开发/评估板!

战略 自2004年以来一直使用和改进的方法是在模拟环境中对98%的代码进行开发,测试,调试和分析。在硬件上进行测试以提供最终证明和低水平的调试/优化。当使用新的外围设备时,我“总是”首先创建它们的模拟,因为这可以确保深入理解,允许基于这种理解对操作进行测试(在整个项目中),然后根据在硬件上观察到的偏差或不太明显的效果进行细化。

以下是一些视频,它们显示了VisualStudio中模拟的使用以及一些使用案例(分析/调试):

硬件调试仅限于非常低级的代码,因此我总是使用完全优化的代码(将在交付时进行调试)进行调试,并充分利用了反汇编/内存/寄存器视图,因为这是操作所在。由于VisualStudio调试功能强大得多,并且在触摸硬件之前通常已经完成(包括代码覆盖率测试),因此在硬件上进行高级代码调试就没有那么有趣了。

使用这种策略,我开发了许多产品,而无需硬件或仅在需要时对客户硬件进行有限的远程调试。

由于我是一名顾问和培训师,在这里我经常帮助解决问题(例如与内存相关的错误,DMA错误),因此非常低级的调试经验非常有用。对于调试器和调试策略的使用,我经常会感到惊讶,因为我缺乏许多帮助的工程师的知识。我的印象是,这是一个经常缺乏培训和持续发展的领域,并且会导致效率低下,尤其是在需要解决更复杂的案件时。

[-]
回覆者 尔米察姆 2017年11月15日

我是大多数微控制器制造商或第三方供应商设计的评估套件的忠实拥护者。它们通常不到100美元,非常适合在您获得原型PCB之前启动代码。评估板内置了许多代码示例,测试点和板上外围设备,可让您对设计充满信心,并且至少可以在进入目标系统时启动代码。

当我第一次提出嵌入式原型时,我总是尝试首先使RS-232开始运行。这是我最喜欢的调试方法,无论是板载外围设备还是复杂算法,都无法替代在设计为运行的实际平台上运行代码。过去,我让代码在模拟器上运行,然后发现当我将其移植到平台上时,它没有以相同的方式运行。一些具有串行输出功能的创意钩子使我的培根从火上拔下来的次数超出了我的估计。

除了值得信赖的DVM之外,示波器是我唯一需要验证时序或波形的工具。这听起来很基础,但是我发现简单+创造力=成功。通过保持简单,您必须了解设计中所有内容的细节。最好的固件设计人员还对设计中每个组件的硬件(直到寄存器级别)都有深刻的了解。甚至在创建原理图之前,花数小时浏览数据表永远不会浪费时间。那些被忽略的小细节可能会扼杀设计或导致大量丑陋的后接线来修复监督。尽管Windows程序员可以负担得起编写更抽象的代码并位于驱动程序级别之上的层,但是嵌入式系统只不过是底层驱动程序和最高效率,因为嵌入式系统是实时系统,而在我的情况下,我从事的工作是实时系统。

[-]
回覆者 前卢维安 2017年11月15日

我曾与逻辑分析仪,监视器,模拟器,评估套件以及反复试验一起工作过,但我相信彻底进行调试的唯一方法是模拟器及其后代,调试器。没有更好的方法来了解微机内部正在发生的事情或停止,监视和调整操作。

但是,当您无法完全解决问题时,还有其他一些技术可以帮助您。尽可能多地带出备用I / O引脚,甚至可能有几个DIL开关或跳线。这些引脚可以作为输出来测量执行时间,是否执行部分代码,何时发生某些事件以及以什么顺序进行测量。作为输入,它们可以帮助创建可能难以实现的条件,例如,如果您每隔7天发生一次事件,则可以使用开关来加快验证代码的时间。

附加输出的特殊情况是闪烁的LED。

在编写代码模块时,我还一次调试了一个模块,一旦测试了该模块,就逐步进行测试,然后测试整个系统。

[-]
回覆者 iv 2017年11月15日
当然,嵌入式调试取决于项目,使用的MCU和个人喜好。
就个人而言,去年,我主要在Gcc / Eclipse环境下使用Cortex-M / A ARM内核,但在某些情况下,我需要为小型8/16位MCU(8051; MSP430; AVR; STM8)调试/开发一些应用程序。 。  

对于Cortex-M / A ARM,我正在使用GCC + Eclipse + OpenOcd + GDB。 

对于小型MCU-始终是IDE的专有版本-Iar或Keil。 

一两年前,我为自己发现了一个Segger IDE(正在使用试用版的nRF52xx进行游戏),我想说的是,从专有IDE来看,这是我见过的最好的IDE之一。市场(只能与Keil / Iar / AtmelStudio / CoIDE进行比较)。

在考虑调试时,对我而言,最重要的是准确地了解在任何给定时间发生的事情,而最糟糕的噩梦是多线程应用程序,您不知道谁在使内存崩溃。您可以将其视为应用程序突然崩溃或一个线程没有响应或出现HardFault或类似问题。  

返回主题。

我认为,通用调试技术将永远存在,它是:

-代码中的断点;

-GPIO(使用示波器)-这是最快且最接近HW方法,可用于性能分析;

-错误处理程序以捕获关键/非关键错误;


然后,更复杂的调试技术-取决于MCU内核:

-无缓冲或更好的缓冲I / O(例如,通过uart);

-在基于Cortex-M的内核上进行半主机,但请记住,半主机非常非常慢;

-用于调试特定场景的特殊工具(例如RTOS);


以下是我的个人喜好,如果有人问最好的话:

-如果可能的话,请使用专有的IDE,因为它们具有与MCU最佳的集成/调试功能。他们具有最佳的硬件调试工具集成。我讨厌Keil,这是您的个人喜好-只是因为他们在GUI中使用了粗框...

-OpenOcd + GDB:我在Eclipse上使用了多年,但是与专有IDE相比,作为嵌入式开发人员,我不太喜欢它(实际上这是因为您需要了解更多以正确的方式使用它) 。至少我希望,我永远不需要使用命令行GDB调试。

-对于嵌入式Linux开发,除了使用GDB之外,我不知道其他选项...为什么不呢?

-目前我的主要嵌入式RTOS是FreeRtos,我发现Tracealyzer + JLink(带有SWO)的组合对我来说是最简单的方法,并且在需要分析项目时可以节省大量时间。对于其他RTOS开发而言,要看到线程之间的交互并不是那么容易。在这里,您需要一些可用内存才能使用此工具。


[-]
回覆者 ashish_gajalkar2017年11月16日
嵌入式系统中的调试是最重要的之一 嵌入式工程师应该具备的技能,因为大多数时候您都会 调试由其他人编写的代码。您可以通过多种方式 可以通过UART打印或内存转储来调试代码。对于哪些程序 在引导加载程序和设备驱动程序方面,最好的调试工具是 JTAG和DSO或示波器。在我公司,我们曾经调试过引导加载程序 借助Lauterbach之类的JTAG调试器编写代码。在JTAG的帮助下 调试器,您可以查看所有寄存器值,也可以逐步调试以查看 每条指令都一一执行。 IDE也是一个非常好的工具 调试程序。在某些情况下,您还可以使用 开发板来调试您的软件并检查您的指令 软件崩溃。我们公司最常用的调试技术是 基于JTAG和UART的调试。
[-]
回覆者 斯蒂芬布 2017年11月20日
我相信Jack Ganssle的这段视频可能对该线程的某些读者有价值: