嵌入式系统调试初学者指南:快速查找错误的 3 个步骤

时间:2023-11-14
 调试嵌入式代码可能是一件非常令人头痛的事情,尤其是当您没有接受过设计方法方面的培训时。过去,硬件设计师负责嵌入式系统的编程,但他们往往缺乏基本设计技术、数据结构和结构化编程的知识。 
 这种趋势至今仍在继续,许多电子工程师在处理嵌入式系统的硬件和软件开发时没有接受过计算机科学家所信奉的设计方法的任何正式培训。
 缺乏设计知识可能会导致一大堆问题,例如组织得像一堆意大利面条一样难以维护的代码。 
键盘上的意大利面条戏剧化,因为有一个术语“意大利面条代码”,该术语用于描述非常混乱的代码,以至于几乎不可能在不破坏代码中的某些内容的情况下更改或添加一件事。图片由 Canva Pro 提供 
 更糟糕的是,一些嵌入式程序员经常将设计方法视为不必要的文档程序或初学者的拐杖,这只会火上浇油。
 然而,事情是这样的;嵌入式代码中的错误不会凭空出现,而是由程序员创建的。因此,作为一名嵌入式程序员,学习帮助您编写干净、有组织且经过深思熟虑的代码的设计方法至关重要。 
 将良好的设计实践融入到您的开发过程中可以提高嵌入式系统的可靠性和可维护性,因此值得花时间去做正确的事情。 
 “如果你没有时间把事情做好,你有时间重新做一遍吗?”——让-多米尼克·沃尼尔  
 2. 满足产品上市时间要求的压力
 在《嵌入式系统编程的艺术》一书中,作者说,从长远来看,研发预算超出 100% 通常只会影响公司利润 3-5%,而产品交付仅延迟六个月交付可能会导致市场份额下降 30%。难怪在构建嵌入式设备时,人们会急于立即开始编写代码。 
 但请记住,速度可以致命——无论是字面上还是比喻上。无论压力有多大,在没有彻底理解要构建的内容的情况下就匆忙编写代码是您可能犯的编程错误之一。在仍然提供可靠产品的同时限度地缩短上市时间的更好方法是通过增量版本来实现。从专注于重要功能的嵌入式系统项目的子集开始,对其进行设计,以便添加其余功能不需要完全重写。许多嵌入式系统都有很多功能,但并非所有功能都是必需的。将一些非必要的内容推迟到 1.1 版本,而专注于发布一个强大但有限的 1.0 版本。
 3. 做工粗劣很容易被忽视
 作为嵌入式系统程序员,我们不会像艺术家或雕塑家那样根据我们的作品是否漂亮来评判。相反,一切都取决于它的工作表现如何。问题在于,粗制滥造的工艺也可以像精心设计和实现的嵌入式代码一样发挥作用。 
 当只有一两个人编写整个项目时,我们就需要以的诚实编写可维护的、结构良好的代码。不幸的是,没有人会因此而拍拍我们的背,我们也不会因为编写“有效”的意大利面条代码而遇到麻烦。
 然而,就像一座质量差的房子终会破裂一样,糟糕的代码迟早会暴露出它的缺陷。以下是编写嵌入式代码时质量低劣的一些迹象:
 修复 bug 需要很长时间
 添加新功能完全是一场噩梦
 改变一个惯例通常会导致一打不相关的错误突然出现 
 4. 调试嵌入式系统可能很乏味
 调试绝非易事。查找和修复错误需要时间,尤其是在使用 C 等语言时。如果您需要修复某些内容,您可能必须离开调试会话,编辑代码,编译它,然后全部再次。
 调试工具(图 2)也可能成本高昂且复杂,例如用于 32 位和 64 位处理器的高速示波器和快速仿真器。 
 
 图 2.检查嵌入式系统执行情况的外部调试器软件。图片由Bart Vermeulen 和 NXP提供 [点击图片放大]
 
 此外,尽管模拟器对于调试算法很有用,但它们并不适合处理难以模拟的中断和直接内存访问 (DMA) 等实时问题。更不用说,调试嵌入式系统发生在项目结束时,当时每个人都已经压力重重。按时完成的压力很大,挫折感也很大。时机本身并不友好,这使得它更具挑战性。
 
 设计文档测试(DDT)方法简介
 即使是在整个开发过程中按计划进行的计划周密的嵌入式系统项目也常常会在阶段遇到障碍。将会出现比预期更糟糕的问题。工具可能会出现故障,原型硬件可能会变得不稳定,并且会出现其他不可预见的问题。接受这些挑战并在您的计划中做好准备非常重要。
 一种方法是使用 DDT(设计、文档、测试)方法。需要明确的是,我没有发明这种方法。感谢 Gary McGath 在一篇名为“编程词源”的文章中介绍了它。DDT 方法可以帮助您避免编写难以调试的代码。尽管无法完全避免调试,但这种方法可以减少调试的时间和挫败感。 
 步:在编写代码之前设计嵌入式系统
 保持无错误的方法是编写没有错误的程序。为嵌入式系统编写无错误程序的关键是在开始编写代码之前彻底设计它们。 
 首先,增强你的倾听能力。仔细聆听客户和规范委员会的意见。系统应该做什么?谁会使用它?由此得出您希望程序执行的操作以及需要哪些数据结构。从这里开始,将计划分解为几个大步骤,并以更具体的方式决定每个步骤的组成部分。您可以使用 Warnier-Orr 图来表示程序的结构,这将帮助您专注于整体计划。 
 嵌入式系统编程的创造性部分在于设计过程,您可以在设计过程中发明算法并构建程序。一旦有了经过深思熟虑的设计,编写实际的代码就很容易了。事实上,与用 C 编写实际代码相比,您可能会更喜欢设计过程。
  第二步:文档——注释、命名和编写代码 
 老实说,许多嵌入式程序员不喜欢对他们的代码进行评论,因为他们认为这是一种浪费时间的干扰。这样想是错误的。注释是针对难以调试的代码的第二道防线。它们有助于确保您理解自己的代码,并且使未来的维护变得轻而易举。因此,文档不应该是事后才想到的。它应该从程序设计开始——当你编写代码要做什么时——并且应该继续添加解释程序操作的注释。但是,不要只是为了添加评论而添加评论。好的文档是关于解释代码的操作的。
 确保每个函数都以一个清晰描述其功能并列出其输入和输出参数的块开头。对函数和变量使用描述性名称。函数名称 get_timer_count 比 getdata 更好。另外,遵循系统的命名约定。
 并谨防不正确的评论。他们比没有评论更糟糕。因此,请确保您的评论准确并在程序的整个生命周期中保持其准确性。所有这些实践将使调试和更新代码变得更加容易。 
 随着嵌入式系统变得越来越复杂,编写文档不正确的代码将无法通过。但是,对于嵌入式程序员来说,写作也许正变得像编码一样重要。如果您不喜欢发表评论,请尝试提高您的写作技巧。参加写作课程、练习写作,并为 AAC 等技术写作社区做出贡献。 
 第三步:测试嵌入式系统的错误
 为了确保您的测试有效,您应该确保您的测试用例是全面的。这意味着不仅要测试“幸福路径”,还要测试边界情况、边缘情况和错误场景。 
 仔细编写程序后,开始使用简单的程序版本进行测试。如果程序次运行正常,请使用不同的数据重试以验证其稳健性。如果程序次无法运行,请使用尽可能简单的情况使用不同的数据重试。如果您在几分钟内找不到错误,请使用快照转储或其他工具来收集有关正在发生的情况的更多信息。 
 例如,如果没有合适的工具来测试实时场景,请避免使用大量中断。 
 
上一篇:了解如何使用查找表在数字图像处理中进行点运算
下一篇:利用 SPICE 中的磁滞减少磁带录音的失真

免责声明: 凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处。非本网作品均来自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

相关技术资料