Welche Tools oder Standards können verwendet werden, um die Zuverlässigkeit von eingebettetem C-Code zu verbessern?

9

Normalerweise programmiere ich PICs in C, normalerweise für Schaltwandler. Ich habe von verschiedenen statischen Analysetools und Standards wie MISRA C gehört , mit denen die Zuverlässigkeit von Code verbessert werden kann. Ich würde gerne mehr wissen. Welche Standards oder Tools könnten für meinen Kontext geeignet sein?

Stephen Collings
quelle
1
Wie eingestellt bist du auf die C-Sprache?
Brian Drummond
1
Ich könnte überredet werden, zu etwas anderem zu wechseln, wenn es einen sehr guten Fall dafür gibt. Aber es müsste ein sehr guter Fall sein.
Stephen Collings
"Ein sehr guter Fall" für den Wechsel von C kann nicht schnell gemacht werden, und für den PIC möglicherweise noch gar nicht. Für AVR, ARM oder MSP430 wäre Ada einen ernsthaften Blick wert (trotz der Negativität, die es anzieht, wie Sie sehen können!) Und für High Rel ist SPARK einen Blick wert.
Brian Drummond
Sie können diese als Hintergrundinformationen interessant finden: SPARK vs MISRA-C spark-2014.org/entries/detail/… und diese laufende Fallstudie: spark-2014.org/uploads/Nosegearpaper_1.pdf
Brian Drummond
Vielleicht ist es besser, Zeit zu investieren, um vom PIC auf etwas Modernes umzusteigen ... Vor allem, wenn Sie die Art von unternehmenskritischen Systemen entwerfen, für die MISRA und SPARK ursprünglich gedacht waren.
Lundin

Antworten:

11

Die Validierung von eingebettetem Code ist schwierig, insbesondere wenn es sich um Teile mit begrenzten Ressourcen wie PICs handelt. Aufgrund der Speicherbeschränkungen des Teils und der häufig in Echtzeit durchgeführten Programmierung auf solchen Geräten haben Sie häufig nicht den Luxus, in Testfällen zu codieren.

Hier sind einige meiner Richtlinien:

  1. Schreiben Sie eine Spezifikation, wenn es keine gibt: Wenn Sie nicht gegen eine Spezifikation codieren, dokumentieren Sie, was Ihr Code soll, was gültige Eingaben sind, was erwartete Ausgaben sind, wie lange jede Routine dauern sollte, was kann und was nicht verstopft usw. - eine Betriebstheorie, Flussdiagramme, alles ist besser als nichts.

  2. Kommentieren Sie Ihren Code: Nur weil etwas für Sie offensichtlich ist, heißt das nicht, dass es für jemand anderen offensichtlich (oder korrekt) ist. Kommentare in einfacher Sprache sind sowohl für die Überprüfung als auch für die Wartbarkeit des Codes erforderlich.

  3. Defensiver Code: Fügen Sie nicht nur Code für normale Eingaben ein. Behandeln Sie fehlende Eingaben, Eingaben außerhalb des Bereichs, mathematische Überläufe usw. - je mehr Ecken Sie durch Ihr Code-Design abdecken, desto weniger Freiheitsgrade hat der Code bei der Bereitstellung.

  4. Verwenden Sie statische Analysetools: Es kann demütig sein, wie viele Fehler-Tools wie PC-Lint in Ihrem Code enthalten sind. Betrachten Sie einen sauberen statischen Analyselauf als guten Ausgangspunkt für ernsthafte Tests.

  5. Peer Reviews sind unerlässlich: Ihr Code sollte sauber und gut dokumentiert genug sein, damit er von einer unabhängigen Partei effizient überprüft werden kann. Überprüfen Sie Ihr Ego an der Tür und denken Sie ernsthaft über Kritik oder Vorschläge nach.

  6. Das Testen ist wichtig: Sie sollten Ihre eigene Validierung durchführen und eine unabhängige Validierung des Codes durchführen lassen. Andere können Ihren Code auf eine Weise brechen, die Sie sich unmöglich vorstellen können. Testen Sie jede gültige Bedingung und jede ungültige Bedingung, die Sie sich vorstellen können. Verwenden Sie PRNGs und geben Sie Mülldaten ein. Tun Sie alles, um Dinge zu beschädigen, reparieren Sie sie und versuchen Sie es erneut. Wenn Sie Glück haben, können Sie Ihren Code im Debug-Modus ausführen und einen Blick auf Register und Variablen werfen. Wenn nicht, müssen Sie geschickt sein und LEDs / digitale Signale umschalten, um eine Vorstellung von Ihrem Status zu erhalten Gerät. Tun Sie alles Notwendige, um das Feedback zu erhalten, das Sie benötigen.

  7. Schauen Sie unter die Haube: Haben Sie keine Angst, sich den von Ihrem C-Compiler generierten Maschinencode anzusehen. Sie können (werden?) Orte finden, an denen Ihr schöner C-Code in zehn, wenn nicht Hunderte von Operationen gesprengt wurde, an denen etwas, das sicher sein sollte (da es nur eine Codezeile ist, richtig?), So lange dauert, bis mehrere Interrupts ausgeführt werden haben die Bedingungen gefeuert und ungültig gemacht. Wenn etwas schrecklich ineffizient wird, überarbeiten Sie es und versuchen Sie es erneut.

Adam Lawrence
quelle
+1 Alle guten Ratschläge. Ich würde erwarten, dass jeder professionelle Firmware-Entwickler beim Lesen nur lächelt und nickt.
Lundin
2
Ein wichtiger Aspekt von Peer Reviews ist, dass es bei der Überprüfung um den Code geht, nicht um den Programmierer. Wenn Sie Ihren Code mit Begriffen wie "Zuerst mache ich das, dann mache ich das" analysieren, sind Sie wahrscheinlich in Schwierigkeiten. "Zuerst macht der Code das, dann macht er das" ist der richtige Weg, darüber nachzudenken. Gleiches gilt für Rezensenten: nicht "Warum haben Sie das getan?", Sondern "Warum macht der Code das?".
Pete Becker
Sie können auch
Folgendes
4

Die meisten der gleichen Techniken zum Erstellen zuverlässiger Software auf einem PC sind auch auf die Embedded-Entwicklung anwendbar. Es ist hilfreich, Ihre Algorithmen vom hardwarespezifischen Code zu trennen und diese separat mit Komponententests, Simulationen, statischen Analysen und Tools wie Valgrind zu testen. Auf diese Weise gibt es viel weniger Code, der nur auf der Hardware getestet wird.

Ich würde C nicht aufgeben. Während Sprachen wie Ada einige kleinere Garantien bieten können, ist es leicht, in die Falle zu tappen, dass die Sprache mehr verspricht als sie wirklich verspricht.

Theran
quelle
Valgrid könnte für den PC ein bisschen relevanter sein als für eine 8-Bit-MCU :)
Lundin
Leider sind einige Techniken zum Erstellen einer guten Software auf PC-Ebene für kleine Mikros sehr ungeeignet, und einige Praktiken, die im PC-Land als schlecht und falsch angesehen werden, sind in einer eingebetteten Umgebung durchaus akzeptabel.
John U
3

MISRA-C ist in der Tat sehr nützlich, um die allgemeine Codequalität zu verbessern und Fehler zu minimieren. Stellen Sie einfach sicher, dass Sie jede Regel lesen und verstehen. Die meisten davon sind gut, aber einige davon ergeben keinen Sinn.

Eine Warnung hier. Das MISRA-Dokument geht davon aus, dass der Leser über umfassende Kenntnisse der C-Sprache verfügt. Wenn Sie keinen solchen gehärteten C-Veteranen in Ihrem Team haben, sich jedoch für einen statischen Analysator entscheiden und dann blind jede Warnung befolgen, führt dies höchstwahrscheinlich zu einem Code mit geringerer Qualität , da Sie möglicherweise die Lesbarkeit beeinträchtigen und versehentlich Fehler verursachen. Ich habe dies schon oft gesehen. Die Konvertierung von Code in MISRA-Konformität ist keine triviale Aufgabe.

Möglicherweise gibt es zwei Versionen des MISRA-C-Dokuments. Entweder MISRA-C: 2004, das immer noch der aktuelle De-facto-Standard der eingebetteten Industrie ist. Oder der neue MISRA-C: 2012, der den C99-Standard unterstützt. Wenn Sie MISRA-C noch nie zuvor verwendet haben, würde ich Ihnen empfehlen, letzteres zu implementieren.

Beachten Sie jedoch, dass sich Tool-Anbieter normalerweise auf MISRA-C: 2004 beziehen, wenn sie angeben, dass sie eine MISRA-Prüfung haben (manchmal beziehen sie sich sogar auf die veraltete Version von MISRA-C: 1998). Soweit ich weiß, ist die Toolunterstützung für MISRA-C: 2012 noch begrenzt. Ich denke, nur einige statische Analysatoren haben es bisher implementiert: Klocwork, LDRA, PRQA und Polyspace. Könnte mehr sein, aber Sie müssen auf jeden Fall überprüfen, welche Version von MISRA unterstützt wird.

Bevor Sie sich entscheiden, können Sie natürlich zunächst das MISRA-Dokument lesen und sehen, was es beinhaltet. Es kann für £ 10 bei misra.org gekauft werden , was im Vergleich zu den Preisen für ISO-Standards recht erschwinglich ist.

Lundin
quelle
1

Mathworks (die MATLAB-Leute) haben ein statisches Code-Analyse-Tool namens Polyspace .

Neben der statischen Code-Analyse, Flusen und dergleichen würde ich eine sorgfältige Definition und Gestaltung der Schnittstellen (mit einem formalen Überprüfungsprozess) und eine Analyse der Codeabdeckung vorschlagen.

