2009-06-06 5 views
23

Obwohl es viele Unit-Test-Frameworks gibt, die C unterstützen, bin ich etwas ratlos, wie man Komponententests für Microcontroller-Code schreibt (PIC in meinem Fall, aber ich denke, die Frage ist allgemeiner als das).Unit-Testmuster für Mikrocontroller C-Code

Ein Großteil des für Mikrocontroller geschriebenen Codes dreht sich um das Schreiben von Konfigurations- und Datenwerten in Register, das Lesen ankommender Daten aus Registern und das Reagieren auf Interrupt-Ereignisse. Ich frage mich, ob irgendjemand auf dem effektivsten Weg einige Hinweise geben kann.

+0

Könnte jemand mit genügend rep bitte auf den "embedded" -Tag auf diese Frage hinzufügen? Vielen Dank. –

Antwort

29

Sie schreiben;

"Ein Großteil des für Mikrocontroller geschriebenen Codes dreht sich um das Schreiben von Konfigurations- und Datenwerten in Register, das Lesen ankommender Daten aus Registern und das Reagieren auf Interrupt-Ereignisse".

Ich stimme zu, dass dies in der Praxis oft der Fall ist, aber ich denke nicht, dass dies eine gute Sache ist, und ich denke, dass das Umdenken ein wenig hilft.

Vielleicht weil Mikrocontroller-Programmierer erreichen und berühren die Hardware jederzeit sie mögen, haben viele (die meisten?) Von ihnen in die Angewohnheit, genau das zu tun, in ihrem Code. Oft wird diese Gewohnheit ohne Frage verfolgt, vielleicht weil so viele Leute, die diese Art von Arbeit machen, keine Computerwissenschaftler sind, sondern durch Ausbildung und Neigung. Ich weiß, ich habe selbst so angefangen.

Der Punkt, den ich versuche zu machen, ist, dass Mikrocontroller-Projekte wie jedes andere Software-Projekt gut gestaltet sein können und sollten. Ein wirklich wichtiger Teil des guten Designs ist es, den Hardwarezugriff auf Hardwaretreiber zu beschränken! Partitionieren Sie den gesamten Code, der Register schreibt, auf Interrupts usw. reagiert, in Module, die dem Rest Ihrer Software einen schönen, sauberen, abstrahierten Zugriff auf die Hardware bieten. Testen Sie diese Treibermodule auf dem Ziel mit Logikanalysatoren, Oszilloskopen, benutzerdefinierten Prüfständen oder was auch immer sinnvoll ist.

Ein wirklich wichtiger Punkt ist, dass jetzt der Rest Ihrer Software, hoffentlich die große Mehrheit davon, jetzt nur C-Code ist, den Sie auf einem Host-System ausführen und testen können. Auf dem Host-System sind die Hardware-Module so ausgestanzt, dass sie Einblick in den Code geben, der gerade getestet wird. Sie können Mainstream Unit Testing-Ansätze für diesen Code verwenden. Dies erfordert einige Vorbereitungen und Arbeit, aber wenn Sie gut organisiert sind, können Sie ein wiederverwendbares System erstellen, das für alle Ihre Projekte gelten kann. Die potenziellen Vorteile sind enorm. Ich habe hier ein wenig mehr über diese Ideen geschrieben;

[http://discuss.joelonsoftware.com/default.asp?joel.3.530964.12][1]

+4

Guter Punkt. Darf ich hinzufügen: Gewöhnen Sie sich daran, uint16_t, uint8_t usw. zu verwenden (statt nur int, char), damit Ihre Typen vorhersagbarer sind, wenn Sie von der eingebetteten Plattform zum PC und zwischen verschiedenen eingebetteten Plattformen springen. –

+3

Probleme mit dieser Antwort: Hardware-Treiberabstraktion verursacht erheblichen Overhead, oft nicht akzeptabel, es sei denn, in Assembler geschrieben. aber Mischen von C und Assembler ist ein enormer Kopfschmerz - nicht nur ist die PIC-Architektur eine PITA zu arbeiten, der Compiler springt durch Reifen jongliert die verschiedenen Banken von Registern usw., die eine sehr große PITA ist, Assembler neben ihm zu schreiben. – Jodes

0

Gibt es vielleicht irgendeinen Loopback-Modus, so dass Sie den Controller selbst verwenden können, um Ereignisse zu generieren, gegen die Sie testen können?

3

Ein Ansatz dazu könnte die Verwendung eines Emulators sein. Ich habe an einem AVR-Emulator gearbeitet und eine der Ideen für die Verwendung ist in der Tat, Unit-Test-Code. Der Emulator implementiert die CPU und Register, Interrupts und verschiedene Peripheriegeräte, und (in meinem Fall) Bytes, die in den emulierten UART geschrieben werden, gehen zum normalen stdout des Emulators. Auf diese Weise kann der Komponententestcode im Emulator ausgeführt werden und seine Testergebnisse in die Konsole schreiben.

Natürlich muss man auch sicherstellen, dass der Emulator das Verhalten der realen CPU korrekt implementiert, sonst kann man den Unit-Tests nicht trauen.

2

Schreiben Sie Mock-Versionen Ihrer Registerzugriffsfunktionen/Makros. Beachten Sie, dass dies davon ausgeht, dass Ihr Code einen allgemeinen Satz von Registerzugriffsfunktionen verwendet und keine Ad-hoc-Dateien wie *(volatile int*)0xDEADBEEF = 0xBADF00D überall.

Rufen Sie Ihre Interrupt-Handler direkt von Ihrem Testcode (kann auf einigen Architekturen ¹ problematisch sein), ein "Software-Interrupt" falls verfügbar, oder von einem Timer-Interrupt-Handler, wenn Sie sie asynchron ausführen müssen. Dies kann erfordern, dass Sie Ihren Interrupt aktivieren/deaktivieren Code in Funktionen/Makros, die Sie mock-up können.

¹ 8051 kommt in den Sinn: Zumindest mit dem Keil 8051 Compiler können Interrupt-Funktionen nicht direkt aufgerufen werden. Dies könnte jedoch mit dem C-Präprozessor ausgearbeitet werden.

Verwandte Themen