Forum: Mikrocontroller und Digitale Elektronik avr-tutorial timer, interruptvektor ist nicht definiert


von ALB (Gast)


Lesenswert?

hallo,
ich beschäftige mich gerade mit dem avr-gcc tutorial auf dieser seite 
und habe eine problem bei den timern. ich will den overflow interrupt 
vom timer1 abfragen. habe schon rausgefunden das der interuptvektor bei 
meinem atmega32 etwas anders heißt als im tutorial. nämlich: TIMER1_OVF. 
also sollte ich ihn doch folgendermaßen benutzen:

#include <avr/interrupt.h>

.text                              ; was nun folgt, gehört in den 
FLASH-Speicher

.global main                       ; main ist auch in anderen Modulen 
bekannt
 temp = r24
.org 0x0000
        rjmp    main                  ; Reset Handler
.org TIMER1_OVF_vect
        rjmp    timer1_overflow       ; Timer Overflow Handler

main:                              ; zu 'main' wird nach Reset 
hingesprungen
        LDI R24, 0xFF
        OUT _SFR_IO_ADDR(DDRA), R24  ;port a als ausgabe setzten
        OUT _SFR_IO_ADDR(PORTA), R24 ;ale pins auf 1

        ldi     r16, 0b00000010      ; CS00 setzen: Teiler 8
        OUT _SFR_IO_ADDR(TCCR1B) , R16

        ldi     r16, 0b00000100      ; TOIE0: Interrupt bei Timer 
Overflow
        OUT _SFR_IO_ADDR(TIMSK), r16

        ldi r17,0x00
        sei

  rjmp Hauptschleife


Hauptschleife:





        rjmp Hauptschleife
timer1_overflow:                      ; Timer 0 Overflow Handler
        OUT _SFR_IO_ADDR(PORTB), r17
        com     r17
        reti

ich bekomme dann folgende fehlermeldung vom compiler:
p4real@noname:~/avr$ avr-gcc -mmcu=atmega32 test.S
test.S: Assembler messages:
test.S:10: Warning: symbol "__vector_9" undefined; zero assumed
test.S:10: Error: attempt to move .org backwards

da steht etwas von vector9(das ist der vektor für den timer1 overflow 
interrupt) jetzt habe ich aber keine ahnung warum der nicht definiert 
ist.

von Jean P. (fubu1000)


Lesenswert?

Prust.
1.)Also als erstes solltest du dir überlegen, ob du in C oder ASM 
programmieren willst.

2.)Wenn du das weißt, versuchs noch einmal selber.
Wenn es dann wieder nicht klappt, melde dich nochmal.

Gruß.

von Johannes M. (johnny-m)


Lesenswert?

Fabian Ostner wrote:
> Prust.
> 1.)Also als erstes solltest du dir überlegen, ob du in C oder ASM
> programmieren willst.
Er hat sich bereits für Assembler entschieden. Was gibt es da 
auszusetzen? Wenn man keine Ahnung hat, sollte man mit solchen 
Äußerungen sehr vorsichtig sein.

@ALB:
Ich meine, mich erinnern zu können, dass es mit den Vektoradressen 
sowieso in gnu-asm ein kleines Problem gab (gnu-asm arbeitet mit 
Byte-Adressen, nicht mit Wort-Adressen wie der ATMEL-AVR-ASM).

Wirf mal einen Blick in den Thread:
Beitrag "Atmel ASM portieren"
Möglicherweise sind da schon ein paar Deiner Probleme behandelt.

EDIT:
Ach ja, die avr/io.h fehlt natürlich, weshalb der den Vektornamen auch 
nicht kennt. Wundert mich nur, dass es nicht mehr Fehlermeldungen 
gibt...

von Chris :. (fr34k)


Lesenswert?

>habe schon rausgefunden das der interuptvektor bei
>meinem atmega32 etwas anders heißt als im tutorial. nämlich: TIMER1_OVF.

Ich hoff ich schreib jetzt keinen blödsinn, aber soweit ich mich 
erinnern kann heißt der vektor: TMR1_OVF

