Hallo zusammen,
bisher habe ich mich nicht so recht an die Speicherverwaltung mit malloc
etc. herangetraut. Aktuell aber habe ich ein Problem bei dem ich
warscheinlich nicht drum rum komme um nicht arg viel Speicher zu
verschwenden.
Folgende Ausgangslage und wie ich das bisher gelöst hätte:
Über die UART Schnittstelle kommen Telegramme herein deren Länge von 8-
270Byte variiert. In der ISR werden die einzelnen Telegrammbytes in ein
Buffer Array gespeichert und nach Telegrammende das gesamte Telegramm in
einen Telegrammbuffer (+ACK an den Absender). In der Hauptroutine werden
diese Telegramme im Telegrammbuffer der Reihe nach abgearbeitet, diese
Abarbeitung kann aber Längere Zeit in Anspuch nehmen daher der Einsatz
eines Bufferspeichers. Wenn der Bufferspeicher voll ist sollen keine
neuen Telegramme mehr Angenommen werden (NACK an den Absender)
Datenstrukur:
Fuktionieren würde das alles so aber da zu über 80% die Telegramme
kürzer als 20Byte sein werden ist der Rest des Telegrambuffers
verschwendeter RAM und daher ist je nach Größe des Arbeitsspeichers die
Anzahl der möglichen gepufferten Telegramme unnötig beschränkt.
Jetzt weiß ich das mit realloc() calloc) etc. dynamisch zur Laufzeit
Speicher reserviert bzw. wieder frei gegeben werden kann. Vorteil wäre
das nur soviel Speicher belegt wird wie die einzelnen Telegramme
tatsächlich brauchen und damit die Anzahl der möglichen gepufferten
Telegramme drastisch steigen würde.
Im Prinzip reserviere ich mir bei Telegrammstart vorsorglich zb. 20Byte
und erweitere bzw. kürze es bei Bedarf entsprechend. (ab Byte 8 weiß ich
die genaue Länge des Datentelegramms) Ist das in einer ISR überhaupt
möglich, günstig (ralloc() Aufrufe)?
Wenn ich den freien Speicher zur Laufzeit auch irgendwie rausfinde
könnte man die Anzahl der möglichen zwischengespeicherten Telegramme je
nach Auslastung variieren.
Da ich damit noch keine Erfahrung habe, frage ich mich ob das
prinzipiell möglich ist oder ob ich mich da auf dem Holzweg befinde?
Wenn möglich wie könnte so etwas aussehen, hat jemand vielleicht schon
was änliches gemacht?
Bin über jede Hilfe dankbar :)
Wie sieht den das Telegramm aus? Du müsstest zuerst die Telegrammlänge
senden, damit Du mit dieser Information den Dynamischen Speicher anlegen
kannst. Kennst Du die Länge vor her nicht -> Worst Case.
Bei der dynamischen Speicherverwaltung ist nicht garantiert, dass immer
genügend Speicher verfügbar ist. Wie willst Du diesen Fall behandeln?
Du schreibst ja, dass Du erst das ganze Telegramm empfängst und danach
dieses verarbeitest. Falls ich es richtig verstanden haben, reicht ein
Buffer mit 270 Byte Länge.
Für den Fall das Empfangen und Verarbeiten parallel geschehen soll,
könntest Du zwei Buffer anlegen. Ist der eine Buffer mit einem
kompletten Telegramm gefüllt, tauschst Du die Zeiger auf die Buffer. Vor
dem tausch muss die Verarbeitung natürlich auch abgeschlossen sein. Der
Buffer der gerade noch Empfangsbuffer war, wird nun Verarbeitungsbuffer
und der Verarbeitungsbuffer wird zum Empfangsbuffer.
Welchen MC verwendest Du? Wie viel RAM hast Du zur Verfügung?
Grüsse
> Das wäre ja genau die Variante die Speichertechnisch nicht gerade> effektiv ist!
Wieso ? Du schreibst immer in diesen Puffer rein und merkst dir die
Aktuelle Position in einem Zähler. Nachdem ein Telegram komplett ist
merkst du dir die position in einem array (entweder Index oder Pointer)
für den Anfang des neuen Telegramms und sendest ein ACK. Du hast einen
weiteren Zähler für den, der die Telgramme verarbeitet und die pointer
im Array invalidiert als abgearbeitet usw.
> Jetzt weiß ich das mit realloc() calloc) etc. dynamisch zur Laufzeit> Speicher reserviert bzw. wieder frei gegeben werden kann. Vorteil wäre> das nur soviel Speicher belegt wird wie die einzelnen Telegramme> tatsächlich brauchen und damit die Anzahl der möglichen gepufferten> Telegramme drastisch steigen würde.
Nachteil ist, dass du keinerlei Garantie hast, dass du diesen Speicher
auch kriegst.
Du kannst rein rechnerisch 500 Bytes frei haben und trotzdem geht eine
Allokierung von 40 Bytes schief.
Warum? Weil es möglich ist, dass du zwar in Summe 500 Bytes hast, aber
keine einzige zusammenhängende freie Lücke im Speicher, die 40 Bytes
umfasst. Du hast zb 50 Stück jeweils 10 Byte große Speicherbereiche im
Speicher frei.
Wenn dieser Speicher, um den es hier geht, der einzige ist, den du
dynamisch verwalten möchtest, dann lass es so. Besser du hast
garantierte Zahlen als du hast 'möglicherweise', 'vielleicht' den Platz
um 3 oder 4 zusätzliche Telegramme 'unter Umstände' 'eventuell'
speichern zu können, ehe du den Sender bremsen musst.
@ Horst (Gast)
>Jetzt weiß ich das mit realloc() calloc) etc. dynamisch zur Laufzeit>Speicher reserviert bzw. wieder frei gegeben werden kann. Vorteil wäre>das nur soviel Speicher belegt wird wie die einzelnen Telegramme>tatsächlich brauchen und damit die Anzahl der möglichen gepufferten>Telegramme drastisch steigen würde.
Und was machst du mit dem "gesparten" RAM? Auf so einem kleinen
Mikrocontroller mit einem FESTEN Programm fast gar nichts. Denn es gibt
keine unvohersehbaren Anwendungen, die plötzlich gestartet werden und
viel RAM brauchen könnten. Deine Anwendung ist klein, fest und
übersichtlich.
>prinzipiell möglich ist
Ja, aber
> oder ob ich mich da auf dem Holzweg befinde?
Auch ja ;-) Dein Malloc brungt nur Stress und Probleme und keinen
Vorteil. Einzig und allein dann, wenn du zwischenzeitlich für andere
Funktionen kurzzeitig viel RAM brauchst. Dann darf aber während dieser
Zeit GARANTIERT kein langes Telegramm ankommen.
> In der Hauptroutine werden diese Telegramme im Telegrammbuffer> der Reihe nach abgearbeitet, diese Abarbeitung kann aber Längere> Zeit in Anspuch nehmen
Arbeite lieber daran, diese Abarbeitung zu beschleunigen.
Im Moment hast du deinen Buffer auf 10 Telegramme eingestellt. Wie oft
kommt es vor, dass diese 10 Telegramme nicht ausreichen? Wenn du die
Abarbeitung um ein paar Prozent beschleunigen kannst, wie oft reichen
<dann> diese 10 Telegramme nicht mehr aus?
Hast du das schon rausgemessen und festgestellt?
Dynamische Speicherallokierung hat nicht nur das Problem der
Fragmentierung (wie in meinem letzten Post angesprochen), sondern auch
das Problem, dass sie relativ aufwändig ist. D.h. durch den Einsatz der
dynamischen Allokierung (das muss ja auch verwaltet werden), zwickst du
dir zusätzliche Laufzeit auf, die als Folge jetzt wieder dazu führen
kann, dass die Abarbeitung der Telegramme langsamer wird und wo vorher
10 Buffer-Slots gereicht haben, reichen jetzt 11 oder 12 nicht mehr.
Was man vielleicht in Erwägung ziehen könnte, das ist eine Mischung aus
'Short-Telegram' und 'Long-Telegram'. Dann hast du zb 30
Short-Telegramme vorrätig und nur 5 Long-Telegramme.
In den Telegrammbuffer kommt anstelle des Struktur-Arrays ein Pointer
Array rein, zusammen mit einer Kennung, auf welchen Typ von Telegram der
Pointer zeigt.
Aber: Das wird vergleichsweise immer noch aufwändig. Denn jetzt brauchst
du natürlich getrennte Verwaltungen dafür, welche Short- bzw.
Long-Telegramme gerade noch frei sind. Aus dem jeweiligen Pool muss
eines 'beschlagnahmt' werden und sein Pointer in den Telegrammbuffer
eingetragen werden. Selbiges dann natürlich in umgekehrter Richtung,
wenn das Telegramm nicht mehr gebraucht wird.
Zumindest das Problem der Speicherfragmentierung kriegt man so in den
Griff. Aber die Laufzeitverzögerung, und damit die Tatsache, dass du
u.U. auf einmal mehr Telegramme buffern musst, dieses 'Problem'
existiert immer noch.
Daher: als erstes mal messen, wie oft eigentlich dieser Fall auftritt,
dass die 10 vorhandenen Telegramme nicht ausreichen. Wenn der so gut wie
nie auftritt, dann optimierst du etwas, was du überhaupt nicht
optimieren brauchst.
> Fuktionieren würde das alles so aber da zu über> 80% die Telegramme kürzer als 20Byte sein werden
Darauf kommts nicht an
> ist der Rest des Telegrambuffers verschwendeter RAM
für nicht benutztes SRAM kriegst du von Atmel kein Geld zurück. Und dem
µC ist es auch egal, ob du jetzt SRAM Zellen benutzt oder nicht benutzt.
Entscheidend ist einzig und alleine, inwiefern dir diese Limitierung auf
10 gebufferte Telegramme tatsächlich den Datenfluss behindert.
Markus M. schrieb:> Wie sieht den das Telegramm aus? Du müsstest zuerst die Telegrammlänge> senden, damit Du mit dieser Information den Dynamischen Speicher anlegen
Kenne die Länge des Telegramms leider erst ab Byte 8, dort ist diese
Information vorhanden, daran kann ich auch nichts ändern. Darum würde
ich ja einfach Hausnummer 20 Byte allocieren und danach auf die exakte
Länge anpassen (wenn ein zusammenhängender Block mit der neuen
Byteanzahl nicht auf der aktuellen Position verfügbar ist muss realloc()
die paar bytes zuvor umkopieren oder? deshalb die Frage wegen ISR!)
Markus M. schrieb:> Bei der dynamischen Speicherverwaltung ist nicht garantiert, dass immer> genügend Speicher verfügbar ist. Wie willst Du diesen Fall behandeln?
dann wird das Telegramm nicht angenommen (NACK) der Sender versucht es
später wieder und dann ist vielleicht wieder speicher frei....
Markus M. schrieb:> Du schreibst ja, dass Du erst das ganze Telegramm empfängst und danach> dieses verarbeitest. Falls ich es richtig verstanden haben, reicht ein> Buffer mit 270 Byte Länge.
Nein, im worst case könnten einige Telegramme in der Warteschlage zur
Bearbeitung stehen, wenn ich dafür einen Buffer mit fixen 270Byte Länge
verwende könnten zb. bei 10 Telegrammen 2,7kB flögen gehen obwohl die 10
Telegramme evtl. nur 10x20Byte also 200Byte bräuchten.....
Markus M. schrieb:> Für den Fall das Empfangen und Verarbeiten parallel geschehen soll
natürlich, aber die Verarbeitung kann eben längere Zeit dauern und es
kommen dennoch neue Telegramme daher. Je effektiver ich den Speicher
verwalte desto mehr Telegramme kann ich in dieser Zeit zwischenspeichern
und danach verarbeiten!
Markus M. schrieb:>Welchen MC verwendest Du? Wie viel RAM hast Du zur Verfügung?
Keinen konkreten, wird auf mehreren Controllern laufen und daher wird
mal mehr und mal weniger Ram zur verfügung Stehen
ui schon wieder soviele Antworten, komm ich ja gar nicht nach :)
Das es nicht leicht ist verstehe ich, daher habe ich es auch immer
vermieden. Dachte jetzt nur weil es auf unterschiedlichen Controllern
laufen wird könnte man da etwas optimieren.
Kontkret läuft es noch nicht daher kann ich noch nicht wirklich sagen
wieviele Telegramme Platz haben müssten, wird aber auch sehr
unterschiedlich sein weil die Aufgesetzten Applicationen sehr
unteschiedliche aufgaben erfüllen.
Sind eben erst Grundsätzliche Überlegungen aber danke schon mal für die
rege Beteiligung :)
Da hast Du aber eine ganze Menge Unbekannte! Es ist keine schlechte Idee
diese im voraus zu minimieren.
Ein intelligentes Speichermangement kostet auch Speicher. Ob Du etwas
gewinnst gegenüber einer statischen Speichernutzung wirst du wohl am
Ende der Arbeit sehen. Aber lohnt sich der Aufwand? Nicht das KISS
Prinzip aus den Augen verlieren.
Weiter oben wird ja schon die Speicherfragmentierung angesprochen. Auf
einem MC ist es besser die Kontrolle selbst zu übernehmen auch über den
Speicher.
Grüsse
Ich hab das jetzt mal so runtergeschrieben. Bis auf Tippfehler sollte da
nichts mehr drinnen sein. Die Allokierung und Freigabe ist einfach eine
verlinkte Liste von Telegrammen, die am hinteren Ende wächst, während
die Hauptschleife sich ein Telegram nach dem anderen vom vorderen Ende
holt, abarbeitet und freigibt.
Horst schrieb:> Kontkret läuft es noch nicht daher kann ich noch nicht wirklich sagen> wieviele Telegramme Platz haben müssten, wird aber auch sehr> unterschiedlich sein weil die Aufgesetzten Applicationen sehr> unteschiedliche aufgaben erfüllen.
Dann solltest du das erst mal mit der einfachsten Implementierung in
Erfahrung bringen.
Man 'optimiert' nicht etwas, von dem man nicht weiß, ob es überhaupt ein
Problem ist.
Ich würde einen möglichst großen Ringpuffer für alle empfangenen
Telegramme statisch anlegen. Die einzelnen Telegramme werden darin
sequenziell abgelegt und jeweils durch ein spezielles Endezeichen (bspw.
'\0') abgeschlossen. Das funktioniert, weil die Verarbeitungsroutine die
Telegramme ebenfalls sequenziell liest.
In diesem Ringpuffer passen je nach Bedarf viele kleine oder wenige
große Telegramme hinein, und es wird im Gegensatz zur malloc-Lösung bis
auf die Endezei- chen kein Platz für Verwaltungsinformation benötigt.
Und es gibt keinerlei Probleme mit Speicherfragmentierung, die du evtl.
bei der Verwendung von malloc hättest.
Und rechenzeiteffizient ist diese Methoden noch dazu.
Um die Größe dieses Ringpuffers festzulegen, musst du nachschauen,
wieviel RAM alle anderen statischen Variablen zusammen benötigen (das
steht im Map-File des Linkers oder kann bei den GNU-Tools mit dem
size-Befehl ermittelt werden). Zusätzlich musst du den Stackverbrauch
abschätzen oder durch Testläufe herausfinden. Im verbleibenden Speicher
kann sich dann der Ringpuffer breit machen.
Ob der Puffer voll ist, kannst du wie üblich daran erkennen, dass der
Schreibindex den Leseindex einholt. Ist dies der Fall, schickts du das
NACK und entfernst das letzte (nicht vollständige) Telegramm aus dem
Puffer, indem zu den Schreibindex auf den Anfang dieses Telegramms
zurücksetzt. Das geht am einfachsten dadurch, dass du noch einen dritten
Index einführst, der immer auf den Anfang des aktuell empfangenen
Telegramm zeigt.
Hmm schrieb:>>Das wäre ja genau die Variante die Speichertechnisch nicht gerade>>effektiv ist!>> Mich würde mal interessieren warum Horst dieser Meinung ist.
Naja, wenn er für jedes Telegramm 270 Bytes reserviert, aber viele
Telegramme nur 20 Bytes lang sind, bleiben für jedes dieser Telegramme
250 Bytes ungenutzt.
>Naja, wenn er für jedes Telegramm 270 Bytes reserviert, aber viele>Telegramme nur 20 Bytes lang sind, bleiben für jedes dieser Telegramme>250 Bytes ungenutzt.
Wenn aber im Worst-Case soviele Telegramme auftreten können, ist der
Ringbuffer immer noch kleiner als malloc/free und das nicht genutzte RAM
kann er ja sowieso nicht anderweitig benutzen, wenn man voraussetzt das
der Worst-Case jederzeit auftreten kann.
Überzeugt mich noch nicht davon, warum man die Ringpuffer-Lösung
ablehnen sollte.
Danke an alles bisherigen Antworten, habe jetzt einigen neue Sichtweisen
aufgezeigt bekommen, besonders die Idee von Yalu X. scheint mir ein
Interessanter Weg zu sein da zwar der reservierte Speicher fix ist,
dieser aber optimal ausgenutzt werden kann.
Hmm schrieb:> Wenn aber im Worst-Case soviele Telegramme auftreten können, ist der> Ringbuffer immer noch kleiner als malloc/free und das nicht genutzte RAM> kann er ja sowieso nicht anderweitig benutzen,
Doch, bei richtiger Speicherorganisation kann der Puffer bei kleinen
Telegrammen eine größere Anzahl davon aufnehmen, was die Häufigkeit der
Pufferüberläufe und der dadurch ausgelösten Sendewiederholungen
reduziert.
@Horst:
Mir ist gerade noch eingefallen, dass du in meinem Vorschlag von oben
die Endezeichen nach den Telegrammen auch weglassen kannst, da die
jeweilige Länge ja bereits in Telegrammdaten enthalten ist. Damit hast
du praktisch keine Speicheroverhead im Puffer.
Horst schrieb:> Da ich damit noch keine Erfahrung habe, frage ich mich ob das> prinzipiell möglich ist oder ob ich mich da auf dem Holzweg befinde?
Ja, ist es.
Lass dich mal nicht von den Unkenrufern hier entmutigen: solange
dein Problem wirklich stochastisch ist (also die langen und kurzen
Telegramme zufällig verteilt reingeflogen kommen) und solange du
gegenüber dem zu erwartenden maximalen Füllstand immer noch etwas
Reserve hast im freien RAM, wird das ganz hervorragend funktionieren.
Ich sehe keinen wirklichen Grund, warum man ein mittlerweile recht
gut debuggtes malloc() an dieser Stelle durch einen eigenen, am
Ende auch bloß nicht effektiveren Ringpuffer oder dergleichen
ersetzen müsste. Selbstverständlich: es liegt in der Natur der
Sache, dass dir der Speicher ausgehen kann und du keine Telegramme
mehr annehmen kannst. Aber mit dieser Situation musst du angesichts
der Tatsache, dass die Summe aller Zuflüsse vorübergehend höher sein
kann als die Summe der Verarbeitungsleistung/Abflüsse, ohnehin
umgehen können, egal ob du nun allen RAM statisch belegst, dir
irgendeine eigene Speicherverwaltung schreibst (die sehr wahrscheinlich
erstmal neue Bugs hat ;) oder gleich malloc() nimmst.
realloc() arbeitet auch so, wie du es erwarten würdest: es erweitert
den Speicherbereich in-place, sofern möglich, ansonsten belegt es
einen neuen und kopiert um. Außerdem defragmentiert free() natürlich
ordnungsgemäß alles, was sich defragmentieren lässt (sofern es
vernünftig implementiert ist).
Nein, die Menge an freiem Heap kann man nicht ohne weiteres ermitteln.
Aber wie Karl-Heinz dir schon schrieb, würde dir eine solche Zahl
nichts nützen, da davon allein nicht klar ist, welche freien Blöcke
welcher Größe gerade existieren.
Benutzt du einen AVR oder was anderes? In der avr-libc könntest du
über:
1
externchar*__brkval;/* first location not yet allocated */
den “break value” abfragen, also die erste freie Adresse, die noch
nicht durch den Heap alloziert worden ist. Wenn du diese mit dem Wert
des Stackpointers vergleichst, hast du ein ungefähres Maß für den
Speicher, der oberhalb des Heap derzeit komplett ungenutzt ist. (Der
Zeiger wird in der avr-libc mittlerweile auch wieder dekrementiert,
wenn free() einen zusammenhängenden Bereich am oberen Ende des Heaps
freigibt.) Davon nicht erfasst ist natürlich die sogenannte
freelist, eine verkettete Liste aller „Löcher“, die zwar
mittlerweile wieder freigegeben worden sind, aber irgendwo in der
Mitte des Heaps liegen.
Disclaimer: Es handelt sich hierbei selbstverständlich um meine völlig
voreingenommene eigene Meinung. Die Voreingenommenheit resultiert
einfach daraus, dass die malloc()-Implementierung der avr-libc zu
großen Teilen auf meinem Mist gewachsen ist. ;-) Das war damals
gewissermaßen mein „Einstand“ in die Opensource-Welt für den AVR.
Yalu X. schrieb:> Mir ist gerade noch eingefallen, dass du in meinem Vorschlag von oben> die Endezeichen nach den Telegrammen auch weglassen kannst, da die> jeweilige Länge ja bereits in Telegrammdaten enthalten ist. Damit hast> du praktisch keine Speicheroverhead im Puffer.
Ja das ist mir auch schon aufgefallen :)
Nachteil bei dieser Methode ist allerdings das ich den Telegrammaufbau
2x Erkennen muss... 1x in der ISR um Zeitgerecht das ACK zu senden bei
richtiger Adressierung und dann 1x in der Auswertefunktion....
Danke Jörg für deine voreingenommene Meinung :) in meiner Unwissenheit
über die Details und dem Willen neues zu lernen bin ich eben auf diese
Fährte aufmerksam geworden.... und auch weil in Objektorientierten
Sprachen wie zb C++ über new xy eigentlich auch nichts anderes gemacht
wird als neuer Speicher allociert der vorher nicht statisch reserviert
wurde und da hinterfragt ja auch keiner oder lieg ich da jetzt falsch?
Den ersten Stack werde ich wohl auf einem CortexM0 (LPC1227) realisieren
aber wie oben schon erwähnt soll er möglichst flexibel und effektiv sein
um auch auf kleine 8bittern ein maximum rauszuholen.....
Das mit dem freien Heap hab ich verstanden allerdings melded realloc ja
wenn er keinen Platz für das nächste Telegramm finden würde, damit geht
man im Extremfall aber bis an die Genzen des Ram.... wie hällt man sich
hier die von dir geforderte Reserve im Ram Frei?
Jörg Wunsch schrieb:> Ich sehe keinen wirklichen Grund, warum man ein mittlerweile recht> gut debuggtes malloc() an dieser Stelle durch einen eigenen, am> Ende auch bloß nicht effektiveren Ringpuffer oder dergleichen> ersetzen müsste.
Nichts läge mir ferner, als dein malloc in irgendeiner Form schlecht
zu reden. Aber in diesem Fall braucht man doch ohnehin eine FIFO-Daten-
struktur (implementiert als Ringpuffer auf einem Array, als verkettete
Liste oder wie auch immer) für einzelne Zeichen oder für ganze Telegram-
me, so dass Verwendung von malloc hier keinerlei Vereinfachung bringt.
>Hmm schrieb:>> Wenn aber im Worst-Case soviele Telegramme auftreten können, ist der>> Ringbuffer immer noch kleiner als malloc/free und das nicht genutzte RAM>> kann er ja sowieso nicht anderweitig benutzen,
Yalu schrieb:
>Doch, bei richtiger Speicherorganisation kann der Puffer bei kleinen>Telegrammen eine größere Anzahl davon aufnehmen, was die Häufigkeit der>Pufferüberläufe und der dadurch ausgelösten Sendewiederholungen>reduziert.
Merkwürdig. Ich sehe da den Widerspruch nicht. Vielleicht kann ich ja
was lernen. Warum schreibst Du "Doch"? Worauf bezieht es sich genau?
1. Ein Ringpuffer braucht bei gleicher Nutzdatenmenge weniger
Verwaltungsinformation als malloc/free. Sind wir uns da noch einig?
2. Das "nicht genutzte RAM", dass ich meinte, tritt dadurch auf, das zu
manchen Zeiten weniger als maximal mögliche Telegramme aufkommen bzw.
eher viele kurze als viele lange. Wenn aber der Worst-Case auch noch
gehen soll, dann bleibt dadurch eben manchmal RAM frei. Das kann aber
nicht anders genutzt werden, da es eben im Worst-Case doch genutzt
werden wird. Der Ringbuffer ist da schon die optimale Organisation, oder
meinst Du nicht? Wenn wir uns bei Punkt 1 einig sind, dann folgt doch
daraus, das die Ringbufferlösung mehr Telegramme aufnehmen kann also
malloc/free.
Horst schrieb:> Das mit dem freien Heap hab ich verstanden allerdings melded realloc ja> wenn er keinen Platz für das nächste Telegramm finden würde, damit geht> man im Extremfall aber bis an die Genzen des Ram.... wie hällt man sich> hier die von dir geforderte Reserve im Ram Frei?
Nein, die hält man sich nicht frei, sondern die muss insgesamt im
Mittel frei bleiben, damit die Stochastik funktioniert. Das ist
wie beim Ethernet: bis zu 95 % Auslastung hat man trotz CSMA/CD
gute Datenraten. Wenn man die letzten 5 % der theoretisch möglichen
Datenrate jedoch ausnutzen will, bricht alles ein, dann geht die
Rate in den Keller.
Keine Ahnung, was für eine Bibliothek du bei deinem LPC benutzt. Wenn
es die newlib ist (die üblicherweise mit dem GCC genutzt wird), dann
lieferst du dort deine eigene Implementierung für _sbrk(), und damit
solltest du zumindest den höchsten belegten RAM auch wieder wissen.
Yalu X. schrieb:> Aber in diesem Fall braucht man doch ohnehin eine FIFO-Daten-> struktur (implementiert als Ringpuffer auf einem Array, als verkettete> Liste oder wie auch immer) für einzelne Zeichen oder für ganze Telegram-> me, so dass Verwendung von malloc hier keinerlei Vereinfachung bringt.
Vereinfachung nicht, aber man muss halt nichts statisch vorbelegen
und kommt daher dynamisch an die Grenzen des verfügbaren RAMs heran,
da die üblichen Implementierungen (auch bei ARM) bei jeder neuen
Anforderung nachschauen, ob sie jetzt eine Stack-Heap-Kollision
riskieren oder nicht.
Fertig implementierte Algorithmen für Queues oder Listen auf Basis
von malloc() sollte man ja ausreichend finden, mit denen man den
FIFO implementieren kann.
@Hmm:
Ich dachte, das hier würde sich auf die Ursprungslösung von Horst
beziehen, bei der mehrere 270 Bytes große Puffer in einem Ring
organisiert sind:
Hmm schrieb:>>Das wäre ja genau die Variante die Speichertechnisch nicht gerade>>effektiv ist!>> Mich würde mal interessieren warum Horst dieser Meinung ist.
Ist ein Telegramm kürzer als 270 Bytes, kann der ungenutzte Teil des
entsprechenden Puffers nicht für andere Telegramme genutzt werden.
Ich sehe aber jetzt gerade, dass sich Horsts und dein Beitrag auf das
hier beziehen:
thomas s. schrieb:> einen circularbuffer nehmen mit 270byte größe und die telegramme> herausnehmen und verarbeiten
Diesen Vorschlag habe ich aber nicht verstanden, da ein einzelner Puffer
mit nur 270 Bytes Größe gerade Platz für ein einzelnes "Full-Size"-Tele-
gramm bietet, Horst aber möglichst viele Telegramme puffern will.
Jörg Wunsch schrieb:> Fertig implementierte Algorithmen für Queues oder Listen auf Basis> von malloc() sollte man ja ausreichend finden, mit denen man den> FIFO implementieren kann.
Kannst du mir hier noch auf die Sprünge helfen, wo findet man sowas?
@Hmm
Ich glaube ihr redet aneinander vorbei, die Variante mit EINEM
Ringbuffer mit maximaler Größe der alle Telegramme Byteweise und nicht
aufgesplittet enthällt ist am Speichereffektivsten, die Variante mit
einem Ringbuffer der die aufgesplitteten Telegrammbuffer mit der
statischen Größe von 270Byte enthält ist nicht sehr effektiv!
Yalu X. schrieb:> thomas s. schrieb:>> einen circularbuffer nehmen mit 270byte größe und die telegramme>> herausnehmen und verarbeiten>> Diesen Vorschlag habe ich aber nicht verstanden, da ein einzelner Puffer> mit nur 270 Bytes Größe gerade Platz für ein einzelnes "Full-Size"-Tele-> gramm bietet, Horst aber möglichst viele Telegramme puffern will.
Ja genau dadurch hab ich das auch erst "Falsch" verstanden.....
Jörg Wunsch schrieb:> Ich sehe keinen wirklichen Grund, warum man ein mittlerweile recht> gut debuggtes malloc() an dieser Stelle durch einen eigenen, am> Ende auch bloß nicht effektiveren Ringpuffer oder dergleichen> ersetzen müsste.
Jörg, du schreibst mal wieder Unfug. Denk doch mal nach!
Diese ominösen Telegramme bestehen aus Zeichen, die per UART
nacheinander hereingerauscht kommen, wahrscheinlich per Interrupt oder
DMA. Sowas fängt man am besten erst mal mit einem Ringpuffer auf, aus
dem man asynchron zum Empfang ausliest und die Zeichen solange in den
Bearbeitungspuffer stopft, bis so ein ominöses Telegramm komplett ist
und bearbeitet werden kann. Für die dafür benötigte Zeit braucht man den
Ringpuffer unbedingt und er muß so groß sein wie die benötigte
Verarbeitungszeit relativ zur Baudrate.
Was willst du an dieser Stelle bloß mit irgendwelchen alloziierten
Blöcken, die wann auch immer wieder freigegeben werden müssen. Ein
Ringpuffer ist die allereffizienteste Methode, um Daten
zwischenzuspeichern. Glaub's mir einfach.
Und was soll der TO zwischen 2 "Telegrammen" mit dem RAM anfangen? Mit
irgendetwas belegen und damit blockieren? Wir sind doch auf nem uC und
haben kein Swapfile.
W.S.
Der Ringpuffer ist niemals fragmentiert. Ungünstig verwendete
malloc/free Aufrufe führen jedoch zu fragmentiertem Speicher. Und dann
bist Du aufgeschmissen, dann hilft nur noch ein Reset.
W.S. hat aber Recht.
Möchtest Du fachlich beraten werden, oder über Höflichkeit diskutieren?
In diesem Forum sollte es um fachliche Themen gehen.
Dass hier oft unhöflich formuliert wird, will ich ja gar nicht
abstreiten. Aber mal ehrlich: Wer mit anderen Menschen richtig gut
kommunizieren kann hat andere Hobbies als wir, nicht wahr?
@ Stefan Frings (stefanfrings_de)
>W.S. hat aber Recht.
Der Ton macht die Musik.
>Möchtest Du fachlich beraten werden, oder über Höflichkeit diskutieren?>In diesem Forum sollte es um fachliche Themen gehen.
Das bedingt aber ein Minimum an Höflichkeit. Siehe Netiquette.
Stefan Frings (stefanfrings_de) schrieb:
> Dass hier oft unhöflich formuliert wird, will ich ja gar nicht> abstreiten. Aber mal ehrlich: Wer mit anderen Menschen richtig gut> kommunizieren kann hat andere Hobbies als wir, nicht wahr?
Nein, ist eben nicht wahr. Sowas wie "mal wieder Unsinn" schreiben
anderen vorzuhalten ist ziemlich respektlos, weil es suggeriert, das
Gegenüber hätte des öfteren keine Ahnung von dem was er von sich gibt.
Ich glaube nicht, dass das auf Jörg zutrifft. Nur unfehlbar ist halt
keiner.
Man hätte auch zum Bleistift schreiben können
- hier irrst du dich
- ich glaube hier liegst du falsch
- das sehe ich ganz anders
usw.
In jeder ernst gemeinten Diskussion fällt man nicht über sich her, denn
man sieht sich auch im virtuellen Leben mehr als einmal.
Stefan Frings schrieb:> W.S. hat aber Recht.>> Möchtest Du fachlich beraten werden, oder über Höflichkeit diskutieren?> In diesem Forum sollte es um fachliche Themen gehen.>> Dass hier oft unhöflich formuliert wird, will ich ja gar nicht> abstreiten. Aber mal ehrlich: Wer mit anderen Menschen richtig gut> kommunizieren kann hat andere Hobbies als wir, nicht wahr?
WTF! Ganz Unrecht hast du nicht...
Stefan Frings schrieb:> W.S. hat aber Recht.
Ganz unabhängig vom Ton: keiner hat vorgeschlagen, dass man einen
per malloc allozierten Puffer in der ISR selbst benutzt.