10 Stimmen

Wie bestimmt man die maximale Stack-Nutzung in einem eingebetteten System?

Wenn ich dem Keil-Compiler die Option "--callgraph" gebe, berechnet er statisch die genaue "Maximale Stack-Nutzung" für mich.

Leider bekomme ich heute die Meldung "Maximum Stack Usage = 284 bytes + Unknown(Functions without stacksize...)", zusammen mit einer Liste von "Functions with no stack information".

Nigel Jones sagt, dass Rekursion in eingebetteten Systemen eine wirklich schlechte Idee ist ( "Berechnung der Stapelgröße" 2009), Daher habe ich darauf geachtet, in diesem Code keine sich gegenseitig rekursiven Funktionen zu erstellen.

Außerdem stelle ich sicher, dass keiner meiner Interrupt-Handler bis zu seinem letzten Return-from-Interrupt-Befehl jemals wieder Interrupts aktiviert, so dass ich mir keine Sorgen über reentrant Interrupt-Handler machen muss.

Ohne Rekursion oder reentrante Interrupt-Handler sollte es in der Lage sein, den maximalen Stackverbrauch statisch zu bestimmen. (Und so werden die meisten Antworten auf Wie lässt sich die maximale Stack-Nutzung ermitteln? gelten nicht). Nach meinem Verständnis findet die Software, die die Option "--callgraph" verwendet zuerst die maximale Stapeltiefe für jeden Interrupt-Handler ermittelt, wenn er nicht durch einen Interrupt höherer Priorität unterbrochen wird, und die maximale Stapeltiefe der main()-Funktion, wenn sie nicht unterbrochen wird. Dann werden alle Werte addiert, um die maximale Stapeltiefe (im schlimmsten Fall) zu ermitteln. Dies ist der Fall, wenn die main()-Hintergrundaufgabe ihre maximale Tiefe erreicht hat, wenn sie von der Unterbrechung mit der niedrigsten Priorität unterbrochen wird, und diese Unterbrechung ihre maximale Tiefe erreicht hat, wenn sie von der Unterbrechung mit der nächstniedrigeren Priorität unterbrochen wird, und so weiter.

Ich vermute, dass die Software, die --callgraph verarbeitet, durch die kleinen Assemblerfunktionen in der Liste "Funktionen ohne Stack-Informationen" verwirrt wird. Die -Callgraph-Dokumentation scheint zu bedeuten, dass ich manuell berechnen (oder eine vorsichtige Schätzung vornehmen) muss, wie viel Stack sie verwenden -- sie sind sehr kurz, also sollte das einfach sein -- und dann "Verwenden Sie Frame-Direktiven in Assembler-Code, um zu beschreiben, wie Ihr Code den Stack verwendet." Einer von ihnen ist der anfängliche Startup-Code, der den Stack auf Null zurücksetzt, bevor er zu main() springt - das verbraucht also in der Tat Null Stack. Ein anderer ist der "Fault"-Interrupt-Handler, der in einer Endlosschleife verharrt, bis ich den Strom wieder einschalte - man kann davon ausgehen, dass dieser null Stack verbraucht.

Ich verwende Keil uVision V4.20.03.0, um Code für den LM3S1968 ARM Cortex-M3 zu kompilieren.

Wie kann ich also "Frame-Direktiven" verwenden, um der Software, die "--callgraph" verarbeitet, mitzuteilen, wie viel Stack diese Funktionen verwenden? Oder gibt es einen besseren Ansatz, um die maximale Stack-Nutzung zu bestimmen?

(Siehe Wie bestimmt man die maximale Stack-Nutzung in einem eingebetteten System mit gcc? für fast die gleiche Frage, die auf den gcc-Compiler abzielt).

3voto

Clifford Punkte 82130

Verwenden Sie die Option --info=stack in der Linkeroption. Die Map-Datei enthält dann eine Stack-Nutzung für alle Funktionen mit externer Verknüpfung.

In einer Single-Tasking-Umgebung gibt der Stackverbrauch für main() den Gesamtbedarf an. Wenn Sie ein RTOS wie RTX verwenden, bei dem jeder Task seinen eigenen Stack hat, müssen Sie die Stack-Nutzung für alle Task-Eintrittspunkte betrachten und dann etwas mehr (64 Byte im Fall von RTX) für die Speicherung des Task-Kontexts hinzufügen.

Diese und andere Techniken, die auf Keil und allgemeiner anwendbar sind, werden beschrieben aquí

3voto

Flash Sheridan Punkte 1701

John Regehr von der University of Utah hat eine gute Diskussion über die Messung der Stack-Nutzung in eingebetteten Systemen unter http://www.embedded.com/design/prototyping-and-development/4025013/Say-no-to-stack-overflow Beachten Sie jedoch, dass der Link zu ftp.embedded.com veraltet ist und dass bei einem Vorkommen von "without interrupts disabled" entweder das erste oder das letzte Wort negiert werden sollte. In der kommerziellen Welt hat Coverity einen konfigurierbaren Stack Overflow Checker, und einige Versionen von CodeWarrior haben ein halbdokumentiertes warn_stack_usage pragma. (In meiner Version der Compiler-Dokumentation wird es nicht erwähnt, aber in MetroWerks' "Targeting Palm OS"-Dokument).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X