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
@ 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
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.
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)
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.
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.
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
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
Ein Interrupt buffer ist ganz sicher nicht dynamisch, sondern statisch. Willste im Interupt noch speicher anfordern ?
> 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.
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
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.
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
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
Ein UART ist nicht schwierig aber nur mit statischem speicher. Ein 64byte ringbuffer sollte passen.
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!
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
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
@ 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.
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!
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.