Forum: Compiler & IDEs "-mmcu="-Parameter bei AVR-GCC?


von Günter R. (galileo14)


Lesenswert?

Was genau bewirkt eigentlich der "-mmcu=xxxx"-Parameter bei 
AVR-GCC-Aufrufen? Setzt er lediglich das benötigte Makro (z.B. 
"__AVR_ATmega128__"), oder tut er noch mehr?

Hintergrund dieser Betrachtung ist: wenn man eigene Bibliotheken 
entwickeln möchte, die nur hardware-unabhängige Funktionen enthalten, so 
will man diese Bibliotheken ja für alle AVR-Typen verwenden, die man 
einsetzt, bei mir also z.B. ATmega48/88/168, ATmega32/644/644P, 
ATmega128, ATmega1280, aber z.B. keine Tiny's.

Ist es dann ratsam, den "-mmcu="-Parameter wegzulassen?

von Günter R. (galileo14)


Lesenswert?

Merke gerade, der AVR-GCC bringt Fehlermeldung, wenn man diesen 
Parameter wegläßt.

von (prx) A. K. (prx)


Lesenswert?

Günter R. wrote:

> Was genau bewirkt eigentlich der "-mmcu=xxxx"-Parameter bei
> AVR-GCC-Aufrufen? Setzt er lediglich das benötigte Makro (z.B.
> "__AVR_ATmega128__"), oder tut er noch mehr?

Er tut mehr. Er sagt dem Compiler, welcher Befehlssatz zur Verfügung 
steht, und sagt dem Linker, welches Linker-Script er verwenden sollte.

> Ist es dann ratsam, den "-mmcu="-Parameter wegzulassen?

Es gibt ein paar Maschinenklassen für die Befehlssatzauswahl, die man 
dann in -mmcu=xxx verwenden kann. Bischen im Compiler nachforschen kann 
dabei helfen.

von Günter R. (galileo14)


Lesenswert?

Du meinst sicher die Sache mit "avr1" ... "avr5"? Dann liege ich 
wahrscheinlich bei meiner o.g. Auswahl mit "atmega128" nicht ganz 
falsch.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Günter R. wrote:
> Du meinst sicher die Sache mit "avr1" ... "avr5"?

Ja.  Du kannst dann auch kein #include <avr/io.h> machen (weil die
Bitdefinitionen natürlich nur für einen konkreten AVR zutreffen
können), aber allgemeine Bibliotheken sollte man auf diese Weise
entwickeln können.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Günter R. wrote:
> Was genau bewirkt eigentlich der "-mmcu=xxxx"-Parameter bei
> AVR-GCC-Aufrufen? Setzt er lediglich das benötigte Makro (z.B.
> "__AVR_ATmega128__"), oder tut er noch mehr?
>
> Hintergrund dieser Betrachtung ist: wenn man eigene Bibliotheken
> entwickeln möchte, die nur hardware-unabhängige Funktionen enthalten, so
> will man diese Bibliotheken ja für alle AVR-Typen verwenden, die man
> einsetzt, bei mir also z.B. ATmega48/88/168, ATmega32/644/644P,
> ATmega128, ATmega1280, aber z.B. keine Tiny's.
>
> Ist es dann ratsam, den "-mmcu="-Parameter wegzulassen?

Nein, es sollte schon angegeben werden, für welche Familie von Derivaten 
übersetzt wird. Ansonsten wird für avr2 übersetzt, also für die Familie 
von AVRs, zu der auch AT90S2313 gehört.

Das Setzen von Builtin-Makros wie _AVR_ATmega128_ ist Resultat von 
-mmcu. Damit kann in Anwendungen (dazu gehört aus gcc-Sicht in gewisser 
Weise auch die avr-libc etc) erkannt werden, um welches Derivat es genau 
handelt -- wichtig, um SFR-Adressen definieren zu können und passende 
Inline-Assembler Makros zu definieren, etwa für EEPROM-Zugriff, 
Sleep-Modes, ...

Darüber hinaus werden noch andere Builtin-Makros gesetzt (oder eben 
nicht gesetzt) wie
1
__AVR_HAVE_RAMPZ__
2
__AVR_HAVE_ELPM__
3
__AVR_HAVE_ELPMX__
4
__AVR_HAVE_MOVW__
5
__AVR_HAVE_LPMX__
6
__AVR_ASM_ONLY__
7
__AVR_ENHANCED__
8
__AVR_HAVE_MUL__
9
__AVR_MEGA__
10
__AVR_HAVE_JMP_CALL__
11
__AVR_2_BYTE_PC__
12
__AVR_ARCH__
Intern richtet avr-gcc die Codeerzeugung nach den Fähigkeiten des 
Targets aus, die sich zB an den oben beschriebenen Eigenschaften 
orientieren.

