WinAVR: gezielt Bytes im Flash belegen

Dec 22, 2010 10 Replies

Hallo zusammen,



ich m=F6chte f=FCr ein Projekt mit einem ATmega, programmiert mit WinAVR = in C, gezielt ein paar Byte im Flash mit bestimmten Bytes belegen.



Die Position dieser Bytes soll gleich hinter der Vektorliste liegen, z.B. auf Adresse 80h. Der Compiler legt aber den Startup-Code und die gesamte Applikation zusammen in ein einziges Segment (.text). Wenn ich dort mit einem kleinen Assemblermodul und entsprechender Linker-Anweisung eigenen (konstanten) Inhalt hinlege, gibt es also eine entsprechende Overlap-Fehlermeldung vom Linker. :-(



Wie bekommt man am einfachsten ein paar konstante Bytes an definierter Stelle ins Flash?



Den Startup-Code holt sich WinAVR aus der Entwicklungsumgebung - ich k=F6nnte den deaktivieren und ein entsprechendes eigenes (abge=E4ndertes)=



Modul ins Projekt einbinden. Ich wei=DF aber nicht, welche Automatismen die Umgebung noch auf den Code anwendet (z.B. K=FCrzen der Vektorliste, Eintragen der Vektoren, Zusammenfassen von Segmenten) - so da=DF mir dieser Ansatz etwas riskant erscheint. Und die CRT1 im WinAVR zu =E4ndern= , ist systematisch falsch: diese konstanten Bytes geh=F6ren zum Projekt und=



nicht zum Arbeitsplatz.



Danke f=FCr Hinweise, Tilmann



Hallo zusammen,

ich m=F6chte f=FCr ein Projekt mit einem ATmega, programmiert mit WinAVR = in C, gezielt ein paar Byte im Flash mit bestimmtem Inhalt belegen.

Die Position dieser Bytes soll gleich hinter der Vektorliste liegen, z.B. auf Adresse 80h. Der Compiler legt aber den Startup-Code und die gesamte Applikation zusammen in ein einziges Segment (.text). Wenn ich dort mit einem kleinen Assemblermodul und entsprechender Linker-Anweisung eigenen (konstanten) Inhalt hinlege, gibt es also eine entsprechende Overlap-Fehlermeldung vom Linker. :-(

Wie bekommt man am einfachsten ein paar konstante Bytes an definierter Stelle ins Flash?

Den Startup-Code holt sich WinAVR aus der Entwicklungsumgebung - ich k=F6nnte den deaktivieren und ein entsprechendes eigenes (abge=E4ndertes)=

Modul ins Projekt einbinden. Ich wei=DF aber nicht, welche Automatismen die Umgebung noch auf den Code anwendet (z.B. K=FCrzen der Vektorliste, Eintragen der Vektoren, Zusammenfassen von Segmenten) - so da=DF mir dieser Ansatz etwas riskant erscheint. Und die CRT1 im WinAVR zu =E4ndern= , ist systematisch falsch: diese konstanten Bytes geh=F6ren zum Projekt und=

nicht zum Arbeitsplatz.

Danke f=FCr Hinweise, Tilmann

Am 22.12.2010 10:44, schrieb Tilmann Reh:

Also du hast eine neue section gebastelt und mit "--section-start=.bla=1234" den Linker angewiesen diese irgendwo hin zu schieben?

".text" wird man doch auch verschieben können?

Hallo Tilmann!

Suchst Du sowas? main.c [..] /* constant definitions {{{ */ /* put signature in ROM in section ".vectors", so it will end up right * behind the interrupt vector table. * For a fixed address, e.g. (byte) 0x40 corresponds to the (word) 0x20 in the * assembler version, we need a custom linker script */ const char signature[] __attribute__ ((section (".vectors"))) = SIG_NATURE; [..]

Gruß Thorsten

PGP welcome! Thorsten online: http://www.ostermann-net.de/electronic Rund um Schrittmotor, Fräs-Bohr-Plotter & Mikrocontroller

Und so sprach Tilmann Reh:

Vermutlich musst du deinem Kompiler erst mal sagen, dass dein Boot-Einsprungpunkt woanders hin gelinkt werden soll. Also, dass er seine main() woanders hin bauen muss. Dann kannst du Konstanten definieren, die du per #pragma $adresse auf feste Adressen legen kannst. Evtl. merkt der Kompiler beim vergeben der Adresse für die Konstante selber, dass er die main() verschieben muss und macht es allein.

Ob das über #pragma, scatterfile oder anders geht, musst du aus deiner Kompiler-Doku ziehen.

Roland

Also ich kenne mich mit dem AVR-Kram nicht mehr so genau aus, aber im Prinzip ist das doch normaler gcc oder?

Du musst irgendwo ein Linkerscript haben und dort solltest du eine neue section erzeugen und sie an eine bestimmte Stelle in den Speicher legen. Danach legst du dann deine Variablen in diese Section.

Ich kann dir leider kein Beispiel zeigen weil diese Linkerscripte je nach gcc Version oder nach dem der sie geschrieben hat stark unterschiedlich aussehen. Allerdings erschliesst sich ihre Funktion normalerweise beim lesen. Also so irgenwie jedenfalls. :-)

Was hat der Startup-Code mit deinen Bytes im Flash zutun? Du kannst natuerlich auch einen Startup-Code erzeugen. Mache ich auch normalerweise, aber das ist unabhaengig von deinen Sections.

Der gcc hat irgendwo ein Linkerscript. (endung .ld) Das musst du dir in dein Projektverzeichnis kopieren. Dann bittest du den Linker dein Script zu verwenden (z.b: -T sh2a.ld fuer meinen sh2a) Wenn du das geschafft hast dann faengst du an dieses Script nach deinen Wuenschen zu aendern.

Olaf

Hallo Thorsten,

VR in

ja, so in der Art - das funktioniert schonmal, aber in der Tat liegen die Bytes dann /unmittelbar/ hinter den Vektoren, ohne da=DF ich deren Position angeben k=F6nnte.

Im aktuellen Fall d=FCrfte das aber reichen - immerhin brauche ich dann nicht am Linkerscript fummeln.

Danke, Tilmann

Heiko Lechner schrieb:

n zu=20

Ja, genau das (kann man =FCbrinx im AVR-Studio unter den Projekteinstellungen machen).

e

Wie schon geschrieben, er packt /alles/ (Vektorliste, Startup-Code, Applikation) in eine /einzige/ .text Sektion - wenn ich die woanders hin linke, funktioniert der Code nicht mehr (mangels Vektoren).

Tilmann

Roland Ertelt schrieb:

Nö, das geht ganz von allein, rein durch den Namen von main().

Einfacher als das, was Tilmann versucht, wäre es allerdings, ein paar Bytes am Ende des Flashs zu reservieren. Dann braucht man sich mit dem ganzen Linkergedödel gar nicht rumschlagen. Die Vektortabelle ist sowieso zwischen den einzelnen AVRs unterschiedlich lang, eine Chance auf eine allzeit gültige feste Adresse gibt's also ohnehin nicht.

cheers, J"org .-.-. --... ...-- -.. . DL8DTL http://www.sax.de/~joerg/ NIC: JW11-RIPE Never trust an operating system you don't have sources for. ;-)

Joerg Wunsch schrieb:

Ich wei=DF - aber das w=E4re in diesem Fall aus anderen Gr=FCnden nicht s= innvoll.

Es reicht, wenn die innerhalb des Projektes fest ist. Da der Controller zwischendurch nicht gewechselt wird, ist das also kein Problem. (Allzeit gleiche Adresse w=E4re nat=FCrlich noch sch=F6ner... Aber der Au= fwand daf=FCr ist im Verh=E4ltnis zu gro=DF.)

Tilmann

Da ich gerade ein Beispiel zur Hand habe (ARMv5/IXP425):

OUTPUT_ARCH (arm) ENTRY (_start) SECTIONS { . = 0x00000000;

. = ALIGN (4); .text : { arch/arm/cpu/ixp/start.o(.text*) net/libnet.o(.text*) board/actux3/libactux3.o(.text*) arch/arm/cpu/ixp/libixp.o(.text*) drivers/serial/libserial.o(.text*)

. = env_offset; common/env_embedded.o(.ppcenv) *(.text*) } [...] }

Hier wird das Environment (section .ppcenv) auf eine feste Adresse (env_offset) innerhalb des Codes gelegt (nämlich in eine der kleinen Pages bei einem 29LV160-Flash). Die Objects ausser start.o sind von Hand so gestückelt, dass es gerade passt - sonst wäre der Bereich ungenutzt, der Linker kann die .text-Sachen leider nicht selbständig auf die 2 Bereiche vor und hinter dem Environment verteilen.

Ich würde den Linker nicht direkt aufrufen, sondern auch zum Linken den gcc aufrufen - Linker-Parameter dann mit -Wl,... angeben. Das hat den Vorteil, daß gcc selber anhand der diversen Kommandozeilenparameter die *passende* libgcc heraussuchen und dazulinken kann.

cu Michael

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required