-         

Ergebnis 1 bis 9 von 9

Thema: Dynamische Speicherverwaltung für AVR Sinnvoll?

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.09.2009
    Ort
    Geilenkirchen
    Beiträge
    419

    Dynamische Speicherverwaltung für AVR Sinnvoll?

    Anzeige

    Nabend!

    Ich bin gerade dabei, einen CanOpen Stack auf einem Atxmega zu implementieren.
    Bisher funktioniert auch alles Wundervoll, ich kann SDOs schicken und empfangen, das gleiche gilt für PDOs und PDO Mapping klappt auch schon, selbst die SPS meckert nicht mehr bei der Kommunikation .

    Jetzt habe ich momentan das Problem, dass der Stack möglichst Flexibel für verschiedene Anwendungen genutzt werden soll.
    Das heißt es müssen alle nötigen Objekte im Speicher vorhanden sein.
    Aktuell Lege ich jedes Objekt einzeln fest, in der Art:
    Code:
    CanObject LedState,Pulswidth,IOReg;
    Das Problem ist, dass auf die Weise viele eventuell nicht genutzte Objekte den Speicher unnötig füllen.
    Am besten wäre, wenn immer nur die Objekte erzeugt werden, die die SPS per SDO konfigurieren will (Natürlich mit einigen Ausnahmen).
    Also benötige ich eine Möglichkeit, die Objekte dynamisch, zur Laufzeit zu erzeugen.
    Würde ich für einen PC Programmieren würde ich zu einer map greifen.
    Auf dem Controller halte ich das für zu ineffektiv.

    Was ist von der Nutzung von malloc() zu halten?
    Dazu habe ich von vielen schlechtes, von einigen aber auch gutes gehört.
    Hat jemand schon Erfahrungen mit so etwas gemacht und kann mir weiter helfen?

    Oder macht vielleicht ein externer Speicher mehr sinn?

    Grüße
    Olaf

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    59
    Beiträge
    2.435
    Hallo Olaf,
    Zitat Zitat von crabtack Beitrag anzeigen
    Was ist von der Nutzung von malloc() zu halten?
    Dazu habe ich von vielen schlechtes, von einigen aber auch gutes gehört.
    Hat jemand schon Erfahrungen mit so etwas gemacht und kann mir weiter helfen?
    Das ist das selbe Problem wie mit Zeigern in C.
    Genial, wenn man damit umgehen kann und frustrierend wenn man das Konzept nicht verstanden hat und nicht aufpasst!

    Es gibt drei grundlegende Gefahren:
    1. Wenn man mit malloc() zu wenig Platz für ein Objekt anfordert überschreibt man natürlich irgendein anderes Objekt. Wie sich die Software verhält hängt jetzt davon ab, welches Objekt sich gerade hinter diesem Objekt befindet. Wenn der Speicher unbenutzt ist, passiert im besten Fall scheinbar gar nichts. Da die Speicherverwaltung dynamisch ist, wird auch das Verhalten der Software entsprechend unvorhersehbar. Möglich ist auch, dass man den Heap killt, in den ersten Bytes eines Verwaltungsblocks befinden sich Verwaltungsinformationen.

    2. Wenn man den Block mit free() zurückgegeben hat, kann man natürlich weiterhin mit dem Zeiger auf diesen Speicherbereich zugreifen. Auch jetzt ist das Verhalten nicht vorhersehbar. Je nachdem ob der Block schon weiter verwendet wird oder nicht. Aus Laufzeitgründen wird der Block mit free() auch nicht auf 0 gesetzt, die Daten des Objekts stehen also noch im Speicher.
    Hier hilft es wenn man, zumindest bei der Debug-Version folgendermassen vorgeht:
    Code:
    free(ptr);
    ptr = NULL;
    Allerdings muss man auch alle Kopien von ptr zurücksetzen, wobei es schon grundsätzlich schlechter Programmierstil ist, hier mit mehreren Variablen zu arbeiten ....

    3. Vergisst man abgelaufenen Objekte mit free() an den Heap zurückzugeben geht einem mit der Zeit der Speicher aus.

    Zitat Zitat von crabtack Beitrag anzeigen
    Oder macht vielleicht ein externer Speicher mehr sinn?
    Den externen Speicher musst du dann für die maximale Objektgrösse und die maximale Anzahl an Objekten auslegen!
    Wenn die typischen Objekte z.B. 16 Byte gross sind und das Grösste 4KB, versaust du jede Menge Speicher
    Für 10 Objekte brauchst du dann rund 40KB Speicher. Da könnte man aber problemlos über 2'500 16-Bit Objekte unterbringen.

    Zitat Zitat von crabtack Beitrag anzeigen
    Hat jemand schon Erfahrungen mit so etwas gemacht und kann mir weiter helfen?
    Jede Menge, habe auch schon selber malloc() und Co selber implementiert, allerdings auf Renesas-CPUs (H8-Familie)

    Im einfachsten Fall hat jedes Heap-Element einen Header mit einem Zeiger auf das nächste Element und einem Flag welches angibt ob der Block frei oder belegt ist.
    Da die H8 16-Bit Zugriffe nur auf gerade Adressen machen können, belegt die Standardvariante, beim 16-Bit Speichermodell, für den Header 4 Bytes. 2Bytes für den Zeiger. 1 Bit für das Flag und 15 Bit sind verschwendet Ich habe dann das Flag in das letzte Adressbit gepackt, die H8 setzen das letzte Bit bei einem Speicherzugriff einfach per Hardware auf 0. Bei kleinen Objekten und nur ein paar KB RAM macht das einiges aus.

    MfG Peter(TOO)
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Kandel
    Alter
    29
    Beiträge
    1.220
    Du musst bedenken, dass du bei AVRs keine Möglichkeit hast, einer Speicherfragmentierung entgegen zu wirken. Wenn du Objekte unterschiedlicher Größe hast und nur manche freigibst und andere nicht, kannst du dir den Heap so zerstückeln dass irgendwann größere Datenstrukturen nicht mehr als ganzes unterzubringen sind.

    mfG
    Markus
    Tiny ASURO Library: Thread und sf.net Seite

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    59
    Beiträge
    2.435
    Hallo Markus,
    Zitat Zitat von markusj Beitrag anzeigen
    Du musst bedenken, dass du bei AVRs keine Möglichkeit hast, einer Speicherfragmentierung entgegen zu wirken. Wenn du Objekte unterschiedlicher Größe hast und nur manche freigibst und andere nicht, kannst du dir den Heap so zerstückeln dass irgendwann größere Datenstrukturen nicht mehr als ganzes unterzubringen sind.
    Die Fragmentierung in dieser Form hat man aber nur unter bestimmten Bedingungen.
    Vor allem hängt es davon ab, wie das Grössenverhältnis zwischen den Elementen und zum Heap ist.

    Normalerweise ist dies kein Problem.

    MfG Peter(TOO)
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    11.08.2008
    Ort
    Hallein
    Alter
    26
    Beiträge
    802
    Man sollte natürlich auch beachten, dass der Heap (malloc/free/realloc) nur Code ist. Also brauchst du zuerst mal eine Implementierung, wie z.b die avr-libc. Dann solltest du beachten, das AVR keinen Speicherschutz haben. Der Stack fängt immer vom Ende des Speichers an. Der Heap wird dann nach .bss und .data Segmenten plaziert. D.h. Heap und Stack arbeiten aufeinander zu und können sich gegenseitig zerstören. Die Heapimplementierung kann zwar prüfen, dass es nicht in den Stack reinarbeitet. Aber da der Stack nichts vom Heap weiß, kann der Stack dir den Heap kaputt machen. Also du solltest unbedingt überdenken was in den Heap soll. Und auch auf die Rekursionstiefe vom Funktionen ist dann acht zu geben, dass der Stack nicht zu groß wird.

    Gegen die Speicherfragmentierung des Heaps hilft natürlich eine möglichst intelligente malloc/free-Routine, die Fragmentierung vermeidet oder im Notfall sogar den Heap defragmentieren kann.
    Kultuverein Metal Resurrection, für mehr Bands und Konzerte in Österreich (:

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    11.08.2008
    Ort
    Hallein
    Alter
    26
    Beiträge
    802
    wenn deine Daten zwar dynamisch unterschiedlich groß sind, aber eigentlich relativ klein und nur innerhalb der einen Funktion leben müssen, wäre alloca() auch eine Möglichkeit. Damit kannst du dynamisch Speicher am Stack allozieren, welcher beim Verlassen der Funktion automatisch wieder frei gegeben wird.
    Kultuverein Metal Resurrection, für mehr Bands und Konzerte in Österreich (:

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Kandel
    Alter
    29
    Beiträge
    1.220
    Zitat Zitat von TheDarkRose Beitrag anzeigen
    Gegen die Speicherfragmentierung des Heaps hilft natürlich eine möglichst intelligente malloc/free-Routine, die Fragmentierung vermeidet oder im Notfall sogar den Heap defragmentieren kann.
    Den Heap defragmentieren geht nicht bei AVRs. Und die möglichst intelligente malloc/free-Routine gibt es auch nicht, weil immer von deinem Einsatzszenario abhängt, was möglichst intelligent ist. Wenn du malloc sparsam und unter Berücksichtigung der Arbeitsweise einsetzt, bekommst du mit einer Speicherfragmentierung keine Probleme. Unbedachtes malloc fliegt dir wahrscheinlich um die Ohren wenn du Objekte mit sehr unterschiedlicher Lebensdauer hast.

    mfG
    Markus
    Tiny ASURO Library: Thread und sf.net Seite

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    11.08.2008
    Ort
    Hallein
    Alter
    26
    Beiträge
    802
    Gut, defragmentieren war etwas überspitzt. Dennoch, wenn zwei Blöcke nebeneinander freigegeben werden, sollte natürlich die Heapverwaltung erkennen, dass diese wieder zu einen zusammenhängenden freien Block werden. Wenn es nicht um Geschwindigkeit geht, kann man natürlich schon speichereffektivere malloc-Routinen verwenden.

    Aber wie gesagt, wenn die Bedingung ist, dass einfach nur dynamisch die Größe des eigentlichen Objektes nötig ist, und der Pointer nicht raus aus der Methode muss (also den Pointer returnen), dann sollte alloca() die bessere Alternative sein.
    Kultuverein Metal Resurrection, für mehr Bands und Konzerte in Österreich (:

  9. #9
    Neuer Benutzer Öfters hier
    Registriert seit
    24.05.2012
    Beiträge
    14
    Ich bin im Embedded Bereich (vor allem bei so kleinen Controllern) im allgemeinen gegen Malloc und Co und nutze sie nur im Notfall. Nur wenn aller genutzter Speicher statisch allokiert wird, kannst du dir sicher sein, dass dir der RAM nicht ausgeht. Am PC ist das nicht so wild, weil a) viel viel mehr RAM da ist und b) RAM auf die Festplatte ausgelagert werden kann, wenn der Platz knapp wird.

    Wenn überhaupt würde ich für deinen CanOpen Stack einen festen Bereich reservieren und den je nach Bedarf neu zu teilen. Allerdings musst du dir auch hier sicher sein, dass 2 Komponenten nicht gleichzeitig den selben Speicher brauchen.

Ähnliche Themen

  1. Toro-Bot: Lampenroboter sorgen für dynamische Beleuchtung
    Von Roboternetz-News im Forum Neuigkeiten / Technik-News / Nachrichten / Aktuelles
    Antworten: 0
    Letzter Beitrag: 27.02.2014, 12:10
  2. Einfache dynamische Beinprothese
    Von eames im Forum Vorstellung+Bilder+Ideen zu geplanten eigenen Projekten/Bots
    Antworten: 14
    Letzter Beitrag: 28.03.2013, 11:08
  3. Arrays und Speicherverwaltung
    Von setirli im Forum Microcontroller allgemeine Fragen/Andere Microcontroller
    Antworten: 6
    Letzter Beitrag: 22.11.2008, 20:01
  4. Dynamische Variablen allocierung
    Von zeusosc im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 1
    Letzter Beitrag: 25.01.2007, 22:15
  5. Frage: dynamische Variablen - Deklarierung
    Von The Man im Forum Software, Algorithmen und KI
    Antworten: 3
    Letzter Beitrag: 15.07.2006, 12:15

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •