嵌入式设计中每一分钱都很重要

描述

  量化节约的最简单方法之一是BML:低成本零件要求公司花费更少的钱来制造产品。在大多数嵌入式设计中,两个最昂贵的部件通常是屏幕(如果设备有,大多数物联网设备没有)和处理器。随着您向处理器添加更多内存(闪存和 RAM),处理器的成本也会增加。虽然成本增加多少的具体细节因半导体公司而异,但粗略的经验法则是,每增加一倍内存,处理器单位成本就会增加约一美元。

  使这个问题变得更糟的是,嵌入式工程师通常不太擅长在应用程序的设计阶段预测内存需求。这些对所需内存量的最佳“猜测”是处理器选择的关键因素。鉴于许多生产运行每年达到数十万或数百万台,在BML中增加不必要的美元会对公司的底线产生有害影响。

  结果,无数项目“资源紧张”,这是“我们没有正确预测内存需求”的代码。加剧这个问题的是,BML通常在项目开始时就被推荐给高层管理人员。一旦发生这种情况,成本就变得不可侵犯。这使人们争先恐后地减少内存占用,或者依靠采购来保持BML成本与管理层预期的相同,通过协商其他组件的更好价格。为了减少内存占用,团队经常求助于编译器的优化引擎来减小生成的代码的大小。

  提高编译器优化的标准

  一些工程师非常不愿意加快优化,因为他们认为优化会给系统带来错误。这种情况很少发生,根据我的经验,大约 5% 的优化器问题最终是优化器的问题。

  当优化级别提高时,编译器对 C 和 C++ 语言的语义非常挑剔。优化决策是基于对语言规则的严格解释做出的。通常,工程师并没有以他们看起来很自然的方式完全了解语言和代码的所有细微差别。

  例如,如果函数调用是这样编写的:

  myFunc(varA, varB, varC, varD);

  自然的假设是从左到右读取变量:varA 将从内存中读取,然后是 varB 等。

  但是,C 或 C++ 中没有任何内容表明必须如此。如果内存是有目的地布置的,或者是偶然的,其中varB位于varD旁边,那么高级优化可能会使用索引寄存器来读取连续的内存空间,以节省代码大小和速度。

  在大多数情况下,这不会对代码产生影响。但是,如果您依赖于从左到右编写时要访问的变量,则可能会出现代码在较低优化下运行良好但在高级别无法正常运行的情况。这就是工具供应商提供的良好支持结构可以帮助发现这些类型的问题并重写代码部分以更好地优化和正常工作的地方,而与优化设置无关。

  此外,如果您的代码可以在高优化下工作,那么它编写正确并且经过更好的测试。如果代码在更高的优化下不起作用,则很有可能潜在缺陷正在等待“咬你”。

  当设置为高尺寸优化时,好的工具可以节省 10-40% 的代码大小。但是,并非所有优化转换都是任何代码段的好选择 - 某些转换实际上可能会增加某些类型代码的代码大小。这本身就是一篇文章。

  目前,有一些资源可以解决“从编译器中获得最少的资源”,这意味着最小大小的代码和最紧凑的执行时间。节省如此多的代码空间可能是剥离功能以保持在设备尺寸内、由于手动优化代码而错过计划或超出 BML 预算之间的区别。

  虽然好的代码可以在任何优化级别上运行相同的操作,但调试高度优化的代码在最好的情况下是很棘手的。例如,整个代码段可以折叠到完全不同的位置的其他代码段中。这就是为什么必须在低优化或无优化下调试代码,并在增加优化以运行全部测试之前验证代码是否正常运行的原因。

  在 BML 中调试成本

  使嵌入式调试变得困难的部分原因是,大多数人根本不知道他们武器库中的所有调试工具。它们倾向于默认使用 printf 语句和代码断点。在尝试隔离硬故障、查找发生堆栈溢出的位置或找出变量不断被破坏的原因时,这些默认值无济于事。

  好消息是,存在特殊的工具可以帮助发现这些类型的问题。

  处理硬故障

  让我们从硬故障开始。许多现代MCU都具有实时指令跟踪功能,可让您跟踪指令流。在基于 Arm 的设备上,用于实现此目的的技术是嵌入式跟踪宏单元 (ETM)。参考手册将指示设备是否支持 ETM。如果是这样,请将跟踪引脚拉到调试标头,并使用启用跟踪的调试器(如 IAR I-jet 跟踪),该调试器可以捕获该实时指令流并将其显示在调试器窗口中。

  要查找导致硬故障的原因,只需滚动跟踪窗口并找到在转到错误处理程序之前执行的指令。瞧!这个指示是罪魁祸首。如果可以可靠地重现错误,请在错误处理程序处设置断点并消除跟踪窗口中的所有滚动 - 罪魁祸首是跟踪窗口中的倒数第二条指令。

  现在原因已知,因此可以在罪魁祸首上设置断点,并再次运行测试用例,以查看导致异常的代码出了什么问题。

  但是,如果您没有 ETM 怎么办?大多数基于 Arm 的设备都具有串行线输出 (SWO),允许采样、低速跟踪。虽然您没有收到每一条指令,但这可以提供足够的跟踪信息来缩小范围并定位问题。此外,尝试降低MCU时钟和/或调整SWO设置,以便从调试器中获取更精细的跟踪信息粒度,以查明问题发生的位置。

  其他设备架构具有与 ETM 或 SWO 类似的功能。因此,使用高质量的工具可以利用这些信息并快速隔离和消除问题。此外,可用的支持资源有助于提高 SWO 的性能,以保护更多的跟踪数据。

  停止堆栈溢出

  堆栈溢出或找出变量神秘丢失其内容的原因怎么样?使用相同的技术来诊断这两种情况。

  在 Arm 领域,大多数处理器在其调试接口中都有一个数据观察点和跟踪 (DWT) 块,可用于快速隔离这些类型的问题。在这种情况下,请使用数据观察点来找出坏事发生的地方。每当接触一段数据时,此观察点本质上就是一个断点。

  将选项配置为仅在读取和/或写入数据时中断执行。此外,甚至可以将其限制为仅在数据是具有特定位掩码的特定值时才中断。在避免每次访问数据时都停止时,这非常方便。

  在堆栈溢出的情况下,我们希望在堆栈顶部设置一个数据观察点。读取或写入该值并不重要,因为堆栈在代码中的那个点已经吹响了。处理器将在堆栈顶部停止执行,提供一个完全保留的调用堆栈,允许查看哪一段代码正在吹堆栈以及您如何到达该点。这是确定如何修复错误的关键。

  清理整理数据

  对于被破坏的数据,我们使用基本相同的技术,只是在该变量经历写入时设置数据观察点。如果始终使用相同的值进行破坏,则进一步缩小断点的范围,仅在将该值写入变量时跳闸。然后,再次运行我们的测试用例,找出导致问题的代码。

  同样,许多其他架构(如瑞萨电子RL78、RX和许多其他芯片供应商的器件)具有类似的功能,可用于实现相同的结果。使用高质量的工具,查找这些类型的问题变得更加容易,并增加了满足紧迫的时间表和截止日期的几率。

  让采购知道您的关心

  事半功倍似乎是一个矛盾,但通过使用正确的工具可以轻松实现。通过使用编译器优化,您可以将代码硬塞到尽可能小的空间中,以便为您的应用程序使用最便宜的设备。

  优化还可以帮助桌面检查您的代码,以查看它在高优化下是否运行相同,以便在您将代码签入构建之前找到潜在的代码缺陷(从而使每个缺陷都计入您的发布指标)。它还通过使用完整的工具箱更快地查找错误来帮助您更有效地进行调试,从而缩短测试和修复周期并更快地启动项目。

  如果您知道工具箱中有哪些工具(以及如何正确使用它们),您就可以让每一分钱都为您的组织发挥作用。

  审核编辑:郭婷

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分