wie gesagt, ich hab jetzt grad weder datenblatt noch sonstwas bei der 
hand, is nur ne erinnerung ....

von ALB (Gast)


Lesenswert?

danke,
der beitrag hat geholfen. (suchfunktion hatte ich zwar auch benutzt, 
aber den hab ich nicht gefunden)

TIMER1_OVF_vect versteht der assembler nicht. also habe ich die 
speicheradresse direkt angegeben, was in meinem fall 0x008 ist.

@ Johannes M. : die avr/io.h hab ich nur versehentlich nicht mit ins 
forum kopiert, sorry

jetzt kann der code ohne Fehler und wahrnungen compiliert werden, aber 
blinken tut trotzdem nichst. `_´ Nur dauerleuchten.
hab den code rauf und runter gelesen und alles nochma geprüft. keine 
ahnung woran es liegt. kann vielleicht nochmal einer von euch füchsen 
nen blick drauf werfen?

#include <avr/io.h>
#include <avr/interrupt.h>

.text                              ; was nun folgt, gehört in den 
FLASH-Speicher

.global main                       ; main ist auch in anderen Modulen 
bekannt


.org 0x0000
        rjmp    main                  ; Reset Handler
.org 0x008
        rjmp    timer1_overflow       ; Timer Overflow Handler

main:                              ; zu 'main' wird nach Reset 
hingesprungen
        LDI R24, 0xFF
        OUT _SFR_IO_ADDR(DDRA), R24  ;port a als ausgabe setzten
  OUT _SFR_IO_ADDR(PORTA), R24 ;alle pins auf 1

        ldi     r16, 0b00000010      ; CS00 setzen: Teiler 8
        OUT _SFR_IO_ADDR(TCCR1B) , R16

        ldi     r16, 0b00000100      ; TOIE0: Interrupt bei Timer 
Overflow
        OUT _SFR_IO_ADDR(TIMSK), r16
   ldi r17,0x00
        sei

  rjmp Hauptschleife


Hauptschleife:

        rjmp Hauptschleife
timer1_overflow:                      ; Timer 1 Overflow Handler
        OUT _SFR_IO_ADDR(PORTA), r17
        com     r17
        reti

von Falk B. (falk)


Lesenswert?

@ ALB (Gast)

>TIMER1_OVF_vect versteht der assembler nicht. also habe ich die
>speicheradresse direkt angegeben, was in meinem fall 0x008 ist.

Tu uns und vor allem DIR einen grossen Gefallen und vergiss den GCC 
Assembler. Dessen Syntax ist inkompatibel zum AVR-Studio. Und so gut wie 
keiner verwendet ihn. Du wirst also auf verlorenem Posten kämpfen.

MFG
Falk

von Stefan B. (stefan) Benutzerseite


Lesenswert?

ALB wrote:

> ...aber
> blinken tut trotzdem nichts. `_´ Nur dauerleuchten.

Was sagt denn deine Theorie zur Blinkgeschwindigkeit?

Ohne den Code zu prüfen: Wenn es zu schnell fürs Auge ist, gibt es 
Dauerleuchten sowie wenn es zu langsam ist und gleichzeitig mit Licht an 
gestartet wird, dann auch...

von ALB (Gast)


Lesenswert?

@falk: ja so lansam kotzt mich dieses ding auch an. kennt jemand einen 
avr-studio kompatiblen assembler für linux?

von ALB (Gast)


Lesenswert?

@steffan: also an der geschwindigkeit sollte es nicht liegen. 16 bit 
zähler zählt bis 65536, vorteiler 8 => zählt etwa 500000 takte, bei 1MHz 
schaltet er 2 mal pro sekunde.

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


Lesenswert?

Falk Brunner wrote:

> Tu uns und vor allem DIR einen grossen Gefallen und vergiss den GCC
> Assembler. Dessen Syntax ist inkompatibel zum AVR-Studio. Und so gut wie
> keiner verwendet ihn.

Das ist, mit Verlaub, Quatsch.

