Hallo, oft ergibt sich die Notwendigkeit, bestimmte Variablen an feste Speicheradressen zu schreiben (z.B. um Parameter getrennt vom Programm laden zu können). Das funktioniert mit gcc, wenn man die entsprechenden Variablen mit const my_varyp my_var _attribute_ ((section (".my_section"))) = {...}; definiert. Dem Linker muss man dann die Section my_section mit --change-section-address=.my_section=0x2000 bekannt machen (hier: feste Adresse 200hex). Leider funktioniert dieses Vorgehen nicht mit AVRStudio (getestet mit den Versionen 4.09 und 4.10 sowohl mit extcoff als auch mit dwarf-2). Die neu angelegte Section wird von AVRStudio schlicht ignoriert. Erzeugt man ein Hex-File, tauchen die Variablen dagegen auf. Allerdings entfällt dann die Debug-Möglichkeit. Als Lösung benutze ich mittlerweile folgende Möglichkeit: Die neue Section wird nicht als eigenständige Section, sondern als Untersection von text deklariert. Dazu muss im Linker-Scriptfile geändert werden (welches Script-File von der aktuellen Konfiguration verwendet wird, lässt sich einfach und brutal herausfinden: das Verzeichnis \WinAVR\avr\lib\ldscripts umbenennen und neu linken, die Linker-Fehlermeldung zeigt dann den Namen des verwendeten Linker-Scripts). Das Linker-Script ins Projektverzeichnis kopieren, sinnvoll umbenennen und folgende Änderungen einfügen: *(.fini3) *(.fini2) *(.fini1) *(.fini0) . = ABSOLUTE(0x2F00); /* neue Zeile: feste Adresse vorgeben */ *(.my_section) /* neue Zeile: Section bekannt machen */ _etext = . ; } > text .data : AT (0x3780) /* optional: Anfang des S.Data vorgeben */ { Im Makefile mus dem Linker die Verwendung des modifizierten Linker-Scripts bekannt gegeben werden (ich benutze ansonsten das Standard-Makefile aus WINAVR 20040720): LDFLAGS = Wl,-Map=$(TARGET).map,--cref,--script=my_linkerscript_avr5.x Wer eine elegantere Lösung gefunden hat, kann sich natürlich gerne melden! Viele Grüße, Stefan
Mach' doch mal'n feature request bei Atmel, dass AVR Studio alle loadable sections unterstützen möge.
Moin, ich bin in C nicht so richtig bewandert - aber kann man Variablen nicht auch mit #PRAGMA an eine vorgegebene Speicherstelle definieren? Oder habe ich irgendetwas mißverstanden?
Kann man zumindest bei GCC nicht. Geht insbesondere schon deshalb nicht, weil es der Linker ist, nicht der Compiler, der etwas an eine Adresse bindet. #pragma ist compilerabhängig, genau dafür ist es gemacht worden.
@Jörg, werde ich machen, ich wollte nur erstmal die Meinung der Experten hören, ob das wirklich ein Problem des AVRStudio ist oder nur meine Fehlinterpretation. Viele Grüße, Stefan
Hallo, ich habe in der oben geposteten Verfahrensweise noch einen Bug entdeckt. Vorinitialisierte Variablen werden mit obiger Methode aus dem falschen Speicherbereich initialisiert. Mit folgender zusätzlich eingefügter Zeile funktionieren auch die initialisierten (globalen) Variablen: *(.fini1) *(.fini0) . = ABSOLUTE(0x2F00); *(.my_section) /* Platz für Daten mit fester Adresse */ . = ABSOLUTE(0x3780); /* diese Zeile zusätzlich einfügen */ _etext = . ; } > text .data : AT (0x3780) { Viele Grüße, Stefan
Es gibt im avrfreaks gcc-Forum grade zwei aktuelle Threads mit aehnlichem Thema.
Tach! Frage dazu: Wie kann ich im Code die Startadresse einer Section rausfingern ? Ich hab z.B. die Versionkennung bei Adresse 0x37FE geschrieben: Makefile: LDFLAGS += -Wl,--section-start=.version=0x37FE Code: const unsigned char ver[2] _attribute_ ((section (".version"))) = {VERSION_MAJOR, VERSION_MINOR}; Ich möchte nun im Code mit pgm_readbyte die Version auslesen, die Adresse dafür möchte ich aber automatisch dem makefile entnehmen lassen falls das mal verschoben werden sollte. Geht das ? Stefan
Ich bin mir jetzt nicht sicher, ob ich die Frage richtig verstanden habe. >Makefile: >LDFLAGS += -Wl,--section-start=.version=0x37FE > >Code: >const unsigned char ver[2] _attribute_ ((section (".version"))) = >{VERSION_MAJOR, VERSION_MINOR}; - Die Adresse, auf die .version zeigt, wird im Linkerfile festgelegt - Im Makefile wird an diese Adresse das Versionsword zugewiesen - Im Code zeigt das array ver auf die beiden Bytes des Words Ändert man jetzt die Position von .version im Linkerfile, muss man das Programm neu Kompilieren und schon kennt das Programm wieder die richtige Adresse (ver = .version) mit dem korrekten Inhalt (ver[0] = 0x??; ver[1] = 0x??). Möchtest Du die Adresse, auf die .version zeigt, im Makefile zuweisen?
Hmmm, ich glaub ich hab grad gemerkt dass ich da ne total bescheuerte Frage gestellt habe... Ja, ich möchte im Makefile die Adresse zuweisen, und im Code die Variable auslesen mit pgm_read_byte, aber im Code nicht noch mal die Adresse hinschreiben müssen. Sonst müsste man das zweimal ändern falls die Adresse geändert werden soll. Aber ein einfaches pgm_read_byte(ver) sollte ja da genügen... Naja, um diese Zeit klappts besser mit dem Hirn ;-) Stefan
Sorry, ich habe mich da ein wenig "verhauen" ;) Die Adresse, auf die .version zeigt, wird in Deinem Falle natürlich im Makefile zugewiesen (0x37FE). Da hab ich wohl ein wenig Verwirrung gestiftet.
>pgm_read_byte(ver) sollte ja da genügen...
fast richtig, aber bitte die Adresse übergeben:
pgm_read_byte(&ver)
Der kleine Haken an pgm_read_byte und Konsorten ist, dass es ein Makro
ist und damit keine Typkontrolle besitzt - Du kannst so ziemlich alles
übergeben, ohne Fehlermeldungen zu bekommen.
Viele Grüße, Stefan
>fast richtig, aber bitte die Adresse übergeben: >pgm_read_byte(&ver) Ebenso "fast richtig" g pgm_read_byte(ver[x]); ...wobei x 0 oder 1 sein kann, und entweder die major oder minor Version enthält ;)
Hmm, bin mir da nicht so sicher, pgm_read_byte will ja einen Pointer übergeben haben, also müsste eigentlich pgm_read_byte(ver) oder pgm_read_byte(&ver[0]) richtig sein, (ver (ohne []) ist ja ein Pointer) werd das mal eben testen... stefan
;) RTFKNR: unsigned char ver[2]; - ver ist ein Pointer (auf den Anfang des Arrays) - ver[x] ist ein Pointer (auf den Eintrag x des Arrays) - ver + 1 ist ein Pointer auf den Anfang von ver + 1 Element
Nö, ver[x] ist vom Elementtyp von `ver', also `char'. Für einen Pointer muss man schon wirklich &ver[x] oder ver + x schreiben (beide Ausdrücke sind in dem Zusammenhang äquivalent).
Ja, gerade getestet (und gelesen ;-) Nochmal zum mitmeiseln: mychar=pgm_read_byte(ver + x); oder mychar=pgm_read_byte(&ver[x]); Jörg hats auf den Punkt gebracht...
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.