Hallo, ich habe ein Programm umgeschrieben von einem anderen assembler auf den avr-gcc bzw. avr-as. Die Dateien bekomme ich einwandrei compiliert. Nur mit dem Linken klappt es nicht so. Compiliert habe ich mit diesem Befehl: "avr-gcc -c -mmcu=at90s2313 -I. -x assembler-with-cpp -Wa,-adhlns=kernel.lst,-gstabs Datei1.S -o Datei1.o" Nur mit dem Linken klappt es nicht. Wenn ich alle Dateien mit dem avr-gcc linken will muss immer eine C-Datei dabei sein. Der Befehl sieht dann folgendermassen aus: "avr-gcc -mmcu=at90s2313 -I. -g -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.o -std=gnu99 main.o datei1.o datei2.o datei3.o --output main.elf -Wl,-Map=main.map,--cref -lm" Das Programm läuft dann auch solange bis der erste interrupt kommt. In den Assembler-Dateien sind feste org-Anweisungen. Dies darf aber wohl nicht sein wenn eine main.c dabei ist. Wie muss der Linkeraufruf aussehen wenn ich nur die Assembler-Dateien linken will? Danke Andreas
> In den Assembler-Dateien sind feste org-Anweisungen. Dies darf aber > wohl nicht sein wenn eine main.c dabei ist. .org kannst du für jegliche Toolchain vergessen, die verschieblichen Objektcode mit anschließendem Linken benutzt. D.h., es war eigentlich schon vor 20 Jahren unter CP/M ,,out''. Sogar das CP/M selbst wurde aus verschieblichen Objektmoduln gelinkt und hat statt .org .phase benutzt. Ja, ich weiß, dass der Linker durchaus auch mit .org zurecht kommt, aber vergiss es dennoch, es hat keinen Sinn. Wenn du irgendwas auf eine bestimmte Adresse haben willst, dann sag das dem Linker, nicht dem Assembler (z.B. indem man dafür eine eigene section aufmacht und mit --section-start arbeitet). > Wie muss der Linkeraufruf aussehen wenn ich nur die > Assembler-Dateien linken will? Typischerweise linkt man, wenn man das C-Laufzeitsystem dabei haben will (also vor allem die Startup-Routinen, Interruptvektoren etc.) über einen Aufruf von avr-gcc, weil der sich um den Rest kümmert. Wenn du in die Kommandozeile ein -v mit aufnimmst, siehst du, was der Compiler dem Linker alles mit auf die Reise gibt. Wenn du ausschließlich Assemblerdateien hast und auch Dinge wie die Interruptvektoren komplett selbst schreiben willst, dann kannst du den Linker ,,zu Fuß'' aufrufen. Sehr wahrscheinlich musst du dann auch deinen eigenen Linkerscript zimmern oder du hälst dich an die Konventionen, die das C-Laufzeitsystem benutzt und nimmst dessen Linkerscript -- aber dann stellt sich die Frage, warum du's überhaupt noch zu Fuß machen willst. Falls du was Konkretes im Auge hast, solltest du natürlich auch konkret werden. ,,Es geht nicht'' ist keine sinnvolle Beschreibung.
Hallo Jörg, danke für die Antwort. Mein "es geht nicht" war darauf bezogen, dass das Programm anläuft dann aber beim ersten Interrupt hängenbleibt. Zwischenzeitlich bin ich einen Schritt weiter. Ich muss nur die C-Datei weglassen und in die Assembler-Datei ein label main: einfügen. Dann geht es soweit. Der Grund warum ich das mit dem avr-gcc statt avr-as machen will ist, dass es erhebliche #defines in den Header-Dateien des Assembler-Programms gibt. Das würde mir einiges an Arbeit sparen. Mit den interrupt-adressen werde ich noch weitersehen. Das stört mich im Moment noch nicht. Weiss aber ungefähr wie Du das meinst. Jetzt habe ich aber ein neues Problem. Meine Variablen deklariere ich folgendermassen: .comm X,1 .comm Y,1 .comm Z,1 Jetzt hätte ich gerne, dass der Linker mir die alle hintereinander setzt. Sie werden aber irgendwo hin gepackt. z.B. erhält X die Adresse 0x88, Y = 0x8C und Z= 0x80. Ich benötige die aber unbedingt hintereinander. Die drei Variablen waren jetzt nur ein Beispiel mit denen ich es aber tatsächlich nochmal ausprobiert habe weil ich mir nicht sicher war. Wie sag ich es dem Linker? KAnn ich mir irgendwie eine Liste ausdrucken lassen mit den Adressen der einzelnen Variablen. Im moment rufe ich immer AVR-Studio auf. Das ist mir zu umständlich. Danke Andreas
> Zwischenzeitlich bin ich einen Schritt weiter. Ich muss nur die > C-Datei weglassen und in die Assembler-Datei ein label main: > einfügen. Ja, das ist das, was die C-runtime aufruft. (Variablenanordnung) > Jetzt hätte ich gerne, dass der Linker mir die alle hintereinander > setzt. Nö, die Reihenfolge ist komplett dem Linker überlassen. Du musst eine große Variable anlegen und darin mit Offsets arbeiten (das ist letztlich das, was der Compiler bei einer struct macht). > Wie sag ich es dem Linker? Wenn du das partout so haben willst, dann nur über einen custom linker script und eine section für jede Variable. Ist 'ne ziemliche Kanone für so einen Spatzen... > KAnn ich mir irgendwie eine Liste ausdrucken lassen mit den Adressen > der einzelnen Variablen. Klar, das nennt sich Symboltabelle und wird von avr-nm generiert. > Im moment rufe ich immer AVR-Studio auf. Das ist mir zu umständlich. Das verstehe ich. ;-) Wo kann man sich denn dort die Symboltabelle angucken? Ich habe das neulich gesucht (weil ich nur eine UBROF-Datei vom IAR hatte, die man sonst mit nichts bearbeiten kann) und nix gefunden außer dem kompletten Disassemblerlisting, in dem man weder suchen kann noch kann man es in direkt in eine Datei abspeichern. cut&paste geht zwar, ist aber schweinig lahmarschig beim Image eines ATmega128, der nur zu 20 % gefüllt ist...
Danke für die Antwort. Das mit dem avr-nm habe ich auch schon gefunden. Das stimmten die Adressen mit dem Avr-Studio überein. Nee im Avr-Studio gibt es solch eine Tabelle nicht. Habe ich mal wieder nicht klar beschrieben weil ich es nicht wichtig fand. Ich greife direkt am Programmanfang zum Test auf die Variablen mit sts zu. Nur um die Adresse rauszubekommen. Ich lese die reine Hex-Datei des avr-gcc in Avr-Studio ein und weiss dann, wenn der sts-Befehl kommt, dass es sich um die entsprechende Variable handelt. Was einfacheres ist mir nicht eingefallen.
Ich habe trotzdem nochmal eine Frage. Bei der Durchsicht der von avr-nm erzeugten Tabelle ist mir aufgefallen, dass der gcc Variablen in Speicherbereiche anlegt, die der Controller überhaupt nicht hat. Hierüber hatte ich mich auch schon beim debuggen mit avr-studio festgestellt. Beispiel: angegeben hatte ich im Makefile: MCU = at90s2313 Folgenden Variablen hatten die entsprechenden Adressen erhalten: 008000e0 B sTxMsgBuf 008000f0 B RxId_1 008000f8 B TxBuf 00800100 B RxBuf_1 00800108 B TxLen 00800109 B RxLen_1 0080010a B TxId Der Speicherbereich des 2313 geht aber nur bis $DF. Was habe ich denn hier beim Aufruf falsch gemacht? Danke schon mal im Voraus Andreas
Nichts. Die 0x800000 sind der Offset, der kennzeichnet, dass diese Variable im RAM liegt. Das ist 'ne Krücke, damit der GCC die Harvard-Architektur (für die er nie konzipiert worden ist) überhaupt irgendwie schluckt. Der EEPROM hat Offset 0x810000.
Das ist schon klar. Das meinte ich auch anders. Aber wenn ich z.B. von der "0080010a B TxId" die 800000 abziehe, hat die immer noch die Adresse 10a. Das geht über den Speicherbereich des 2313 hinaus.
> Das geht über den Speicherbereich des > 2313 hinaus. Das ist natürlich wahr... War mir nicht aufgefallen, ich habe lange nichts mehr mit so kleinen AVRs gemacht. Ich denke, da hast du wohl insgesamt ein Problem.
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.