Das Teil vom AVR Studio ist ein einfachster Absolutassembler, der zu
nicht viel taugt.  Eric Weddington hätte ihn lieber heute als morgen
komplett abgeschossen, da der Aufwand für die Parallelentwicklung
unsinnig ist.  Das scheitert eigentlich nur noch daran, dass mal
jemand einen Script zimmern muss, der die Syntax des alten und völlig
standalone gezimmerten Atmel-Assemblers in GNU-Syntax automatisch
überführt.  Wenn man einen solchen Script hat, kann man das Atmel-Teil
durch einen CLI-kompatiblen Wrapper ersetzen, der im Hintergrund den
gas aufruft.

Um den GNU-Assembler führt insgesamt ohnehin kein Weg herum, da der
Atmel-Assembler nicht in der Lage ist, verschiebliche Objekte zu
erzeugen, ganz zu schweigen von ELF-Dateien.  Das beides braucht man
aber, wenn man ihn als Backend für einen Compiler nehmen will.  Damit
ist die Weiterentwicklung des gas für den AVR praktisch garantiert und
zwingend notwendig (obwohl der GCC selbst durchaus auch andere
Assembler aufrufen könnte).

Ein Hinweis für den OP: .org ist außerhalb eines Absolutassemblers
kein sinnvoller Befehl.  Die Zuordnung der Speicheradressen erledigt
dort der Linker.  Zwar kann man auch Assemblerdateien komplett über
den Compiler als Frontend bearbeiten lassen, aber beim Linken sollte
man entweder den Linker mit avr-ld explizit selbst aufrufen, oder
du benutzt -nostartfiles, damit du deinen eigenen Startupcode
definieren kannst.  Im Moment wirft dein avr-gcc-Kommando sowohl den
Assembler (mit C-Präprozessor) als auch gleich danach den Linker an,
d. h. beide Schritte werden im Hintergrund durch ein einziges
Kommando ausgeführt.

Dein Beispiel ist leider schlecht formatiert, da du keine Code-
Markierungen benutzt hast.  Folgende Variante sollte funktionieren:
1
#include <avr/io.h>
2
3
.global main
4
main:                              ; zu 'main' wird nach Reset hingesprungen
5
        LDI R24, 0xFF
6
        OUT _SFR_IO_ADDR(DDRA), R24  ;port a als ausgabe setzten
7
        OUT _SFR_IO_ADDR(PORTA), R24 ;ale pins auf 1
8
9
        ldi     r16, 0b00000010      ; CS00 setzen: Teiler 8
10
        OUT _SFR_IO_ADDR(TCCR1B) , R16
11
12
        ldi     r16, 0b00000100      ; TOIE0: Interrupt bei Timer Overflow
13
        OUT _SFR_IO_ADDR(TIMSK), r16
14
15
        ldi r17,0x00
16
        sei
17
18
Hauptschleife:
19
        rjmp Hauptschleife
20
21
.global TIMER1_OVF_vect
22
TIMER1_OVF_vect:                      ; Timer 0 Overflow Handler
23
        OUT _SFR_IO_ADDR(PORTB), r17
24
        com     r17
25
        reti

Kommando:
1
avr-gcc -mmcu=atmega32 -o timer.elf timer.S

Damit wird der Startup-Code des C-Laufzeitsystems benutzt,
einschließlich deren Interruptvektortabelle.  Daher muss das
Hauptprogramm auch zwingend ein globales Symbol namens main
sein und die Interruptvektornamen müssen globale Symbole mit den
entsprechenden Makronamen aus <avr/io.h> sein.

Wenn du das nicht willst, sondern alles selbst unter Kontrolle haben
willst, dann wäre das hier die Variante:
1
#include <avr/io.h>
2
3
        jmp     Hauptprogramm
4
        jmp     INT0_vector
5
        jmp     INT1_vector
6
        jmp     TIMER2_COMP_vector
7
        jmp     TIMER2_OVF_vector
8
        jmp     TIMER1_CAPT_vector
9
        jmp     TIMER1_COMPA_vector
10
        jmp     TIMER1_COMPB_vector
11
        jmp     TIMER1_OVF_vector
