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?
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.
Du meinst sicher die Sache mit "avr1" ... "avr5"? Dann liege ich wahrscheinlich bei meiner o.g. Auswahl mit "atmega128" nicht ganz falsch.
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.
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
Hallo, Johann, herzlichen Dank! Schöne Thema-Zusammenstellung. Ich werde mich damit noch genauer befassen. Danke Dir. Günter
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?
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.
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.
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.