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).