Forum: Compiler & IDEs GNU Assembler (avr-as) und Interrupt Vektoren fuer ATmega


von Thorsten (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich habe mir gerade an etwas (fast) die Zaehne ausgebissen:
(Dass der gnu-as einen anderen Pseudo-Op Syntax hat, hab ich schnell
hingekriegt :-|)

Irgendwas stimmt mit den Adressen und dem .org Pseudo im Zusammenhang
mit dem Atmel ATmega (hier ATmega32) nicht:

Wenn ich im *.S-file ein

.org URXCaddr rjmp int_rxc

einfuege und mit avr-as assembliere, zeigt der Atmel Disassembler mir
diesen Befehl an der Adresse 0x0D an, obwohl im m32def.inc file
folgendes steht:

.equ  URXCaddr, 0x01a  ; USART Receive Complete Interrupt Vec

Gebe ich jedoch in das .S file 0x0034 ein, funktioniert es und der
Befehl kommt an die (Atmel)-Adresse 0x001a

Die Erklaerung mag sein, dass avr-as davon ausgeht, dass (zumindest
beim .org Pseudo) immer 8-Bit Bloecke adressiert werden, dagegen fuer
Atmel immer 16-Bit adressiert werden, und daher kommt der schoene
Faktor 2.

(Nur das hex, das der AVR Disassembler `richig' anzeigt, funktioniert
dann auch auf der Zielhardware.)

Gibt es noch andere Fallen, die beim avr-as lauern?
Das heisst ja, man braucht ein ganzes neues Set an *.inc Dateien fuer
den avr-as?
Gibt es jemanden, der den avr-as voellig problemlos einsetzt?

Schoene Gruesse

Thorsten


PS: meine `toolchain' ist:
avr-gcc  -Os -mmcu=ATmega32  -o dram.o dram.S
avr-objcopy -j .text -O ihex dram.o dram.hex

Anbei mein Test-File.

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


Lesenswert?

> Wenn ich im *.S-file ein

> .org URXCaddr rjmp int_rxc

> einfuege ...

.org ist böse. ;-)  Bei einer Toolchain mit verschieblichen
Objektmoduln sollte man .org prinzipiell vermeiden, da es ja erst der
Linker ist, der die einzelnen Objekte an die passenden Stellen im
Speicher schiebt.  Wenn man also bestimmte Dinge an bestimmten
Adressen haben will, sollte man das dem Linker kund tun (in diesem
Falle zum Beispiel über separate .section's, deren Startadressen man
im Linkerscript hinterlegt).

Das hat übrigens gar nichts mit AVR oder GNU-Tools zu tun, das war
schon unter CP/M beim M80 und L80 so.

Dein Beispiel ist dahingehend eine Ausnahme: du hast alles in einer
Datei und benutzt die Verschieblichkeit des Objekts praktisch nicht.

> ..., zeigt der Atmel Disassembler mirdiesen Befehl an der Adresse
> 0x0D an ...

Die Atmel-Tools und -Datenblätter arbeiten im ROM mit 16-bit-Worten
als Einheit, da der ROM im Prinzip so organisiert ist.  ,,Im
Prinzip''
deshalb, weil man ihn mit LPM trotzdem byteweise zugreifen kann.
Außerdem ist es natürlich verwirrend, unterschiedliche
Speicherbereiche mit unterschiedlich großen Wortgrößen innerhalb der
Tools zu adressieren.

Wenn du stattdessen den GNU-Disassembler benutzt (avr-objdump -d),
dann bekommst du auch konsistente Adressierung.

> Das heisst ja, man braucht ein ganzes neues Set an *.inc Dateien
> fuer den avr-as?

Du kannst auch #include <avr/io.h> nehmen, allerdings lies dir bitte
vorher die Doku (in der avr-libc-Doku) durch.  Die IO-Register werden
dann anders benutzt oder du musst einen Kompatibilitätsmodus
einschalten.

> Gibt es jemanden, der den avr-as voellig problemlos einsetzt?

Den GCC? ;-)

