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.
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ß.
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...
>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 ....
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
@ 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
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...
@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.
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
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.
@ 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
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
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)
Falk Brunner wrote:
> So wie damals WinWord. Ist aber dennoch Defacto Standard im Bereich ASM.
Winword? :-)
Naja, Mittelmäßigkeit setzt sich halt prima durch.