Hallo, wie kann ich, um meine Firmware per IAP zu updaten, eine Funktion ins Ram kopieren und von das ausführen?
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_projects/index.html#gcc_ramfunc Martin Thomas
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
> 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.
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?
> 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:
1 | /* put data into ROM. It will be copied to RAM at startup time */ |
2 | .data : AT (ADDR (.jcr) + SIZEOF (.jcr)) |
3 | { |
4 | __data_start = . ; |
5 | *(.data .data.* .gnu.linkonce.d.*) |
6 | KEEP (*(.gnu.linkonce.d.*personality*)) |
7 | SORT(CONSTRUCTORS) |
8 | } > ram |
9 | |
10 | __data_load_start = LOADADDR(.data); |
11 | __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.
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
> 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.
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.