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...
@falk: ja so lansam kotzt mich dieses ding auch an. kennt jemand einen avr-studio kompatiblen assembler für linux?
@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 |
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.
@ 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
Danke, das war doch mal eine solide antwort. jetzt blinkts auch.
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.
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.