Diese Eigenschaften unterteilen die AVRs in Familien, die grobkörniger 
sind als einzelne AVRs. Diese Familien können auch per -mmcu angegeben 
werden:

avr1, avr25, avr2 avr35, avr3, avr31, avr3, avr51, avr5, ...

welche im Makro _AVR_ARCH_ ersichtlich ist:
1
> touch dummy.c 
2
> avr-gcc dummy.c -E -dM -mmcu=atmega8 | grep AVR_ARCH

Die Erstelluung von Bibliotheken aus Sicht von avr-gcc braucht nur diese 
Klassen zur Unterscheidung, da dort keine SFRs angesprochen werden. Dies 
dient also zur Erstellung der Multilibs, wie sie zB bei WinAVR unter 
./avr/lib zu finden sind. avr-gcc selbst hat kein Wissen über 
SFR-Adressen, diese stehen in Headern der avr-libc. Das einzige, was er 
weiß, ist ob er ein IN/OUT nehmen kann oder ein LDS/STS.

Zur Erzeugung einer HAL-Bibliothek, die zB einen generischen UART 
implementiert, reicht die Granulierung per AVR_ARCH nicht aus.

Die angegebene -mmcu Option wird per Specs, also per Kommandozeile, an 
die Tools wie as und ld weitergereicht, damit auch die nachgeschalteten 
Tools darüber Bescheid wissen, was das Derivat an Befehlen kann und was 
nicht, etc.

Zudem wird der Linker darüber informiert, welchen Startup-Code er 
hinzulinken soll (crt*.o), und teilweise wird der Linker auch über 
-Tdata über die Startadresse einzelner Sections angewiesen. Das crt 
selbst wird jedoch erst im Rahmen der avr-libc zur Verfügung gestellt 
(./crt1/gcrt1.S) aus dem die unterschiedlichen crt erzeugt werden.

In deinem Falle wird sich der Code zB darin unterscheiden, ob eine 
Funktion per CALL oder per RCALL aufgerufen wird, ob es ELP- und RAMPZ 
gibt, etc.

Johann

von Günter R. (galileo14)


Lesenswert?

Hallo, Johann,

herzlichen Dank! Schöne Thema-Zusammenstellung. Ich werde mich damit 
noch genauer befassen.

Danke Dir.

Günter

von Günter R. (galileo14)


Lesenswert?

Innerhalb von WinAVR gibt es (u.a.) die Directories "avr3", "avr4" und 
"avr5" mit jeweils Bibliotheken "libgcc.a"; man darf dann doch wohl 
davon ausgehen, daß es sich hier jeweils um Compilate für die diversen 
Prozessor-Architekturen handelt, und daß beim Linken anhand des 
mcu-Parameters das richtige Directory ausgewählt wird?

Im Makefile gibt es die Zeilen

MCU = atmega1280         (beispielsweise)
COMMON = -mmcu=$(MCU)
LDFLAGS = $(COMMON)

Genau hier wird wohl dem Linker die Info zugespielt, um welchen 
Prozessor es sich handelt, sodaß er sich dann aber selbst das richtige 
Directory auswählt? Irgendwo muß es also eine Tabelle geben, wo die 
Prozessoren den Architektur-Klassen zugeordnet werden. Ist das die Datei 
"specs" und dort die Zeilen "*multilib_matches:"? Dort finde ich Zeilen 
wie "mmcu=atmega103 mmcu=avr3".

Ist das die Mechanik, die hier angewandt wird? Wie könnte man das für 
eigene Bibliotheken nutzen?

Würde es funktionieren, wenn man seine eigenen Bibliotheken auch in die 
Directories "avr3", "avr4", "avr5" schreiben würde?

von Günter R. (galileo14)


Lesenswert?

Ich habe das mal ausprobiert - scheint zu funktionieren.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Günter R. wrote:

> Irgendwo muß es also eine Tabelle geben, wo die
> Prozessoren den Architektur-Klassen zugeordnet werden. Ist das die Datei
> "specs" und dort die Zeilen "*multilib_matches:"?

Ja, wenn du eine externe specs-Datei hast, dann wird die genommen,
ansonsten gibt es eine entsprechend voreingestellte Tabelle noch
intern eincompiliert.

von Günter R. (galileo14)


Lesenswert?

Ich meinte schon die voreingestellte Tabelle, die auch vom gcc-Linker 
verwendet wird; ich würde dann einfach meine eigenen Bibliotheken per 
Batch in die entsprechenden Directories ("avr3", "avr4" etc.) 
reinkopieren, sonst nichts.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Günter R. wrote:
> Ich meinte schon die voreingestellte Tabelle, die auch vom gcc-Linker
> verwendet wird; [...]

