可以使用哪些工具或标准来提高嵌入式C代码的可靠性?


9

我通常使用C语言编写PIC,通常用于开关模式转换器。我听说过各种静态分析工具和标准,例如MISRA C,可用于帮助提高代码的可靠性。我想了解更多。哪种标准或工具可能适合我的情况?


1
您对C语言的看法如何?
Brian Drummond 2014年

1
如果有很好的理由,可以说服我改用其他产品。但这一定是一个很好的案例。
Stephen Collings 2014年

从C切换的“一个很好的情况”不能很快做出,对于PIC来说,可能还没有。对于AVR,ARM或MSP430,Ada值得一看(尽管它吸引了很多负面因素,如您所见!),而对于relrel而言,SPARK值得一看。
Brian Drummond

您可能会发现这些有趣的背景信息:SPARK与MISRA-Cspark-2014.org/entries/detail/…以及正在进行的案例研究:spark-2014.org/uploads/Nosegearpaper_1.pdf
Brian Drummond

可能会花费更多的时间来为从PIC转向现代产品提供理由...尤其是如果您要设计MISRA和SPARK原本打算用于的关键任务系统。
伦丁2014年

Answers:


11

嵌入式代码验证非常棘手,尤其是在处理诸如PIC之类的资源有限的部件时。由于部件的内存限制以及在这类设备上进行的“实时”编程,您常常没有在测试用例中编写代码的奢侈方法。

这是我的一些准则:

  1. 如果没有规范,则写一个规范:如果您不按照规范进行编码,请记录您的代码应该是什么,有效输入是什么,预期输出是什么,每个例程应该花多长时间,可以和不能得到什么?崩溃等-操作理论,流程图,没有什么总比没有好。

  2. 注释您的代码:仅仅因为某些东西对您而言是显而易见的,并不意味着它对其他人而言是显而易见的(或正确的)。注释和代码的可维护性都必须使用纯语言注释。

  3. 防御性代码:不要只包含普通输入的代码。处理缺失的输入,超出范围的输入,数学上的溢出等-代码设计覆盖的角落越多,部署代码时的自由度就越小。

  4. 使用静态分析工具:可能会令人困惑,例如在代码中可以找到PC-lint之类的错误工具。将干净的静态分析运行作为认真测试的一个良好起点。

  5. 同行评审是必不可少的:您的代码应干净整洁并有充分的文档记录,以使独立的各方可以对其进行有效地审查。在门口检查自己的自我,认真考虑提出的任何批评或建议。

  6. 测试是必不可少的:您应该自己进行验证,并对代码进行独立验证。其他人可能以您无法想象的方式破坏您的代码。测试您可以想到的每个有效条件和每个无效条件。使用PRNG并输入垃圾数据。尽一切可能破坏事物,然后修复并重试。如果幸运的话,您将能够在调试模式下运行代码,并查看寄存器和变量-如果不行,则需要提高技巧并切换LED /数字信号以了解自己的状态设备。做任何必要的以获得您需要的反馈。

  7. 深入了解不要害怕看C编译器生成的机器代码。您可能会(会吗?)找到漂亮的C代码爆炸成数十个(甚至不是数百个)操作的地方,应该安全的地方(因为它只有一行代码,对吗?)执行多个中断所需的时间很长。已解雇条件并使其无效。如果某些事情变得非常低效,请对其进行重构,然后重试。


+1所有声音建议。我希望任何专业的固件开发人员在阅读本文时都会微笑并点头。
伦丁2014年

2
同行评审的一个重要方面是,评审与代码有关,而不与程序员有关。如果您使用诸如“首先我先执行此操作,然后再执行该操作”之类的术语来分析代码,则可能会遇到麻烦。思考它的正确方法是“首先由代码执行此操作,然后再执行此操作”。审稿人也是如此:不是“为什么要这么做?”,而不是“为什么代码要这样做?”。
Pete Becker 2014年

您还可以考虑添加:1.使用Cyclomatic Complexity
Check

4

用于在PC上创建可靠软件的大多数相同技术也适用于嵌入式开发。将您的算法与特定于硬件的代码分开,并使用单元测试,模拟,静态分析和诸如Valgrind之类的工具分别进行测试,这很有帮助。这样,只有经过硬件测试的代码要少得多。

我不会放弃C。虽然像Ada这样的语言可以提供一些小的保证,但很容易陷入陷阱,以为该语言的承诺要比实际的多。


Valgrid与PC的关联性可能比8位MCU的关联性高一点,但是:)
Lundin 2014年

不幸的是,一些用于创建优秀PC级软件的技术非常不适合小型微型计算机,而某些PC领域的“坏与错误”实践在嵌入式环境中完全可以接受。
约翰·U