> PS: meine `toolchain' ist:
> avr-gcc  -Os -mmcu=ATmega32  -o dram.o dram.S

Das "-Os" ist bedeutungslos, wenn du gar nicht compilierst...
Außerdem benennst du die Ausgabedatei auf .o, was per Konvention
impliziert, dass es sich um ein verschiebliches Objektmodul handeln
würde.  In der Tat lässt du den Compiler aber auch noch den Linker
aufrufen, d. h. die Objektdatei ist nicht mehr verschieblich.  Unter
Unix wäre sie in diesem Falle normalerweise endungslos, in der
AVR-GCC-Welt hat sich der Suffix .elf dafür eingebürgert (obwohl die
verschieblichen .o-Datei ebenfalls ELF-Dateien sind).  Ich bin mir
übrigens nicht ganz sicher, ob der Compiler in dieser Aufrufform noch
die Interruptvektoren aus gcrt1.S mit einbinden will oder nicht,
eigentlich ist diese Aufrufform für C-Code vorbehalten (bei der neben
den Interruptvektoren noch ein minimales Laufzeitsystem für das
Initialisieren der Variablen, den Aufruf von main() und den
abschließenden Aufruf von exit() existiert).  Wie der Linker genau vom
Compiler aus aufgerufen wird, kannst du dir durch hinzufügen der
Option -v sagen lassen.

von Thorsten (Gast)


Lesenswert?

Hallo Jörg!

Vielen Dank fuer Deine ausfuehrliche Antwort!

> .org ist böse. ;-)
Habs nur genau so gemacht, wie den meisten Beispielcode fuer das
AVRStudio auch ... Aber weil alle es machen, muss es ja nicht gut sein
;-)

> Außerdem ist es natürlich verwirrend, unterschiedliche
> Speicherbereiche mit unterschiedlich großen Wortgrößen innerhalb der
> Tools zu adressieren.
Das sollte ins Wiki zum GNU-GCC / avr-as ... weil der selbe Code bei
zwei verschiedenen Assemblern nicht das selbe liefert (selber Code =
bis auf den etwas anderen Syntax = mit sed modifizierter
AVRStudio-Code). I'll do this later.

> Wenn du stattdessen den GNU-Disassembler benutzt (avr-objdump -d),
> dann bekommst du auch konsistente Adressierung.
Das ist korrekt. Deswegen hatte ich gar nicht angefangen, ueber die
`wirkliche' Adresse nachzudenken. Erst als ich das .hex-File
auseinandergenommen habe, wunderte ich mich sehr ...

> Du kannst auch #include <avr/io.h> nehmen,
Fuer dieses einfache Projekt bleib ich erstmal bei quick-and-dirty.
Aber danke, dass Du mich drauf hingewiesen hast, wie man es am besten
und richtigsten macht.
Gibts da irgendwo mal ein Beispielprojekt mit Makefile oder so? Bisher
habe ich immer nur was fuer C/C++ gefunden.

>> Gibt es jemanden, der den avr-as voellig problemlos einsetzt?
> Den GCC? ;-)
Ich dachte an einen Menschen, der damit handgeschriebenen
Assembler-Code assembliert und in den AVR laedt. Wie gesagt, die
meisten scheinen ja nur C/C++ einzusetzen.

Schoene Gruesse

Thorsten

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


Lesenswert?

>> Du kannst auch #include <avr/io.h> nehmen,

> Gibts da irgendwo mal ein Beispielprojekt mit Makefile oder so?
> Bisher habe ich immer nur was fuer C/C++ gefunden.

http://www.nongnu.org/avr-libc/user-manual/assembler.html

>>> Gibt es jemanden, der den avr-as voellig problemlos einsetzt?

>> Den GCC? ;-)

> Ich dachte an einen Menschen, der damit handgeschriebenen
> Assembler-Code assembliert und in den AVR laedt. Wie gesagt, die
> meisten scheinen ja nur C/C++ einzusetzen.

Naja, wenn man die GNU-Tools installiert hat, dann vermutlich in
erster Linie nicht, um damit Assemblerprojekte zu realisieren.  Was
aber eher der Fall sein dürfte ist, dass man eine einzelne
Assemblerdatei (zum Beispiel für einen Interrupthandler) in ein
C-Projekt mit einbindet.

Für letzteres habe ich auch mal ein Beispiel für die avr-libc-Doku
angefangen, aber das ist noch nicht bis zur Veröffentlichung gelangt
bislang.

von André K. (freakazoid)


Lesenswert?

Hiho.

Momentan hab ich den ENC28J60-Teil + ARP/ICMP/UDP/TCP/IRQ-Handling in
Assembler und das ganze 'drumherum' in C.
Alles mit AVR-GCC/AVR-AS ;-)

Es geht also. Über den Sinn läßt sich streiten, aber ich wollte eine
kleine TCP-Lib haben (schreibt man ja nicht immer neu das Teil) und die
Bequemlichkeit von C, bzw dem Linker für den Rest.

Ich verstehe es irgendwie nicht große Assemblerprojekte zu erstellen,
die dann haufenweise .asm-Dateien oder .inc-Dateien einbinden. Das gibt
doch bestimmt haufenweise Redefines, doppelten Code und sonstigen nicht
bedachten Quatsch.
Vielleicht fehlt mir dazu auch die Disziplin. Aber dafür gibt's ja die
Tool-Chain ;-)

Grüße, Freakazoid

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.