Forum: Compiler & IDEs avr-gcc Assembler Probleme!


von Zero V. (Firma: Angestellter/Freelancer) (gnd)


Lesenswert?

Hi,

Ich versuche einen ATmega8 in Assembler(avr-gcc) unter Linux zu 
programmieren.
1
avr-gcc -c -Wall -Wextra -mmcu=atmega8 ./test.S -o ./test.elf
Ist -c (compile do not link) vielleicht falsch?
Wenn ich ohne -c starte kommt die Fehlermeldung: "undefined reference to 
main".

Wie kann ich mir den fertigen Assembler-Code vom avr-gcc anzeigen lassen 
(also was er aus meinem macht)?
1
#define __SFR_OFFSET 0
2
#include <avr/io.h>
3
...
4
.org 0x000
5
rjmp RESET
6
7
RESET:
8
ldi r16, 0xFF
9
out DDRD, r16
10
11
ldi r16, 0xFF
12
out PORTD, r16
13
14
end: rjmp end

aus iom8.h
1
/* Port D */
2
#define PIND    _SFR_IO8(0x10)
3
#define DDRD    _SFR_IO8(0x11)
4
#define PORTD   _SFR_IO8(0x12)
aus sfr_defs.h
1
#ifndef __SFR_OFFSET
2
/* Define as 0 before including this file for compatibility with old asm
3
   sources that don't subtract __SFR_OFFSET from symbolic I/O addresses.  */
4
#  if __AVR_ARCH__ >= 100
5
#    define __SFR_OFFSET 0x00
6
#  else
7
#    define __SFR_OFFSET 0x20
8
#  endif
9
#endif
10
...
11
#define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)

Jetzt habe ich #define __SFR_OFFSET 0 in meinem Code, weil ohne gibts 
Fehlermeldungen (...must be less than 32 bei SBIS PORTD[im späteren 
code]).
Wenn SFR_OFFSET 0x20 ist funktioniert OUT, aber bei SBIS PORTD z.B 
funktionierts nicht mehr, da müsste denn für I/O Register 0x20 
substrahiert werden ???
Nun weiß ich nicht wie man das nun korrekt macht ???

Danke für Tipps!

von Spess53 (Gast)


Lesenswert?

Hi

>Wenn SFR_OFFSET 0x20 ist funktioniert OUT, aber bei SBIS PORTD z.B
>funktionierts nicht mehr, da müsste denn für I/O Register 0x20
>substrahiert werden ???

Dir ist aber klar, das der mögliche Adressbereich von 'sbis/sbis' 
kleiner als der von 'in/out' ist?

MfG Spess

von Zero V. (Firma: Angestellter/Freelancer) (gnd)


Lesenswert?

Spess53 schrieb:
> Dir ist aber klar, das der mögliche Adressbereich von 'sbis/sbis'
> kleiner als der von 'in/out' ist?

Ja SBIS (0 - 31(0x1F)) und OUT/IN (0 - 63(0x3F))

von Spess53 (Gast)


Lesenswert?

Hi

Dann verstehe ich deine Frage

>Wenn SFR_OFFSET 0x20 ist funktioniert OUT, aber bei SBIS PORTD z.B
>funktionierts nicht mehr, da müsste denn für I/O Register 0x20
>substrahiert werden ???
>Nun weiß ich nicht wie man das nun korrekt macht ???

nicht so richtig. Für IO-Register >= 100 wird die Speicheradresse 
benutzt und es wird mit sts/lds auf die Register zugegriffen. Bei 
Adressen zwischen 32 und 99 werden 0x20 von der Speicheradresse 
abgezogen und in/out, und eingeschränkt sbic/sbis, verwendet.

MfG Spess

von eProfi (Gast)


Lesenswert?

> Wenn ich ohne -c starte kommt die Fehlermeldung: "undefined reference to
main".

Die Fehlermeldung kommt wohl vom Linker. Wenn Du diesen ausschaltest, 
kommt sie nicht.

Kannst Du mal komplette files / das Projekt anhängen?

von Zero V. (Firma: Angestellter/Freelancer) (gnd)


Lesenswert?

