Hallo ihr GCC-Spezies, angenommen, ich möchte bei einem Programm (AVR 8-Bit) den gesamten, bislang noch nicht genutzten, SRAM-Bereich mit einer eigenen Speicherverwaltung verwenden, z.B. als Cache - oder auch etwas anderes. Die Größe soll bei Programmänderungen möglichst automatisch angepasst werden, so dass immer die maximal mögliche Speichergröße zur Verfügung steht. "Sauber" wären wohl folgende Möglichkeiten: 1.) uint8_t-array anlegen und manuell tunen, so dass am Ende aller Speicher genutzt wird. 2.) mit malloc() den gesamten Heap auf einmal reservieren. (Frage: Wie bekomme ich da die maximal mögliche Größe heraus?) "Unsauber"(?): 3.) Einfach Zeiger auf den Bereich zwischen __heap_start und __malloc_margin setzen und so den Speicher nutzen. (Fragen: Gibt es diese Werte überhaupt, wenn ich malloc() & Co gar nicht nutze? Wie gebe ich GCC vor, wie groß der potentielle Stack sein soll, wo also __malloc_margin hinzeigen soll?) Was würdet ihr da empfehlen? Vielen Dank schon einmal für eure Antworten. Gruß, DetlevT
Dein Problem ist das gleiche wie das, was malloc() hat: ohne genaue Kenntnis, wie tief der Stack worst case maximal werden kann, kannst du nur raten, wie viele Bytes oberhalb der regulären Variablen wirklich frei sind. Das ändert sich ja zur Laufzeit der Applikation auch ständig. malloc() dafür zu benutzen hat nur Sinn, wenn du auch seine Verwaltung mit nutzen willst (also die Freigabe des Speichers, das Wieder-zusammen-fügen der freigegebenen Bereiche etc.), ansonsten ist das nur nutzloser Overhead, wenn du ohnehin deinen Cache selbst verwalten willst.
Hallo Jörg, wenn ich dich richtig verstehe, soll ich den Speicher also einfach nutzen. Mit irgendwelchen seltsamen Nebenwirkungen ist also nicht zu rechnen, richtig? Was die maximale Stackgröße betrifft ist meine Vorstellung, dass ich in einer Konfigurationsdatei (.h) - oder auch als Kommandozeilen-Parameter von GCC - irgendeine Größe vorgeben kann und GCC mir dann __margin_heap entsprechend setzt, damit ich diesen Wert im Programm zur Verfügung habe. "Raten" würde ich diese Größe schon können :D. (O.K., so wichtig ist das nicht, weil ich ja auch RAMEND-maximale Stackgröße rechnen kann. Ob __heap_start auch ohne malloc() existiert werde ich gleich einmal ausprobieren.) Zur Ergänzung vielleicht noch diese Information: Es soll mit demselben Quelltext vielleicht wahlweise ein ATMEGA644P oder, wenn mehr RAM gebraucht wird, auch ein ATMEGA1284P zum Einsatz kommen. Da die sich (zur Zeit?) im Preis aber nicht unterscheiden, wäre das nicht ganz so wichtig. Gruß, DetlevT
Detlev T. schrieb: > wenn ich dich richtig verstehe, soll ich den Speicher also einfach > nutzen. Mit irgendwelchen seltsamen Nebenwirkungen ist also nicht zu > rechnen, richtig? Compiler oder Bibliothek fassen (mit Ausnahme von malloc() natürlich) den Bereich zwischen den Variablen und dem Stack nicht an.
Hallo Jörg, Jo, vielen Dank. Zur Ergänzung: Dieser Code lässt sich mit avr-gcc kompilieren (und tut hoffentlich das, was ich will ;-) )
1 | #include <avr/io.h> |
2 | #include <stdlib.h> |
3 | |
4 | #define MAX_STACK_SIZE 512
|
5 | |
6 | int main(void) |
7 | {
|
8 | uint16_t buffer_size; |
9 | uint8_t * buffer = (uint8_t *) __malloc_heap_start; |
10 | |
11 | buffer_size = RAMEND - (uint16_t) buffer - MAX_STACK_SIZE; |
12 | return 0; |
13 | }
|
Gruß, DetlevT
Mal angenommen, ich verwende keine Rekursion. Kann avr-gcc mir dann berechnen, wie viel Stack ich maximal brauche? Kann avr-gcc den Callgraphen nach Zyklen durchsuchen (und mich warnen wenn doch irgendwo eine Rekursion steckt)?
sebastians schrieb: > Kann avr-gcc mir dann berechnen, wie viel Stack ich maximal brauche? Nein. > Kann avr-gcc den Callgraphen nach Zyklen durchsuchen (und mich warnen > wenn doch irgendwo eine Rekursion steckt)? Nein. Andreas
Andreas Ferber schrieb: > sebastians schrieb: >> Kann avr-gcc mir dann berechnen, wie viel Stack ich maximal brauche? > > Nein. Jein. ;-) Wenn du dir den generierten Assemblercode ansiehst (das ist nicht der disassemblierte Code, der im .lss-File gezeigt wird!), dann findest du da Angaben zur Größe des jeweiligen stack frames. Denn Graphen musst du dir schon selbst bauen, aber anhand dieser Angaben solltest du schnell zu einer Idee über den Stackverbrauch gelangen können.
Hi, bevor du irgendetwas machst in deinem code, hole dir nen Pointer auf dein RAM und schreibe es mit einem pattern komplett voll (z.B. 0xdeadbeef, 0x55, 0xaa, ...) Aber kein malloc! Mit "komplett" musst du allerdings aufpassen, dass der Bereich von main() nicht überschrieben wird, sowie ZI etc. Das müsste man vorher aus der map ableiten, wo die Sachen liegen und wie gross die sind. Alternativ kannst du auch in der pre-main btw. im ASM Code diese Rotine unterbringen. Danach lässt du dein Programm wie gewohnt ne Weile laufen, es sollten möglichst alle Zweige durchlaufen werden (worst case), und schaust, was überschrieben wurde. Je nach Laufzeit gibt dir das eine recht verlässliche Idee über den RAM Bedarf. VG, /th.
thorstendb schrieb: > Das müsste man vorher aus > der map ableiten, wo die Sachen liegen und wie gross die sind. Ich habe inzwischen festgestellt, dass __malloc_heap_start auch dann gültig ist, wenn man malloc() selbst nicht aufruft. Damit hat man schon einmal den Beginn des "freien" Bereiches ohne irgendwelche .map-Kalkulationen. RAMEND ist ebenfalls verfügbar. Einfach Ausprobieren ist manchmal recht praktisch, seinen Code zu kennen aber hier wohl noch besser. Im Zweifelsfall hängt das Laufzeitverhalten ja auch von den Parametern ab, da sollte man zumindest abschätzen können, was das worst case scenario sein sollte.
Detlev T. schrieb: > Ich habe inzwischen festgestellt, dass __malloc_heap_start auch dann > gültig ist, wenn man malloc() selbst nicht aufruft. Ja, diese Variable wird statisch mit dem vom Linker bereitgestellten Symbol __heap_start vorbelegt: char *__malloc_heap_start = &__heap_start; > RAMEND ist ebenfalls verfügbar. Sinnvoller ist es aber in jedem Falle, den Stackpointer selbst abzufragen. Dann hast du zumindest bereits den "bottom of stack" zum Zeitpunkt der Abfrage.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.