Möglicherweise möchten Sie auch Richtlinien für das sicherheitskritische Code-Design lesen, einschließlich MISRA, aber auch die Standards UL1998 und IEC 61508.

Spehro Pefhany
quelle
Ich empfehle nicht, in die Nähe von IEC 61508 zu gehen, es sei denn, Sie müssen. Es erwähnt zwar Software, aber es fehlen moderne wissenschaftliche Quellen für seine Behauptungen. Dieser Standard kam 30 Jahre zu spät - wäre er in den 70er Jahren wie die meisten seiner sogenannten "Quellen" veröffentlicht worden, wäre er möglicherweise nützlich gewesen.
Lundin
1

Für eine vollständige Antwort auf diese Frage würde ich den Gedanken an "Code-Zuverlässigkeit" unterdrücken und stattdessen an "Design-Zuverlässigkeit" denken, da der Code nur der endgültige Ausdruck des Designs ist.

Beginnen Sie also mit den Anforderungen und schreiben und überprüfen Sie diese. Wenn Sie kein Anforderungsdokument haben, zeigen Sie auf eine zufällige Codezeile und fragen Sie sich, warum diese Zeile benötigt wird. Die Notwendigkeit einer Codezeile sollte eventuell auf eine Anforderung zurückgeführt werden können, selbst wenn dies so einfach / offensichtlich ist wie "Das Netzteil muss 5 VDC ausgeben, wenn der Eingang zwischen 12 und 36 VDC liegt." Eine Möglichkeit, darüber nachzudenken, ist, dass wenn diese Codezeile nicht auf eine Anforderung zurückgeführt werden kann, woher wissen Sie dann, dass es der richtige Code ist oder dass er überhaupt benötigt wird?

Überprüfen Sie als Nächstes Ihr Design. Es ist in Ordnung, wenn es vollständig im Code enthalten ist (z. B. in Kommentaren), aber das macht es schwieriger zu wissen, ob der Code das tut, was wirklich gemeint ist. Beispielsweise kann der Code eine Zeile mit der Aufschrift output = 3 * setpoint / (4 - (current * 5)); Ist current == 4/5eine gültige Eingabe, die einen Absturz verursachen könnte? Was ist in diesem Fall zu tun, um die Division durch Null zu verhindern? Vermeiden Sie den Vorgang insgesamt oder verschlechtern Sie stattdessen die Ausgabe? Wenn Sie in Ihrem Entwurfsdokument einen allgemeinen Hinweis zum Umgang mit solchen Randfällen haben, können Sie den Entwurf auf einer höheren Ebene viel einfacher überprüfen. Die Codeüberprüfung ist jetzt einfacher, da überprüft werden muss, ob der Code dieses Design korrekt implementiert.

Außerdem sollte die Codeüberprüfung nach häufigen Fehlern suchen, die Ihre IDE nicht abfängt (Sie verwenden eine IDE, oder?), Wie z. B. '=', wenn Sie '==' gemeint haben, fehlende Klammern, die die Bedeutung von 'if' ändern 'Aussagen, Semikolons, wo sie nicht sein sollten, etc.

Während ich dies schreibe, fällt mir ein, dass es wirklich schwierig ist, jahrelange Schulungen / Erfahrungen in Softwarequalität in einem einzigen Beitrag zusammenzufassen. Ich schreibe Code für Medizinprodukte und das Obige ist eine extrem vereinfachte Zusammenfassung unserer Herangehensweise.

Lyndon
quelle
Meines Wissens nach wird der Codeteil in einem Medizinprodukt fast so getestet, als wäre es ein separates Gerät. Ist das richtig?
Scott Seidman
@ScottSeidman Wahrscheinlicher ist, dass es auf Anforderungsbasis getestet wird, wie in dieser Antwort erwähnt. Für jede Anforderung sollten Sie ein Codemodul haben, und für jedes dieser Codemodule sollten Sie einen Test haben. Im Wesentlichen hat jede Anforderung einen entsprechenden Test und der Code ist das Mittel, um die Anforderung zu erfüllen. Diese Art der Anforderungsverfolgung ist in allen geschäftskritischen Systemen üblich, lange bevor das Schlagwort "TDD" auftauchte.
Lundin
Ich bezog mich speziell auf FDA- Richtlinien wie fda.gov/downloads/RegulatoryInformation/Guidances/ucm126955.pdf. Software erfordert tatsächlich mehr, als Sie vielleicht denken, wenn sie Teil eines Medizinprodukts ist, beginnend mit der Planungsphase und den Entwurfskontrollen.
Scott Seidman
Scott, ich habe es nie so gesehen, aber du hast recht. Unsere Mitarbeiter der Software-Qualitätssicherung überprüfen die Software (so weit wie möglich) getrennt vom Rest des Systems, bevor sie sie an eine andere Gruppe übergeben, die für die Systemüberprüfung und -validierung verantwortlich ist.
Lyndon