mikrocontroller.net

Forum: Compiler & IDEs Arm Gcc Funktion ins Ram


Autor: stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wie kann ich, um meine Firmware per IAP zu updaten, eine Funktion ins 
Ram kopieren und von das ausführen?

Autor: Martin Thomas (mthomas) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Am Einfachsten, indem man die Funktion der .data section zuweist vgl. 
gcc-manual function-attributes. Dann wird die Funktion beim üblichen 
C-Startup mit dem Rest von .data (initialisierte Variablen ungleich 0) 
ins RAM kopiert. Mögliche Fallen (und Abhilfen): evtl. alignment nicht 
korrekt (dann eigene C-Section für die RAM Funktionen anlegen und im 
Linker-Script eintragen) und/oder long-calls erforderlich (dann 
long-call attribute ergänzen).
Mglw. ist mein Beispiel hilfreich: 
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm...

Martin Thomas

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Antwort. Werde ich mal probieren. Kann ich das ganze auch 
erst dann machen, wenn ich es brauche? Also die Funktion nachträglich 
ins Ram kopieren? Wenn ich teile des Heaps dafür überschreibe ist mir 
das ansich egal, da ich die danach eh nicht mehr brauche...

Grüße, Stefan

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Kann ich das ganze auch erst dann machen, wenn ich es brauche? Also die
> Funktion nachträglich ins Ram kopieren?

Im Prinzip schon. Dann mußt du dich allerdings selbst um alles kümmern. 
Du müßtest dazu im Linkerskript eine neue Sektion anlegen. Als 
Inspiration dazu kann dir die .data-Sektion im bisher verwendeten 
Linkerskript dienen. Du gibst dabei im Linkerskript zwei Adressen an, 
einmal die im Flash, an die die Funktion geschrieben wird, und dann die 
im RAM, in der der Code später ausgeführt werden soll. arm-elf-objdump 
-h gibt dir diese Adressen als LMA und VMA an.
Außerdem definierst du im Linkerskript Symbole, über die du dann vom 
Programm aus drauf zugreifen kannst. Die kannst du dann mit memcpy 
verwenden, um die Funktion vor ihrem Aufruf an ihre Zielstelle zu 
befördern.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, hab ich fast verstanden. NUr eins nicht: Wie komm ich an die Adresse 
für die Position im Flash?
Darf die Adresse im Ram mit dem Data-Segment kollidieren? - Also die 
gleiche sein?

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> NUr eins nicht: Wie komm ich an die Adresse für die Position im Flash?

Du meinst aus dem Programm heraus? Du mußt dazu ein Symbol im 
Linkerskript definieren. Im Prinzip muß es völlig analog zur Sektion 
.data gemacht werden. Die .data-Sektion sieht in meinem Linkerskript 
z.B. so aus:
  /* put data into ROM. It will be copied to RAM at startup time */
  .data   : AT (ADDR (.jcr) + SIZEOF (.jcr))
  {
    __data_start = . ;
    *(.data .data.* .gnu.linkonce.d.*)
    KEEP (*(.gnu.linkonce.d.*personality*))
    SORT(CONSTRUCTORS)
  } > ram

  __data_load_start = LOADADDR(.data);
  __data_load_end = __data_load_start + SIZEOF(.data);

Das AT am Anfang gibt dabei an, wo die Sektion im Flash stehen soll. In 
diesem Fall ist das nach dem Ende der Sektion .jcr. Du müßtest für deine 
eigene Sektion raussuchen, welche Sektion bisher die letzte im Flash ist 
und deine dann dahinter anhängen.
Die Definitionen von __data_load_start und __data_load_end sind die 
Symbole für den C-Code.  Dann könnte man in C mit:

extern unsigned char __data_load_start[];
extern unsigned char __data_load_end[];
const size_t data_size = __data_load_end - __data_load_start;

die Startadresse und die Größe der Sektion im Flash verfügbar machen. 
Analog dazu gibt's oben noch __data_start für die Adresse im RAM. Damit 
hast du alles, was zum Aufruf von memcpy benötigt wird. Danach kannst du 
die Funktion dann ganz normal aufrufen wie jede andere auch.
Ob bzw. wie man dem Linker sagen könnte, daß eine RAM-Doppelbelegung in 
diesem Fall erlaubt ist, weiß ich nicht.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tausend Dank für Deine super Erklärung. NUn sollte es klar sein.
Hast Du vielleicht noch einen Link, wo ich sowas nachlesen kann um mich 
noch weiter zu bilden. Vor allem was es mit den Sektionen (.jcr) auf 
sich hat?

Ansich müsste ich die Funktion ja auch unabhängig davon was 
__data_load_start ist, an eine beliebige Stelle im Ram kopieren können, 
da alle Sprünge ja relativ sein sollten, oder?

Grüße, Stefan

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Hast Du vielleicht noch einen Link, wo ich sowas nachlesen kann um mich
> noch weiter zu bilden. Vor allem was es mit den Sektionen (.jcr) auf
> sich hat?

Es gibt die Deokumentation vom GNU-Linker, aber da stehen die Rollen der 
einzelnen Sektionen nicht drin. Letztendlich sind die auch 
Compiler-abhängig. Ich kenne keine Liste, die die ganzen Sektionen 
beschreibt.

> Ansich müsste ich die Funktion ja auch unabhängig davon was
> __data_load_start ist, an eine beliebige Stelle im Ram kopieren können,
> da alle Sprünge ja relativ sein sollten, oder?

Da bin ich mir nicht sicher. Du kannst es versuchen, dann eben über 
einen selbst definierten Funktionszeiger, aber ich würde die Zieladresse 
lieber vom Linkerskript nehmen. Ich weiß nicht, ob innerhalb der 
Funktion wirklich alle Adressen immer relativ und von außen immer 
absolut sind. Spätestens, wenn deine Funktion eine andere aufruft, die 
auch im RAM ist, wird's nicht mehr gehen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.