Forum: Mikrocontroller und Digitale Elektronik Speicherplatz abfragen


von Mario H. (rocko)


Lesenswert?

Hi Leute,
Hab schon ein wenig gegoogelt und auch schon in Büchern geschmökert, hab 
aber nix rausgekriegt.
Kann es sein dass es keine Möglichkeit gibt herauszukriegen wieviel 
Speicher im Mikrokontroller RAM noch frei ist?
(Atmega 2560, WINAVR)

Ich vergebe speicher dynamisch aufgrund der Daten die über den UART 
kommen und hätte gerne eine rechtzeitige Vorwarnung bevor malloc ein 
"NIL" zurückgibt.

vielen Dank


lg Rocko

von Falk B. (falk)


Lesenswert?

@  Mario Hirth (rocko)

>Kann es sein dass es keine Möglichkeit gibt herauszukriegen wieviel
>Speicher im Mikrokontroller RAM noch frei ist?
>(Atmega 2560, WINAVR)

AFAIK nein.

>Ich vergebe speicher dynamisch aufgrund der Daten die über den UART
>kommen

Sowas ist auf so kleinen uCs wie den AVRs in 99% aller Fälle ungünstig 
bis unsinning. Lege konstante Arrays an und fertig.

MfG
Falk

von Mark B. (markbrandis)


Lesenswert?

Wenn's von Haus aus nix gibt, warum nicht selber machen:
Eine Variable anlegen, die durch jedes malloc() um N Byte größer und 
durch jedes free() um N Byte kleiner wird.

von Horst H. (tubie)


Lesenswert?

So, jetzt geht es angemeldet weiter...

Wenn du das ganze Dynamisch erledigst, gibt es doch eine Routine, welche 
die Daten in des Ram schreiben darf. Vor dem schreiben einfach 
überprüfen, an welcher Stelle der Write Pointer steht und wenn er zu nah 
an die vorher definierte Grenze stößt, dann gibt es einen vor-Alarm und 
beim erreichen der Grenze den richtigen Alarm.


Warum definierst Du nicht einen festen Bereich für den Uart? Sozusagen 
eine Software FiFo und wenn die voll ist, kann entschieden werden ob 
neue Daten nicht mehr gespeichert werden oder ob ältere Daten verworfen 
werden sollen.


Gruß,
Horst(Tubie)

von Hrm (Gast)


Lesenswert?

Kann man eigentlich überhaupt verhindern, das malloc und Kohorten 
gelinkt werden. Soweit ich es von PC Compilern weiss, verwendet 
malloc/free ja eine Art Verwaltungsstruktur (Heap), die ja auch schon 
Platz belegt und zwar auch wenn dann die Funktionen nicht benutzt 
werden.

von Hrm (Gast)


Lesenswert?

Um nochmal auf die ursprüngliche Fragestellung zurückzukommen, müsste es 
doch möglich sein in den Quelltexten von malloc/free zu sehen wieviel 
Platz überhaupt für den Heap vorgesehen ist. Vermutlich ist das ein 
define/const, die man auswerten kann.
Dennoch würde ich einem der Vorredner zustimmen, das man bei dem wenigen 
Speicher eigentlich ganz auf malloc/free verzichten sollte und einen 
eigenen Zähler verwalten. malloc/free ist wohl eher für heterogene 
Speicherstrukturen (Elemente) bei denen auch wahl- bzw. regellos 
(random) Elemente freigegeben werden können, geeignet.

von Mario H. (rocko)


Lesenswert?

Hi Leute,
vielen dank für die vielen Antworten, scheint als hätte ich hier gleich 
einige Philosophiefragen losgetreten ;-)

Zu meinem Grundproblem vielleicht noch ein paar Infos:
Die Daten zum Speichern kommen über die UART rein die ich zum Anzeigen 
speichern muss.
Dabei kommen auch werte Listen (Strings) vor wie z.B. "wenig, mittel, 
viel" oder "Ein, Aus" die einmal von einem Sender definiert werden (die 
listen werden mir eben über den UART geschickt). Später wird über die 
UART nur mehr ein Kürzel für "Zeige Listenwert 5 der 2ten Liste" 
geschickt.

Da die einzelnen Strings zwischen 2 Zeichen (z.B. Ja) und vielen Zeichen 
("Ein Fehler ist Aufgetreten, Rufen Sie den Support") schwanken kann, 
ist es nicht möglich Speicherplatz fix zu vergeben, sodass alle 
Möglichkeiten enthalten sind. Ich möchte also zwischen "wenigen langen 
Texten" und "vielen kurzen Texten" im Betrieb wählen können womit mir 
nur malloc einfällt.

Wenn es alternativen gibt, bitte her damit.

Wäre es denkbar einfach ein laaaaaanges char array zu definieren (das 
fast den gesamten speicherbereich ausfüllt) und ich überlege mir ein 
Schema wie ich rauskriege wo ein listenelement anfängt und wo ein 
anderes aufhört?
Machbar wäre das natürlich, aber ist malloc da nicht die elegantere 
variante?

Ideas welcome


vielen Dank

Rocko

von Peter D. (peda)


Lesenswert?

Mario Hirth schrieb:
> Machbar wäre das natürlich, aber ist malloc da nicht die elegantere
> variante?

Malloc ist nur sinnvoll, wenn die Lebenszeit der Speicherbereiche 
unterschiedlich ist.

Du willst aber nur einmalig zu Anfang Strings speichern und die dann 
adressieren. Dann kannst Du die auch hintereinander in ein festes Array 
ablegen.
Wenn Du nicht immer durchzählen willst bei der Stringausgabe, dann mach 
noch ein Array, was die Adressen der einzelnen Strings enthält, z.B. für 
10 Strings.

Wenn die Strings sich nur selten ändern, dann kannst Du sie auch im 
EEPROM oder Flash ablegen.


Peter

von hmm... (Gast)


Lesenswert?

Ein Interrupt buffer ist ganz sicher nicht dynamisch, sondern statisch. 
Willste im Interupt noch speicher anfordern ?

von Peter (Gast)


Lesenswert?

> Um nochmal auf die ursprüngliche Fragestellung zurückzukommen, müsste es
> doch möglich sein in den Quelltexten von malloc/free zu sehen wieviel
> Platz überhaupt für den Heap vorgesehen ist. Vermutlich ist das ein
> define/const, die man auswerten kann.
ich weiss zwar nicht wie es auf µC ist, aber normalerweise geht das 
überhaupt nicht, weil der speicher auch fragmentiert sein kann.
z.b. ist es dann möglich 2 mal 10byte speicher zu bekommen aber es ist 
nicht möglich 20byte zu bekommen. Damit hilft die die Angabe es sind 
noch 20byte frei überhaupt nicht.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Mario Hirth schrieb:

> Da die einzelnen Strings zwischen 2 Zeichen (z.B. Ja) und vielen Zeichen
> ("Ein Fehler ist Aufgetreten, Rufen Sie den Support") schwanken kann,
> ist es nicht möglich Speicherplatz fix zu vergeben, sodass alle
> Möglichkeiten enthalten sind. Ich möchte also zwischen "wenigen langen
> Texten" und "vielen kurzen Texten" im Betrieb wählen können womit mir
> nur malloc einfällt.
>
> Wenn es alternativen gibt, bitte her damit.
>
> Wäre es denkbar einfach ein laaaaaanges char array zu definieren (das
> fast den gesamten speicherbereich ausfüllt) und ich überlege mir ein
> Schema wie ich rauskriege wo ein listenelement anfängt und wo ein
> anderes aufhört?
> Machbar wäre das natürlich, aber ist malloc da nicht die elegantere
> variante?

Selbst wenn malloc() nicht NULL zurückliefert, kannst du nicht sicher 
sein, daß deine Anwendung aufgrund von Speicherkorruption nicht 
abstürzt. Das liegt daran, weil sich Heap und Stapel einen 
Speicherbereich teilen und nix voneinander wissen.

http://www.rn-wissen.de/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc

Falls die Anwendung die Strings in einer Init-Phase schickt und danach 
nie mehr verändert, könnten sie mit alloca auf dem Stack angelegt 
werden.

http://www.rn-wissen.de/index.php/Avr-gcc/Interna#Dynamische_Speicherallokierung

