Hallo Für mein aktuelles Projekt (Bilderkennung) komme ich ziemlich an die Grenzen des Speichers meines AVR. Nun wird mein Bild schrittweise analysiert. Ein erster Schritt benötigt eine Anzahl Variabeln (insbesondere Arrays), die später nicht mehr benötigt werden und nur viel Platz wegnehmen. Wie kann man solche Variabeln wieder 'löschen'? Natürlich könnte man sie lokal in einer Funktion definieren, doch leider werden sie auch in ISRs benötigt - es sind also Globalvariabeln. Gruss Michael
Variablen global definieren ist ein schlechter programmierstill. Deklariere die Varialen lokal, und übergebe dann nur einen Pointer auf die Daten, an die sub routine.
Hallo, das würde mich mal auch interessieren. Das mit dem Zeiger ist ja klar, aber wie macht man daß bei einer Interruptroutine ? Die ruft der Prozessor ja selber auf; da kann ich nichts übergeben. Wie kriegt man also eine Verbindung zwischen der Variablen der ISR und der einen lokalen Funktion ? Ich wüßte auf die schnelle keinen praktikablen Weg. Jogibär
Das geht entweder über globale Variablen (wobei man das volatile nicht vergessen darf) oder eben (elegant), indem man die Bearbeitung des Interrupt-Ereignisses an sich nicht in der ISR durchführt, sondern dort nur ein Flag setzt und den Rest im Hauptprogramm (mit lokalen Variablen) macht. Letztere Variante geht natürlich nicht in Fällen, wo es wirklich zeitkritisch ist. Da bleibt einem dann nichts anderes übrig, als global zu denken;-)
> Das mit dem Zeiger ist ja klar, aber wie macht man daß bei > einer Interruptroutine ? > Die ruft der Prozessor ja selber auf; da kann ich nichts übergeben. Ohne eine globale Variable kommst du da nicht weg. Aber die globale Variable kann ein Pointer sein, welcher dann auf die eigentlichen Daten zeigt. struct MeineDaten { int MemberA; int MemberB; char Buffer[200]; unsigned char Image[400]; }; volatile struct MeineDaten* pData; ISR( was_auch_immer_vect ) { if( pData ) { // mach was mit den Daten pData->MemberA = 5; pData->MemberB = 8; } } void foo() { struct MeineDaten Data; // die lokalen Variablen für die ISR bereitstellen pData = &Data; // // so , jetzt kann die ISR arbeiten // // funktion wird verlassen, die ISR wieder von den // Daten abklemmen pData = NULL; } int main() { ..... foo(); while( 1 ); }
> Ein erster Schritt benötigt eine Anzahl Variabeln > (insbesondere Arrays), die später nicht mehr benötigt werden und > nur viel Platz wegnehmen. Genau diese Aufgabenstellung ist die Grundidee hinter einer union: * Ein Programm läuft in Abschnitten ab. * Jeder Abschnitt hat seine eigenen Variablen, die nur in diesem Abschnitt gebraucht werden * Ausserhalb des Abschnittes sind die Variablen nutzlos und liegen nur im Speicher rum * Mittels einer union kann vereinbart werden, dass die Variablen mehrerer Abschnitte quasi übereinandergelegt werden sollen und damit verschiedene Abschnitte immer denselben Speicher benutzen.
Hallo @Karl Heinz: Das hört sich schlüssig an! Werde es dann wohl so machen. Irgendwie dachte ich an die Union, getraute mich aber nicht so recht ;-) Gruss Michael
Hallo Nochmals @Karl Heinz: Hört sich doch nicht so schlüssig an, weil: Eine Union kann ja nur eine Variable pro Zeitpunkt speichern. Wenn ich nun aber in meinem Programm in Abschnitt A zehn einfache Variabeln und fünf längere Arrays habe und in Abschnitt B dann einfach ein längeres Array, dann geht das leider nicht mit Unions. Was haltet ihr von den Funktionen malloc() und free()? Gruss Michael
Wieso sollte das mit Unions nicht gehen? Mit malloc/free wird's auch gehen, aber bringt halt einen gewissen Overhead mit sich.
Kann eine Union denn mehrere Variabeln zum gleichen Zeitpunkt aufnehmen? Hmmm...ich könnte für jeden Programmabschnitt ein struct 'reinpacken! lichtaufgeht Andere Frage: Overhead bei malloc/free? Wenn das alle paar Sekunden geschieht, sollte das doch nicht allzuviel ausmachen?
> Hmmm...ich könnte für jeden Programmabschnitt > ein struct 'reinpacken! *lichtaufgeht* Bingo! > Andere Frage: Overhead bei malloc/free? Wenn das alle paar > Sekunden geschieht, sollte das doch nicht allzuviel ausmachen? Zeitlich vermutlich nicht. Du mußt allerdings auch noch den Speicherverbrauch dazurechnen. Einerseits brauchen die Funktionen selbst wieder Flash, andererseits braucht die Speicherverwaltung noch zusätzliches RAM. Ich weiß ja nicht, um welchen AVR es geht und wieviele Ressourcen noch verfügbar sind. Ehrlich gesagt weiß ich auch nicht, wieviel genau die Speicherverwaltung kostet.
Noch eine Frage: Muss ich irgend etwas spezielles beachten, wenn ich zwischen den verschiedenen Variabeln in der union wechsle? Ausser, dass ich sie vor Gebrauch natürlich wieder mit einem sinnvollen Wert initialisieren muss ;-)
> Ehrlich gesagt weiß ich auch nicht, wieviel genau die > Speicherverwaltung kostet. 10 Bytes statischen RAM-Verbrauch, sowie 2 Bytes RAM zusätzlich pro alloziertem Block, um die Größe dieses Blocks aufzuzeichnen. 1-Byte-Blöcke werden auf 2 Bytes aufgerundet. 542 Bytes Code auf den ,kleinen' Prozessoren (die kein MOVW und MUL haben), 498 Bytes Code auf den großen Prozessoren. Also vielleicht nicht gerade sinnvoll für einen ATtiny2313 :), ab einem ATmega8 kann man drüber nachdenken, ab einem ATmega32 interessiert der Ressourcenverbrauch wohl kaum noch, da bleibt dann nur noch die Frage nach den möglichen Auswirkungen der Speicherfragmentierung. Da es im Thread um Bildverarbeitung geht, wird es wohl nicht gerade der allerkleinste AVR sein.
Hallo Ist ein Mega32 - Hauptproblem ist ganz klar das RAM (2 kB + 32 kB extern (dämlich angesteuert über 4024 als Adress-Counter)), das Programm passt locker rein und auch die Rechengeschwindigkeit ist ganz ok (schnellere Echtzeitauswertung kann man auf einem AVR aber vergessen). Mit unions funktioniert das ganze eigentlich am besten - besser als mit malloc() und free(), denn hier müsste jede einzelne Variable angefordert und wieder entfernt werden, mit entsprechender Pointerorgie, bei der union kann man bequem ein paar Structs für jeden Programmabschnitt machen, die dann nacheinander benutzt werden. Einziger Nachteil: Man schreibt genug: union.struct.variable - und ich weiss nicht, wie schnell da der Zugriff intern gehandhabt wird. Gruss Michael
Kleiner Tip: Mittels Makros hat sich schon so mancher so manchen Schreibaufwand eingespart. #define VARIABLE union.struct.variable und schon wird aus einem union.struct.variable = 5; ein simples VARIABLE = 5; Nutze die Macht, Luke. Äh, mr. chip
> und ich weiss nicht, wie > schnell da der Zugriff intern gehandhabt wird. Da beim Zugriff alles statisch ist, und der Compiler die Adressen ausrechnen kann, kannst du mal davon ausgehen dass er das auch tun wird.
> Da beim Zugriff alles statisch ist, und der Compiler > die Adressen ausrechnen kann, kannst du mal davon ausgehen > dass er das auch tun wird. Das heisst dann, ein Zugriff auf eine 'union.struct.variable' ist vom Aufwand her äquivalent zu einem Zugriff auf 'variable'?
> Mit unions funktioniert das ganze eigentlich am besten - besser als > mit malloc() und free(), denn hier müsste jede einzelne Variable > angefordert und wieder entfernt werden, Ist eine Frage der Lebenszeit. Wenn die Variablen alle praktisch immer leben, dann sind die unions sicher am besten. Wenn du eine stochastische Verteilung der Lebensdauer hast, belegst du bei der malloc()-Variante halt nur den Speicher, den du gerade brauchst.
> Ist eine Frage der Lebenszeit. Wenn die Variablen alle praktisch > immer leben, dann sind die unions sicher am besten. Wenn du eine > stochastische Verteilung der Lebensdauer hast, belegst du bei der > malloc()-Variante halt nur den Speicher, den du gerade brauchst. Klingt logisch. Allerdings habe ich wie erwähnt eine ganz klare Aufstellung, wann welche Variabeln existieren. Im ersten Abschnitt des Programms jene, im zweiten andere. Es gibt weder Überlappungen noch 'Zufälligkeiten'. Ich denke, dies ist auf einem kleinen Mikrocontroller bei derart speicherintensiven Anwendungen auch die Regel - man muss jedes einzelne Byte genau einteilen, sonst hat das wüste Folgen...
> Ich denke, dies ist auf einem kleinen Mikrocontroller bei derart > speicherintensiven Anwendungen auch die Regel - man muss jedes > einzelne Byte genau einteilen, sonst hat das wüste Folgen... Würde ich so nicht ganz stehen lassen. Stochastik kann ebenfalls gut funktionieren, auch wenn es auf den ersten Blick wie Chaos aussieht. Die Diskussion erinnert mich an den Streit, was das bessere Vernetzungsprinzip ist: die ,,reine Lehre'' besteht darauf, dass jeder nur dann senden kann, wenn er ,,dran'' ist. Zu diesem Zweck wird ein Staffelstab herumgereicht, der jeder Station sagt, wann sie dran ist. Wenn sie nichts zu senden hat, gibt sie diesen weiter. Die Alternative ist, dass jeder sendet, ,,wann er will'', nur zuvor mal nachsieht, ob nicht vielleicht gerade jemand anders sendet. In diesem Fall ,,ein bisschen'' wartet. Das erste nennt sich `token ring', das zweite `Ethernet'. Mittlerweile dürfte ziemlich klar sein, wer der Gewinner dieses Streits war. Mit dem Speicher ist das ganz genauso. Die Stochastik hat natürlich ihre Grenzen: bei ,Verstopfung' ist das jeweilige deterministische System zuverlässiger. Der Tote Ring erreicht gleichmäßige Übertragungsraten auch noch kurz vor der Sättigung, während Ethernet in diesem Bereich durch die häufigen retries einbricht. Wenn dein Speicher also bis zum letzten Byte ausgereizt ist, wird die Stochastik nicht mehr gut funktionieren, weil immer häufig der Zustand `out of memory' zuschlägt.
> Wenn dein Speicher also bis zum letzten Byte ausgereizt ist, wird die > Stochastik nicht mehr gut funktionieren, weil immer häufig der Zustand > `out of memory' zuschlägt. Ich kann sozusagen frei wählen, wie voll ich meinen Speicher haben will - je mehr Speicherplatz ich zur Verfügung habe, desto besser wird meine Bildauswertung. Von daher werde ich also so nahe wie möglich ans Limit gehen.
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.