Wie kann ich ein Bild vom Speicher (SRAM) Verwendung eines AVR-Programm?
Ich habe ein problem in einem C-Programm läuft auf einem AVR-mikrocontroller (ATMega328P). Ich glaube, es ist aufgrund von einem stack/heap Kollision, aber ich möchte in der Lage, dies zu bestätigen.
Gibt es eine Möglichkeit, ich kann visualisieren SRAM Verwendung von stack und heap?
Hinweis: das Programm ist compiliert mit avr-gcc und nutzt die avr-libc.
Update: Das eigentliche problem, das ich habe, ist, dass die malloc-Implementierung ist nicht (Rückkehr NULL
). Alle malloc
ing geschieht auf Start und alle free
ing geschieht am Ende der Anwendung (die in der Praxis nie, da die wichtigsten Teile der Anwendung in eine unendliche Schleife). Also ich bin mir sicher, dass die Fragmentierung ist nicht das Problem.
InformationsquelleAutor der Frage Matthew Murdoch | 2009-06-06
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ihnen sagen malloc fehlschlägt, und NULL zurückgeben:
Die offensichtliche Sache, die Sie sollten auf den ersten Blick ist, dass Sie Ihre Haufen "voll" - ich.e, die Erinnerung, du hast gefragt, malloc zugewiesen werden kann, weil es nicht verfügbar ist.
Gibt es zwei Szenarien zu Bedenken:
: Sie haben eine 16-K-heap, haben Sie bereits malloced 10 K und Sie versuchen, und malloc einen weiteren 10K. Dein Haufen ist einfach zu klein.
b: häufiger, Sie haben eine 16 k Speicher, den Sie gemacht haben, ein Bündel von malloc/free/realloc-Aufrufe und Ihre heap weniger als 50% "voll": Sie rufen malloc für 1K und es nicht - was ist Los? Antwort - die heap-Speicherplatz fragmentiert ist - es ist nicht ein contigous 1K freier Speicher zurückgegeben werden können. C Heap-Manager können nicht kompakt heap wenn dies geschieht, so sind Sie in der Regel in einem schlechten Weg. Es gibt Techniken, um eine Zersplitterung zu vermeiden, aber es ist schwierig zu wissen, ob dies wirklich das problem. Sie müssten hinzufügen, Protokollierung Beilagen zu malloc und free, so dass Sie können erhalten eine Idee von, was dynamischen Speicher-Operationen durchgeführt werden.
EDIT:
Sagen Sie alle mallocs passieren beim starten, sodass die Fragmentierung ist nicht das Problem.
In dem Fall, sollte es einfach sein zu ersetzen, die dynamische Allokation bei der statischen.
alten code-Beispiel:
neuen code:
Sobald Sie dies getan haben, überall, Ihr LINKER sollte Sie warnen, wenn alles passt nicht in den Speicher zur Verfügung. Vergessen Sie nicht, reduzieren Sie die heap-Größe - aber Vorsicht, dass einige runtime-io-system Funktionen noch verwenden den heap, so dass Sie möglicherweise nicht in der Lage es komplett zu streichen.
InformationsquelleAutor der Antwort Roddy
Können Sie überprüfen, statische RAM-Nutzung mittels
avr-size
- Dienstprogramm, wie beshrieben inhttp://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=62968,
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=82536,
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=95638,
und http://letsmakerobots.com/node/27115
avr-size -C -x Filename.elf
(avr-size-Dokumentation: http://ccrma.stanford.edu/planetccrma/man/man1/avr-size.1.html )
Folgt ein Beispiel, wie man dies auf eine IDE:
Auf Code::Blocks, Projekt -> Build-Optionen -> Pre/post-build-Schritte -> Post-build-Schritte umfassen:
avr-size -C $(TARGET_OUTPUT_FILE)
oder
avr-size -C --mcu=atmega328p $(TARGET_OUTPUT_FILE)
Beispiel für die Ausgabe am Ende von build:
Daten ist dein SRAM, und es ist nur der Betrag, den der compiler
weiß zur compile-Zeit. Sie müssen auch Raum für die Dinge, die erstellt am
Laufzeit (besonders stack-Nutzung).
Überprüfen stack usage (dynamic RAM),
von http://jeelabs.org/2011/05/22/atmega-memory-use/
Hier ist eine kleine utility-Funktion, die bestimmt, wie viel RAM ist
derzeit ungenutzt:
Und hier ist eine Skizze, code:
Dem freeRam () - Funktion gibt an, wie viele bytes existiert zwischen dem Ende des Heaps, und die letzten reservierten Speicher auf dem stack, so ist es effektiv, wie viel der stack/heap wachsen können, bevor Sie kollidieren.
Sie könnte prüfen, die Rückkehr dieser Funktion um code, den Sie in Verdacht verursacht stack/heap Kollision.
InformationsquelleAutor der Antwort mMontu
Nicht verwenden den heap /dynamische Zuordnung auf embedded targets. Vor allem mit einem Prozessor mit so begrenzten Ressourcen. Eher redesign der Anwendung, weil das problem erneut auftreten, da Ihr Programm wächst.
InformationsquelleAutor der Antwort Gerhard
Ist die übliche Vorgehensweise wäre zu füllen die Speicher mit einem bekannten Muster und dann zu überprüfen, welche Bereiche überschrieben werden.
InformationsquelleAutor der Antwort starblue
Wenn Sie beide Stapel und heap, dann kann es ein wenig komplizierter. Ich werde erklären, was ich getan habe wenn nicht-heap verwendet wird. Als Allgemeine Regel werden alle Firmen, für die ich gearbeitet habe, für die (in der Domäne der embedded C software) vermieden werden können, den heap für kleine embedded-Projekte zu vermeiden, die Unsicherheit der heap-Speicher Verfügbarkeit. Wir die Verwendung von statisch deklarierten Variablen statt.
Eine Methode ist, füllen die meisten der stack-Bereich mit einem bekannten Muster (z.B. 0x55) bei start-up. Dies geschieht in der Regel durch ein kleines Stück code, der frühzeitig in der software-Ausführung, entweder gleich beim start von main(), oder vielleicht sogar vor der main() beginnt, in der start-up-code. Achten Sie darauf, nicht zu überschreiben, die kleine Menge des Stapels zu diesem Punkt natürlich. Dann, nach der Ausführung der software für eine Weile, überprüfen Sie den Inhalt des stack-space und sehen, wo die 0x55 ist noch intakt. Wie Sie "inspizieren", hängt von Ihrem Ziel-hardware. Vorausgesetzt, Sie haben ein debugger angeschlossen ist, dann können Sie einfach aufhören, das Mikro laufen und Lesen des Speichers.
Wenn Sie einen debugger, der kann auch ein memory-access-Haltepunkt (ein bisschen mehr Phantasie als die übliche Ausführung, Haltepunkt), dann legen Sie einen Haltepunkt in einer bestimmten stack-location—wie der am weitesten entfernte Grenze Ihres stack-Speicher. Das kann sehr nützlich sein, weil es auch zeigt Sie genau das, was Stück code, der ausgeführt wird, wenn es erreicht, das Ausmaß der stack-Nutzung. Aber es erfordert, dass Sie Ihre debugger zur Unterstützung der Gedächtnis-Zugang Haltepunkt-Funktion, und es ist oft nicht in der "low-end" - Debugger.
Wenn man auch ein heap ist, dann kann es ein bisschen komplizierter, da kann es unmöglich sein, vorherzusagen, wo stack und heap wird kollidieren.
InformationsquelleAutor der Antwort Craig McQueen
Angenommen, Sie sind mit nur einem stack (also nicht ein RTOS oder nichts) und dass der Stapel am Ende des Speichers, wächst nach unten, während der heap beginnt nach dem BSS/DATA region, aufgewachsen. Ich habe gesehen, Implementierungen von malloc, die tatsächlich überprüfen Sie die stackpointer und nicht auf eine Kollision. Sie könnten versuchen, das zu tun.
Wenn Sie sich nicht anpassen kann, ist das malloc-code, können Sie wählen, um Ihre Stapel am Anfang des Speichers (unter Verwendung der linker-Datei). Im Allgemeinen ist es immer eine gute Idee zu wissen/definieren Sie die maximale Größe des stack. Wenn du es an den start, erhalten Sie eine Fehlermeldung, die auf das Lesen über den Anfang des RAM. Der Heap wird am Ende und kann wahrscheinlich nicht wachsen, über das Ende, wenn es eine anständige Implementierung (NULL zurück statt). Gute Sache, die Sie wissen müssen 2 separate Fehler-Fällen, für 2 getrennte Fragen.
Finden Sie heraus, die maximale stack-Größe, Sie könnte füllen Sie Ihre Speicher mit einem Muster, die Anwendung ausführen und sehen, wie weit es ging, siehe auch die Antwort von Craig.
InformationsquelleAutor der Antwort Ron
Wenn Sie können, Bearbeiten Sie den code für Ihre heap, pad könnte es mit ein paar extra bytes (schwierig auf so niedrige Ressourcen) für jeden block des Speichers. Diese bytes enthalten können ein bekanntes Muster unterscheidet sich von dem Stapel. Dies könnte Ihnen eine Ahnung, wenn es kollidiert mit dem stack, indem Sie sehen, es erscheinen in den stack oder Umgekehrt.
InformationsquelleAutor der Antwort Jay Atkinson
Auf Unix-artigen Betriebssystemen eine library-Funktion namens sbrk() mit einem parameter von 0 ermöglicht den Zugriff auf die oberste Adresse des dynamisch allozierten heap-Speicher. Der Rückgabewert ist ein void * - pointer und könnte verglichen werden mit der Adresse von einem beliebigen Stapel zugewiesene variable.
Anhand des Ergebnisses dieses Vergleichs mit Vorsicht verwendet werden sollte. Abhängig von der CPU-und system-Architektur, kann der Stapel wächst nach unten von einem beliebigen hohen-Adresse während der zugewiesenen heap nach oben von low-gebunden-Speicher.
Manchmal das Betriebssystem hat andere Konzepte für die Verwaltung des Speichers (z.B. OS/9) die Plätze heap und stack in verschiedenen Speicher-Segmente, die im freien Speicher. Auf diese Betriebssysteme, insbesondere für eingebettete Systeme - definieren Sie die maximale Speicher-Anforderungen Ihres
Anwendungen im Voraus, damit das system die Speicher-Segmente passende Größen.
InformationsquelleAutor der Antwort Ralf Edmund