Damit wäre das Problem der Speicherüberlaufs reduziert auf eine 
Unbekannte, nämlich den nach unten wachsenden Stapel, zu dessen 
Größenabfrage Tipps im ersten Link sind. Zudem ist alloca effizienter 
als malloc, jedoch nicht so allgemein einsatzbar, da es nur lokal 
arbeitet.

Johann

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du wirst Dir Probleme einhandeln, wenn Du malloc/free mit 
unterschiedlichen Blockgrößen verwendest, da das zur Fragmentierung des 
Heaps führen kann.
Mal angenommen, Du hast 120 Bytes Speicherplatz und forderst dann drei 
Pakete a 30 Bytes an. Bleiben also noch 30 Bytes unbenutzt.

Nun gibst Du das erste der drei 30-Byte-Pakete frei. Also sind 60 Bytes 
frei. Und dann versuchst Du, ein 40-Byte-Paket anzufordern.

Tja, das geht nicht, obwohl doch viel mehr Speicher frei ist.

Auf Systemen mit virtueller Speicherverwaltung per MMU macht das nichts, 
weil der Speicher problemlos in MMU-Blöcken herumgeschoben werden kann, 
aber auf einem µC sieht das schon anders aus.

von Mario H. (rocko)


Lesenswert?

Hallo,
Danke für die vielen Tipps.
Ich muss noch einmal drüber schlafen (erst muss ich den UART fehlerfrei 
hinkriegen, der stürtzt dauernd ab) aber eure ideen laufen in richtung 
statisch adressieren und selbst verwalten hinaus.
Also einfach ein laanges array statisch anlegen und einsprungstellen 
definieren (wo die nächste Liste anfängt (primitiv hashen sozusagen)).

Da ich ja keinen speicherplatz wieder freigeben kann/muss um andere 
Variablen zu speichern (ich kann das array ja sowieso bei bedarf für was 
anderes nehmen, muss ich hald vorsichtig ein wenig rumcasten!) scheint 
mir malloc nach euren Kommentaren nicht geeignet (zumindest 
überqualifiziert und mit recourcenverlust verbunden).

Für die Anwendung passts auch besser, auf dem uc hab ich eh lange genug 
Zeit. (Wenn der uc eine halbe sekunde braucht bis er weis was 
Listeneintrag 5 der 2. Liste ist, ists auch wurscht, also massig zeit 
zum rumsuchen!).

Da is es besser ich spare Speicher und halte mich von malloc fern.


Wenn jetzt niemand schreit dass ich auf dem Holzweg bin,
dann darf ich mich noch ganz herzlich für die Tipps bedanken.

Hab auch wieder einiges dabei gelernt!

Vielen Dank...

Rocko

von Peter D. (peda)


Lesenswert?

Mario Hirth schrieb:
> Ich muss noch einmal drüber schlafen (erst muss ich den UART fehlerfrei
> hinkriegen, der stürtzt dauernd ab)

Hier mal ein rundum sorglos UART Treiber:

Beitrag "AVR-GCC: UART mit FIFO"


Peter

von hmm... (Gast)


Lesenswert?

Ein UART ist nicht schwierig aber nur mit statischem speicher. Ein 
64byte ringbuffer sollte passen.

von Mario H. (rocko)


Lesenswert?

Hi Leute,

danke für die UART Tipps, hat sich aber durch Zufall grad recht schnell 
geklärt: Programmierer abhängen, dann geht's.

Hab ja glatt übersehen dass der ISP die UART Pins verwendet, da kann ja 
nix gehen!
Mist, bei der RS232 Implementierung hab ich's nicht übersehen, jetzt 
schreibe ich aber grade um für RS485 und hab einfach drauf vergessen!

Trotzdem danke!

von Peter D. (peda)


Lesenswert?

Mario Hirth schrieb:
> Hab ja glatt übersehen dass der ISP die UART Pins verwendet, da kann ja
> nix gehen!

Dann ist es aber doch kein ATmega2560.

Die Ausnahme mit dem Konflikt UART/ISP betrifft nur 64-polige AVRs.
Alle anderen AVRs nehmen das SPI als ISP.


Peter

von Mario H. (rocko)


Lesenswert?

Aha,
die RS232 Implementierung habe ich tatsächlich auf einem Atmega-2561 er 
gemacht. Wird aber trotzdem vom ISP irgendwie gestort.

Macht nix, ich muss mir eh erst einen Paket Sniffer basteln, und 
vielleicht sollte ich auch die Leitungen mal abschließen ;-)

Dürfte jedenfalls ein Hardware/Störungs Problem sein. Werd ich schon 
dahinter kommen, da mach ich mir keine Sorgen!

lg Rocko

von Hrm (Gast)


Lesenswert?

@ Peter
>ich weiss zwar nicht wie es auf µC ist, aber normalerweise geht das
>überhaupt nicht, weil der speicher auch fragmentiert sein kann.
>z.b. ist es dann möglich 2 mal 10byte speicher zu bekommen aber es ist
>nicht möglich 20byte zu bekommen. Damit hilft die die Angabe es sind
>noch 20byte frei überhaupt nicht.
Du hast vollkommen recht. Das war mir gerade nicht gewärtig. Nutze 
einfach malloc nicht auf nem uC und auf dem PC muss man sich schon Mühe 
geben damit es kracht, wobei ich da oft auch feste Bereiche selber 
verwalte.

von Mario H. (rocko)


Lesenswert?

Johann L. schrieb:

>
> Selbst wenn malloc() nicht NULL zurückliefert, kannst du nicht sicher
> sein, daß deine Anwendung aufgrund von Speicherkorruption nicht
> abstürzt. Das liegt daran, weil sich Heap und Stapel einen
> Speicherbereich teilen und nix voneinander wissen.
> ...
> http://www.rn-wissen.de/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc
> ...
> Damit wäre das Problem der Speicherüberlaufs reduziert auf eine
> Unbekannte, nämlich den nach unten wachsenden Stapel, zu dessen
> Größenabfrage Tipps im ersten Link sind. Zudem ist alloca effizienter
> als malloc, jedoch nicht so allgemein einsatzbar, da es nur lokal
> arbeitet.
>
> Johann

Hallo Allerseits,
Ich muss das Speicherplatz abfragen hier nochmals aufgreifen, da mir 
mittlerweile der Speicher knapp wird. Es ist zwar noch genug zum 
optimieren da, ich möchte aber nicht unnötig Zeit investieren bzw. auf 
Komfort durch kürzere Textmessages etc... verzichten nur weil ich mich 
nicht traue das letzt kb noch anzufangen...

im geposteten link ist ein fertiger Code enthalten für die Abfrage des 
benutzen Stacks (auch wenn bis zum Zeitpunkt der Abfrage der Stack 
wieder kleiner wurde).

Der Code geht aber von der Kenntniss des heap-Endes aus, das man mit 
einem Linkerscript als Makro in den Code bekommen soll.

Ich hab bereits gegoogelt und im Forum geschmökert, aber ohne auch nur 
einen Ansatz zu finden.

Kann mir da wer auf die Sprünge helfen?

Ziel der Aktion ist im Programm eine Konstante (eigentlich ein Pointer) 
__heapstart zur Verfügung zu haben, die den Beginn des freien 
Speicherplazes anzeigt. (malloc nicht verwenden vorausgesetzt ;-)

vielen Dank


Rocko

ps.: speziellen Dank an Johann L. für den Link, hat mir einiges erklärt!

von Michael M. (technikus)


Lesenswert?

Wenn Du kein malloc verwendest, bieten die Code-Beispiele von 
http://www.rn-wissen.de/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc 
eine schöne Methode, den minimal verfügbaren Speicher festzustellen.

Servus
Michael

von Mario H. (rocko)


Lesenswert?

Hallo Michael

genau das hab ich mir ja angesehen, hab aber ein Kommentar falsch 
interpretiert, da steht:
// __heap_start is declared in the linker script

Ich dachte da muss ich das linker skript anpassen damit ich die variable 
__heap_start zur verfügung habe.

Ich habs jetzt einfach im Simulator ausprobiert und es geht!


vielen Dank

lg Rocko

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
Noch kein Account? Hier anmelden.