Gibt es Standardtestmethoden für Bare-Metal-Code?

Ich möchte wissen, ob Bare-Metal-Code, insbesondere Dinge wie Geräte-/Peripherie-Initialisierungscode, Testmethoden hat, da beim Schreiben in Register wenig bis nichts schief gehen kann (sobald Sie wissen, dass alle Adressen korrekt zugeordnet sind). Außerdem hat diese Art von Code normalerweise sehr wenige Verzweigungen/Pfade, wenn das Gerät nur für eine einzige Funktion konfiguriert wird. Welche Arten von Tests wären hier also notwendig oder anwendbar?

Antworten (1)

Das erste, was ich auf einem neuen Board überprüfe, ob es einen internen Oszillator oder einen externen Quarz verwendet, ist, dass ich die Taktfrequenz richtig eingestellt habe. Dies ist wichtig, da viele Peripheriegeräte wie UART, SPI, I2C und Timer davon abhängen.

Ich verifiziere es, indem ich ein Programm mit einer kurzen Schleife schreibe, entweder in Assembler, wo ich die Zyklen manuell zählen kann, oder in C, solange Sie eine Disassemblierungsliste erhalten und dasselbe tun können - und eine LED einschalten und aus. Ich habe eine Schleife so eingerichtet, dass sie einmal pro Sekunde ausgeführt wird. Ich führe den Code aus und überprüfe, ob die LED 60 Mal in einer Minute blinkt.

Was die Peripheriegeräte betrifft, so können Sie sie am besten mit einem Oszilloskop überprüfen, falls Sie eines haben, und sich die RX-Leitung für UART, die CLK-, MOSI- und Chipauswahlleitungen für SPI sowie die SDA- und SCL-Leitungen ansehen I2C, und überprüfen Sie, ob die Leitungen umschalten und das Timing korrekt aussieht.

Wenn Sie kein Oszilloskop haben, können Sie LEDs an diesen Leitungen anbringen und dann die Peripheriegeräte aktivieren oder deaktivieren. Wenn sie deaktiviert sind, sind die meisten Leitungen niedrig (LED aus), aber einige sind hoch, wie die RX-Leitung des UART (LED an). Wenn das Peripheriegerät aktiviert ist, sollten die meisten LEDs dimmen, da die Leitungen umschalten. Durch das Ausführen einer Schleife (deaktiviert/aktiviert) ist es einfacher, den Unterschied zwischen ein oder gedimmt zu erkennen.

Für den UART können Sie die TX-Leitung als Schleife mit der RX-Leitung verbinden. Sie können dann auch ein UART-zu-USB-Kabel anschließen und auf dem PC ein reales Terminal mit einem Programm wie RealTerm verbinden . Neben dem Testen der Schnittstelle wird dies später für andere Debugging-Aufgaben nützlich sein.

Für andere Codeteile verwende ich nach Bedarf mehrere LEDs, um anzuzeigen, dass verschiedene Pfade im Code ausgeführt werden. Wenn der UART funktioniert und mit einem PC verbunden ist, können Sie Ihren Code mit Aufrufen einer Unterroutine bestreuen, um eine Nachricht auszugeben, die anzeigt, welche Punkte das Programm erreicht hat (oder verwenden Sie printf, wenn Sie die Standard-C-Bibliotheken zur Verfügung haben). Aber wie Vladimir Cravero in einem Kommentar unten darauf hinweist, kann dies Ihren Code etwas verlangsamen (bei 115.200 Baud nicht zu viel, da die Zeit eines Zeichens < 10 µs beträgt). Aber in ISRs und anderem zeitkritischem Code verwenden Sie einfach LEDs.

Wie Al Bundy in einem Kommentar unten betont, können In-Circuit-Debugger auch nützlich sein, insbesondere wenn man mehrere Breakpoints setzen kann, und noch nützlicher, wenn man Breakpoints an einem Speicherort setzen kann, der geändert wird. Nicht alle Debugger haben diese Funktion.