12
        jmp     TIMER0_OVF_vector
13
        jmp     SPI_STC_vector
14
        jmp     USART_RXC_vector
15
        jmp     USART_UDRE_vector
16
        jmp     USART_TXC_vector
17
        jmp     ADC_vector
18
        jmp     EE_RDY_vector
19
        jmp     ANA_COMP_vector
20
        jmp     TWI_vector
21
        jmp     INT2_vector
22
        jmp     TIMER0_COMP_vector
23
        jmp     SPM_RDY_vector
24
25
Hauptprogramm:
26
        LDI R24, 0xFF
27
        OUT _SFR_IO_ADDR(DDRA), R24  ;port a als ausgabe setzten
28
        OUT _SFR_IO_ADDR(PORTA), R24 ;ale pins auf 1
29
30
        ldi     r16, 0b00000010      ; CS00 setzen: Teiler 8
31
        OUT _SFR_IO_ADDR(TCCR1B) , R16
32
33
        ldi     r16, 0b00000100      ; TOIE0: Interrupt bei Timer Overflow
34
        OUT _SFR_IO_ADDR(TIMSK), r16
35
36
        ldi r17,0x00
37
        sei
38
39
Hauptschleife:
40
        rjmp Hauptschleife
41
42
TIMER1_OVF_vector:                      ; Timer 0 Overflow Handler
43
        OUT _SFR_IO_ADDR(PORTB), r17
44
        com     r17
45
        reti
46
47
; leere Vektoren
48
49
INT0_vector:
50
INT1_vector:
51
TIMER2_COMP_vector:
52
TIMER2_OVF_vector:
53
TIMER1_CAPT_vector:
54
TIMER1_COMPA_vector:
55
TIMER1_COMPB_vector:
56
TIMER0_OVF_vector:
57
SPI_STC_vector:
58
USART_RXC_vector:
59
USART_UDRE_vector:
60
USART_TXC_vector:
61
ADC_vector:
62
EE_RDY_vector:
63
ANA_COMP_vector:
64
TWI_vector:
65
INT2_vector:
66
TIMER0_COMP_vector:
67
SPM_RDY_vector:
68
        rjmp    .-2

Kommando:
1
avr-gcc -mmcu=atmega32 -nostartfiles -o timer.elf timer.S

Hier bist du in der Namensvergabe völlig frei, dafür musst du die
Interruptvektortabelle selbst aufbauen.  Sinnvoller Weise baut man
sie komplett ein, wenngleich im Prinzip eine lückenhafte Definition
mit .org auch denkbar ist.  Die Namen müssen keinerlei Konvention
mehr unterliegen und auch nicht global sein.  Die fertige ELF-Datei
enthält exakt diesen Code und sonst nichts.

von Falk B. (falk)


Lesenswert?

@ Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite

>Das Teil vom AVR Studio ist ein einfachster Absolutassembler, der zu
>nicht viel taugt.

So wie damals WinWord. Ist aber dennoch Defacto Standard im Bereich ASM.

MFG
Falk

von ALB (Gast)


Lesenswert?

Danke,
das war doch mal eine solide antwort. jetzt blinkts auch.

von Jean P. (fubu1000)


Lesenswert?

Ui,
da sag ich mal sry.
Habe noch nie GNU-Assembler gesehen, sah für mich aus wie ne Mischung 
aus C und ASM. Zumal du auch noch was von AVR-GCC-Tutorial geschrieben 
hast.

Schäm

von ALB (Gast)


Lesenswert?

noch ein kleiner nachtrag: der code den ich hier reingeschrieben habe 
und der von (dl8dtl) berichtigt wurde hat einen kleinen Fehler. in der 
3.letzten zeile muss porta anstatt portb hin. (achtung stolperstein für 
den nächsten anfänger der dieses problem hat)

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


Lesenswert?

Falk Brunner wrote:

> So wie damals WinWord. Ist aber dennoch Defacto Standard im Bereich ASM.

Winword? :-)

Naja, Mittelmäßigkeit setzt sich halt prima durch.

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.