mikrocontroller.net

Forum: Compiler & IDEs RAM-"Rest" als Cache - malloc oder nicht malloc?


Autor: Detlev T. (detlevt)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Detlev T. (detlevt)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Detlev T. (detlevt)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 ;-) )
#include <avr/io.h>
#include <stdlib.h>

#define MAX_STACK_SIZE 512

int main(void)
{
  uint16_t  buffer_size;
  uint8_t * buffer = (uint8_t *) __malloc_heap_start;

    buffer_size = RAMEND - (uint16_t) buffer - MAX_STACK_SIZE;
    return 0;
}

Gruß, DetlevT

Autor: sebastians (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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)?

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: thorstendb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Detlev T. (detlevt)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Josef D. (jogedua)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.