Ich auch.  Die Aussage oben bezieht sich darauf.

Das Kommando "gcc" ist nur der Compiler-Treiber: er nimmt die
Kommandozeilenargumente entgegen und ruft die einzelnen Backend-
Kommandos auf (cc1, cc1plus, as, ld).  Denen gibt er dann die
entsprechenden Argumente mit.  Der Linker selbst weiß also nicht,
wo er das suchen sollte; er bekommt das alles haarklein vom
Compiler-Treiber gesagt, und dieser wiederum benutzt dafür die
specs (entweder extern als Datei, oder einen eincompilierten
internen String).

Das kann man alles mit der Option -v verfolgen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Günter R. wrote:
> Innerhalb von WinAVR gibt es (u.a.) die Directories "avr3", "avr4" und
> "avr5" mit jeweils Bibliotheken "libgcc.a"; man darf dann doch wohl
> davon ausgehen, daß es sich hier jeweils um Compilate für die diversen
> Prozessor-Architekturen handelt, und daß beim Linken anhand des
> mcu-Parameters das richtige Directory ausgewählt wird?

Ja, das sind die ober erwähnten Multilibs von avr-gcc. Die libgcc (nicht 
zu verwechseln mit der libc) wird für jede Derivatfamilie erzeugt.

> Im Makefile gibt es die Zeilen
>
> MCU = atmega1280         (beispielsweise)
> COMMON = -mmcu=$(MCU)
> LDFLAGS = $(COMMON)
>
> Genau hier wird wohl dem Linker die Info zugespielt, um welchen
> Prozessor es sich handelt, sodaß er sich dann aber selbst das richtige
> Directory auswählt? Irgendwo muß es also eine Tabelle geben, wo die
> Prozessoren den Architektur-Klassen zugeordnet werden. Ist das die Datei
> "specs" und dort die Zeilen "*multilib_matches:"? Dort finde ich Zeilen
> wie "mmcu=atmega103 mmcu=avr3".

Ja, das geschieht über specs-File bzw. über die Builtin-Specs von 
avr-gcc.

Allerding wird man üblicherweise den Linker avr-ld nicht direkt 
aufrufen, sondern das Treiberprogramm avr-gcc den Aufruf erzeugen 
lassen.

Im Makefile etwa:
1
MCU_TARGET =atmega8
2
CC         = avr-gcc -mmcu=$(MCU_TARGET)
3
LD         = $(CC)

oder über ähnliche Konstrukte. Damit stimmen dann die Lib-Pfade und auch 
das Startup-File crt*.o, das hinzuzulinken ist sowie sonstige Angaben. 
Ein nackter ld hat kaum Infos, und die müsste man erst mühsam 
zusammentragen.

> Ist das die Mechanik, die hier angewandt wird? Wie könnte man das für
> eigene Bibliotheken nutzen?

Was du suchst ist wohl eine Möglichkeit, gegen selbst erstellte 
Multilibs zu linken oder sie zu erzeugen?

Ersteres könnte so aussehen (ungetestet):
1
%.elf: $(OBJ)
2
  $(LD) $(OBJ) -L$(MY_MULTILIB)/`$(CC) -print-multi-directory` ...

MY_MULTILIB enthält dann Unterverzeichnisse wie avr2, avr3, etc., welche 
die möglichen Multilibs abdecken, d.h. für jedes Derivat, für das gegen 
deine Lib zu linken ist, muss für die Derivat-Familie, der es angehört, 
eine Ausprägung der Lib existieren.

Zur Erzeugung von Multilibs kann die Info per -print-multi-lib hilfreich 
sein.

> Würde es funktionieren, wenn man seine eigenen Bibliotheken auch in die
> Directories "avr3", "avr4", "avr5" schreiben würde?

Ja, aber davon würde ich abraten. Ebenso davon, Header in die 
Systemverzeichnisse zu mischen, damit sie gefunden werden.

Was du brauchst sollte mit -L, -l nebst -print-multi-directory ohne 
eigene specs zu bewerkstelligen sein.

Falls deine Libs feiner granuliert sind als die avr-Multilibs, reicht 
das aber nicht mehr aus. Dann musst du explizit im Makefile angeben, 
wogegen gelinkt werden muss oder mit specs arbeiten.

Johann

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Johann L. wrote:

> Falls deine Libs feiner granuliert sind als die avr-Multilibs, reicht
> das aber nicht mehr aus. Dann musst du explizit im Makefile angeben,
> wogegen gelinkt werden muss oder mit specs arbeiten.

Dann würde es allerdings wohl Sinn haben, dass man gleich eine Lib
per Device baut und
1
LDLIBS += -L$(MY_LIBDIR)/$(MCU)

benutzt.

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
Noch kein Account? Hier anmelden.