3

MISRA-C对于提高通用代码质量并最大程度地减少错误确实非常有用。只要确保您已阅读并理解每条规则,它们中的大多数都是好方法,但是其中一些没有任何意义。

这里是警告。MISRA文档假定读者是具有C语言广泛知识的人。如果您的团队中没有这样的资深C专家,而是决定使用静态分析器,然后盲目地遵循每一个给出的警告,则很可能会导致代码质量降低,因为这可能会降低可读性并偶然引入错误。我已经看到这种情况发生了很多次,将代码转换为MISRA合规性并不是一件容易的事。

可能有两种版本的MISRA-C文档。MISRA-C:2004仍然是当前的嵌入式行业实际标准。或支持C99标准的新MISRA-C:2012。如果您以前从未使用过MISRA-C,我建议您实施后者。

但是请注意,工具供应商通常会在说自己进行MISRA检查时引用MISRA-C:2004(有时甚至会参考过时的MISRA-C:1998版本)。据我所知,MISRA-C:2012的工具支持仍然有限。我认为到目前为止,只有一些静态分析器实现了它:Klocwork,LDRA,PRQA和Polyspace。可能更多,但您肯定需要检查其支持的MISRA版本。

在做出决定之前,您当然可以先阅读MISRA文件并查看其中的内容。可以从misra.org上以10英镑的价格购买它,与ISO标准的价格相比,这是相当实惠的。


1

Mathworks(MATLAB专家)拥有一个称为Polyspace的静态代码分析工具。

除了静态代码分析,lint等之外,我还建议仔细定义和设计接口(具有正式的检查过程)以及代码覆盖率分析。

您可能还需要查看有关安全关键代码设计的准则,包括MISRA,UL1998和IEC 61508标准。


除非必须这样做,否则我建议不要靠近IEC 61508。它确实提到了软件,但是缺乏现代的科学依据。该标准来得晚了30年-如果像大多数所谓的“资源”一样在70年代发布,它可能会很有用。
伦丁2014年

1

对于此问题的完整答案,我不考虑“代码可靠性”的思想,而是考虑“设计可靠性”,因为代码只是设计的最终表达。

因此,从需求开始,编写并检查这些需求。如果您没有需求文档,请指向随机的代码行,然后问自己“为什么需要该行?” 最终,对任何一行代码的需求都应该可以追溯到需求,即使它很简单/显而易见,例如“如果输入介于12-36VDC之间,则电源将输出5VDC。” 考虑这一点的一种方法是,如果该行代码无法追溯到需求,那么您怎么知道它是正确的代码,或者根本不需要它?

接下来,验证您的设计。如果它完全在代码中(例如,在注释中)也可以,但是这使得很难知道代码是否在执行真正的意思。例如,代码中的一行可能显示output = 3 * setpoint / (4 - (current * 5));current == 4/5:是否输入有效的输入,可能会导致崩溃?在这种情况下应采取什么措施防止被零除?您是完全避免该操作还是降低输出?在设计文档中有关于如何处理此类极端情况的一般注释,可以更轻松地在更高级别上验证设计。因此,现在代码检查变得更加容易,因为这是检查代码是否正确实现了该设计的问题。

与此同时,代码检查还应检查IDE不能捕获的常见错误(您正在使用IDE,对吗?),例如,当您表示'=='时,例如'=',缺少会改变'if'含义的花括号。 '语句,不应在的分号等。

在撰写本文时,我很难在一个帖子中总结多年的软件质量培训/经验。我为医疗设备编写了代码,以上内容是我们处理该方法的极为简化的摘要。


我的理解是,医疗设备中的代码部分几乎像单独的设备一样经过测试。准确吗?
Scott Seidman 2014年

@ScottSeidman更有可能,如本答案所述,它是在需求基础上进行测试的。对于每个需求,您都应该有一个代码模块,对于每个此类代码模块,都应该有一个测试。因此,从本质上讲,每个需求都有相应的测试,而代码就是满足需求的手段。在任何关键任务系统中,这种需求跟踪都是很常见的做法,早在“ TDD”流行语出现之前。
伦丁2014年

我专门指的是FDA指南,例如fda.gov/downloads/RegulatoryInformation/Guidances/ucm126955.pdf 从规划阶段和设计控制开始,该软件实际上对医疗设备的需求超出了您的想象。
Scott Seidman

斯科特,我从来没有那样想过,但是你是对的。我们的软件质量保证人员在将软件移交给另一个负责系统验证和确认的小组之前,将软件与系统的其余部分分开(尽可能)进行验证。
lyndon 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.