mikrocontroller.net

Forum: Compiler & IDEs Feste Speicheradressen mit WinAVR und AVRStudio


Autor: Stefan Kleinwort (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mach' doch mal'n feature request bei Atmel, dass AVR Studio alle
loadable sections unterstützen möge.

Autor: thkais (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Stefan Kleinwort (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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

Autor: Stefan Kleinwort (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: mthomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt im avrfreaks gcc-Forum grade zwei aktuelle Threads mit
aehnlichem Thema.

Autor: Stefan Seegel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Stefan Seegel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Stefan Kleinwort (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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 ;)

Autor: Stefan Seegel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Stefan Kleinwort (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
grummel  .... stimmt ;-)

Viele Grüße, Stefan

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
;)

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

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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).

Autor: Stefan Seegel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

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.