1
#define __SFR_OFFSET 0
2
3
#include <avr/io.h>
4
5
#define tmp r16
6
7
#define MIN r17
8
#define HOUR r18
9
10
.text
11
12
.org 0x000
13
  rjmp RESET
14
15
RESET:
16
17
  ldi MIN, 0x00
18
  ldi HOUR, 0x00
19
20
  ldi tmp, 0xFF
21
  out DDRD, tmp
22
  ldi tmp, 0xFF
23
  out PORTD, tmp
24
test:  RJMP test ; !!! ENDLOSSCHLEIFE zum TESTEN
25
26
  ldi tmp, 0x00  ;input Taster PINC0, PINC1 
27
  out DDRC, tmp
28
  ldi tmp, 0x03
29
  out PORTC, tmp
30
31
32
WHILE:  in tmp, PORTC
33
  sbis PORTC, 0
34
  inc MIN
35
  out PORTD, MIN
36
  sbis PORTC, 1
37
  inc HOUR
38
39
  ldi tmp, 0xFF
40
WAIT:  dec tmp
41
  brne WAIT
42
  rjmp WHILE
1
#!/bin/bash
2
avr-gcc -Wall -Wextra -mmcu=atmega8 -O0 ./test.S -o ./test.elf
3
avr-objcopy -j .text -j .data -O ihex ./test.elf ./test.hex
4
sudo avrdude -c avr910 -p m8 -P /dev/ttyUSB0 -e -U ./test.hex

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

James Bonddraht schrieb:

> Ich versuche einen ATmega8 in Assembler(avr-gcc) unter Linux zu
> programmieren.
>
1
avr-gcc -c -Wall -Wextra -mmcu=atmega8 ./test.S -o ./test.elf
> Ist -c (compile do not link) vielleicht falsch?

Ja. -c macht preprocess, compile and assemble.  Das ist nur ein Teil. 
Du will auch den Linker Symbole und Relocations auflösen lassen, Daten 
und Funktionen lokatieren lassen, etc.

> Wenn ich ohne -c starte kommt die Fehlermeldung: "undefined reference to
> main"

Weil es keine main gibt.

In C-Programmen gibt es eben immer eine main, und da du avr-gcc als 
Treiber verwendest, werden auch C-Bibliotheken wie libgcc, (AVR-)libc 
und Start-Up Code crt*.o hinzugebunden.

Der Startup-Code initialisiert den µC (SP, R1, .data, .bss), ruft 
Konstruktoren auf (.ctors, .dtors) und schliesslich main, exit und 
Destruktoren (.dtors), weiters definiert crt*.o die Vektor-Tabelle.

avr-gcc ist nur ein Treiber-Programm, das anhand von -c/-S/-E etc. 
Sub-Programme aufruft und mit adäquaten Kommandozeilenoptionen versort.

> Wie kann ich mir den fertigen Assembler-Code vom avr-gcc anzeigen lassen
> (also was er aus meinem macht)?

avr-gcc ruft nur den Präprozessor auf, der die # auflöst.  Das bekommst 
du mit -save-temps.  Danach kannst du Dumps/Disassemblies vom Assembler 
erzeugen lassen, Disassemblies mit objdump und Map-Files vom Linker.

> .org 0x000
> rjmp RESET
>
> RESET:

Lass das .org weg.  Das ist keine absolute Adresse.
Eher sowas, damit zB in der Vector-Tabelle kein Relaxing stattfindet und 
.vectors garantiert bei 0 liegt:
1
#include <avr/io.h>
2
3
;; AVR-Libc definiert leider keinen RESET_vect
4
#define RESET_vect_num  0
5
#define RESET_vect      _VECTOR (RESET_vect_num)
6
7
;; Vector-Tabelle
8
.section .vectors,"ax",@progbits
9
.global  __vectors
10
__vectors:
11
    rjmp  RESET_vect
12
13
14
;; Programm
15
.text
16
17
RESET_vect:
18
    ;; Code

Das ganze braucht du natürlich nur, wenn du ohne C-Umgebung arbeitest, 
d.h. sowas wie -Wl,-nostdlib -Wl,-nodefaultlibs -nocrt0.
Wie die Optionen genau sind sagt die Doku, hab ich jetzt nicht im Kopf.