Allerdings verwende ich Debugger nicht oft, es sei denn, ich muss zum Beispiel Bits in einem Peripherieregister betrachten; oder um einen Fehler aufzuspüren, den ich nicht durch Inspektion finden kann; oder zu einer rudimentären Code-Coverage-Analyse. Aber im Allgemeinen führe ich Programme gerne mit ihrer "normalen" Geschwindigkeit aus, da normalerweise viele Probleme auftreten, die möglicherweise nicht auftreten, wenn das Programm in Einzelschritten ausgeführt wird. Die meisten meiner Programme verwenden häufig Interrupts, was die Verwendung eines Debuggers stört.

Sie haben so ziemlich alles gesagt, ich würde nur hinzufügen, dass das Besprühen Ihres Codes mit fprintf ihn normalerweise sehr verlangsamt, es ist eine Sache, die Sie bei Bedarf verwenden sollten und wenn Sie wissen, was Sie tun. Ich habe einige Fragen (und hatte einige Probleme) zu einem fprintf in einem ISR oder so gesehen.
@VladimirCravero Stimme zu - deshalb verwende ich gerne LEDs.
Danke für die Antwort. Irgendwelche Hinweise darauf, welche Tools/Setups Sie für die Codeabdeckung verwenden würden, falls Sie nur einen Simulator, aber nicht die eigentliche Hardware haben?
Was ist mit dem Debugger? Ist es nicht erwähnenswert?
@ user4934 Code-Coverage-Tools sind sehr abhängig von dem verwendeten Prozessor und Compiler/IDE, daher kann ich keine empfehlen. Außerdem können sie sehr teuer sein – in Tausenden von Dollar. Stattdessen können Sie mithilfe einiger der Techniken in diesem Artikel Ihre eigenen Codeabdeckungstools erstellen . (Anmerkung: Beispiele sind in Perl, aber sehr C-ähnlich.) Um zu testen, welche Pfade ein Programm nimmt, können Sie Haltepunkte auf einem oder beiden Zweigen setzen, wann immer Sie eine Entscheidung treffen.
Ich stimme Ihnen absolut zu, aber da ARM immer beliebter wird, möchte ich daran erinnern, dass GCC und GDB (beide unterstützen ARM) kostenlose Tools sind und es sich lohnt, bei der Auswahl eines Geräts für ein Projekt daran zu denken.
@AlBundy Ich verwende Debugger nicht oft, es sei denn, ich muss zum Beispiel Bits in einem Peripherieregister betrachten. oder um einen Fehler aufzuspüren, den ich nicht durch Inspektion finden kann; oder um eine rudimentäre Codeabdeckungsanalyse durchzuführen, wie ich in meinem Kommentar zum OP erwähnt habe. Aber im Allgemeinen führe ich Programme gerne mit ihrer "normalen" Geschwindigkeit aus, da normalerweise viele Probleme auftreten, die nicht auftreten, wenn das Programm in Einzelschritten ausgeführt wird. Die meisten meiner Programme verwenden häufig Interrupts, was die Verwendung eines Debuggers stört. Ich werde einige dieser Kommentare in meine Antwort aufnehmen.
Ein funktionierender In-Circuit-Debugger kann viel Zeit sparen, insbesondere wenn ein System komplex wird. Es ist wertvoll, einfach einen Breakpoint auf unerwartete System-Traps setzen zu können.
@ pjc50 Ich stimme voll und ganz zu; Mir fallen keine Projekte ein, die ich in den letzten Jahrzehnten durchgeführt habe, bei denen ich keinen In-Circuit-Debugger hatte. (Ich habe in den späten 70ern angefangen, als sich das Programm auf einem separaten EPROM – nicht EEPROM – befand und es kein In-Circuit-Debugging gab, es sei denn, Sie wollten Intel 5500 Dollar für einen ICE-86 zahlen, ich kann mich nicht erinnern, ob jemand andere verkauften ICEs. Ihr hatten ein Kabel, das in die Buchse für Ihren Mikroprozessor eingesteckt wurde.) Ich arbeite hauptsächlich mit PICs und habe sowohl einen ICD 3 als auch einen RealICE, letzterer ermöglicht die Verwendung der in den PIC32 eingebauten JTAG-Schnittstelle.