Mit C-Umgebung siehts einfach so aus:
1
#include <avr/io.h>
2
3
.text
4
5
;; Eine ISR
6
.global TIMER1_COMPA_vect
7
TIMER1_COMPA_vect:
8
    reti
9
10
;; Programmstart nach crt*.o
11
.global main
12
main:
13
    ;; Code

von Zero V. (Firma: Angestellter/Freelancer) (gnd)


Lesenswert?

Danke schonmal!

Ich bin damit leider völlig überfordert.
Woher hast du dein Wissen, woher komme ich an mehr 
Hintergrundinformationen (alle man-pages möchte ich nun nicht lesen)!

Und wie würdest du das fertige Assembler-Programm übersetzen?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

James Bonddraht schrieb:

> Woher hast du dein Wissen,

Schwer zu sagen.  Ich weiß auch nicht mehr, wo und wann ich gelernt hab, 
dass Deutschland an Frankreich grenzt...

> woher komme ich an mehr Hintergrundinformationen
> (alle man-pages möchte ich nun nicht lesen)!

man ist hier nicht sehr gehaltvoll, aber keine Doku zu lesen ich ein 
ganz schlechter Anfang.  Brauch man zwar nicht komplett durchzulesen, 
aber 5 Minuten überfliegen, um im entscheidenden Moment zu wissen, wo 
man was nachschaut, ist Gold wert und spart im Endeffekt viel Zeit und 
Nerven.

Da sind zunächst die Doku der Binutils [1], des Compilers [2] und 
der AVR-Libc [3].

Startup-Code der AVR-Libc, i.W. die Quelle der crt*.o, findet sich in 
[4] und die entsprechenden Teile des Startup-Codes, den die libgcc [5] 
beisteuert, ist das, was in .init-Sections steht.

Weiters gibt es ein Tutorial nebs Dome-Projekten [6] in der AVR-Libc.

Schliesslich ist es auch hilfreich, dem Tools bei der Arbeit 
zuzuschauen:

- Welchen Code erzeugt der Compiler?
- Wie ruft er Assembler und Linke auf?
- Was steht in eim Map-File?
- Welche Standard-Sections gibt es und wozu dins die gut?
  .data, .text, .progmem, .init, .vectos, .comment, .rodata, .bss, ...
- Wie sieht das Disassembly aus?

> Und wie würdest du das fertige Assembler-Programm übersetzen?

Kommt drauf an ob du Bare-Metal magst oder den flauschigen Unterbau 
der AVR-Libc bevorzugst mit ihren Headerm, I/O-Definitionsn, 
Startup-Code, Vektor-Tabelle, ...


[1] http://sourceware.org/binutils/docs-2.22/
[2] http://gcc.gnu.org/onlinedocs/
[3] http://www.nongnu.org/avr-libc/user-manual
[4] 
http://svn.savannah.nongnu.org/viewvc/trunk/avr-libc/crt1/gcrt1.S?&root=avr-libc&view=markup
[5] 
http://gcc.gnu.org/viewcvs/trunk/libgcc/config/avr/lib1funcs.S?revision=190644&view=markup
[6] http://www.nongnu.org/avr-libc/user-manual/group__asmdemo.html

von makefile (Gast)


Lesenswert?

@gjlayde

Zu den crts ein kleiner avr-gcc Bug Report:
-mmcu=at90usb1287 bindet crtusb1286 statt crtusb1287 ein.

Falscher Eintrag in der avr-mcus.def?

Macht programmtechnisch keinen Unterschied, da beide bis auf den Namen
identisch sind. In meinem Build-System baue ich die libc aber explizit
für ein Device und dabei ist es gerade aufgefallen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

makefile schrieb:

> Zu den crts ein kleiner avr-gcc Bug Report:
> -mmcu=at90usb1287 bindet crtusb1286 statt crtusb1287 ein.
>
> Falscher Eintrag in der avr-mcus.def?

Ja, mach bitte nen Bugreport dafür. Danke.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

makefile schrieb:

> Zu den crts ein kleiner avr-gcc Bug Report:
> -mmcu=at90usb1287 bindet crtusb1286 statt crtusb1287 ein.

Ist behoben:

http://gcc.gnu.org/viewcvs/trunk/gcc/config/avr/avr-mcus.def?revision=191132&view=markup#l198

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.