INT0 und INT1 mit Atmega8 benutzen: ISR wird mit avr-gcc nicht ausgeführt

Gast #3405674
Lesenswert?

Hallo

Ich versuche gerade was mit meinem Atmega8 und dem avr-gcc:

Wenn an PD2 oder PD3 (Die Interrupteingänge) eine fallende Flanke kommt, 
soll eine LED an PB0 leuchten. An PD2 und PD3 sind Taster angeschlossen, 
die den Pegel beim Drücken auf low ziehen.

Folgendes funktioniert super (geklaut vom avr-Tutorial von 
Mikrocontroller.net, die beiden Zeilen, die einen Wert in PortD laden 
habe ich hinzugefügt, wollte gucken, ob das ganze auch mit Pullups an 
den Interrupteingängen läuft) Das Programm schaltet die LED in einer 
Routine an, in der anderen aus.
1
.include "m8def.inc"
2

3
.def temp = r16
4

5
.org 0x000
6
         rjmp main            ; Reset Handler
7
.org INT0addr
8
         rjmp int0_handler    ; IRQ0 Handler
9
.org INT1addr
10
         rjmp int1_handler    ; IRQ1 Handler
11

12

13
main:                         ; hier beginnt das Hauptprogramm
14

15
         ldi temp, LOW(RAMEND)
16
         out SPL, temp
17
         ldi temp, HIGH(RAMEND)
18
         out SPH, temp
19

20
         ldi temp, 0x00
21
         out DDRD, temp
22

23
         ldi temp, 0b00001100
24
         out PORTD, temp
25

26
         ldi temp, 0xFF
27
         out DDRB, temp
28

29
         ldi temp, (1<<ISC01) | (1<<ISC11) ; INT0 und INT1 auf fallende Flanke konfigurieren
30
         out MCUCR, temp
31

32
         ldi temp, (1<<INT0) | (1<<INT1) ; INT0 und INT1 aktivieren
33
         out GICR, temp
34

35
         sei                   ; Interrupts allgemein aktivieren
36

37
loop:    rjmp loop             ; eine leere Endlosschleife
38

39
int0_handler:
40
         sbi PORTB, 0
41
         reti
42

43
int1_handler:
44
         cbi PORTB, 0
45
         reti


Mein C-Programm läuft hingegen nicht:

1
#define F_CPU 3686400UL
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4

5

6

7
int main(void){
8
  SP=RAMEND;
9
  DDRD=0x00;  //PortD als Interrupteingang
10
  PORTD=0b00001100; //Pullups am Interrupteingang
11
  DDRB=0xFF;  //Port B als LED-Ausgang (LED an PB0)
12
  MCUCR = (1<<ISC11) | (1<<ISC01); //Flankenverhalten setzen, Int0 und Int1 bei fallender Flanke auslösen
13
  GICR = (1<<INT0) | (1<<INT1);  //INT0 und INT1 aktivieren
14

15

16
  sei();  //Interruptflag setzen
17

18
  while(1){
19
  }
20

21
  return 0;
22
}
23

24
ISR(INT0_vect){
25
  PORTB |= 0b00000001;
26
}
27

28
ISR(INT1_vect){
29
  PORTB |= 0b00000001;
30
}


Der vom Compiler erzeugte Assemblercode:
1
   .file  "main.c"
2
__SP_H__ = 0x3e
3
__SP_L__ = 0x3d
4
__SREG__ = 0x3f
5
__tmp_reg__ = 0
6
__zero_reg__ = 1
7
  .section  .text.startup,"ax",@progbits
8
.global  main
9
  .type  main, @function
10
main:
11
/* prologue: function */
12
/* frame size = 0 */
13
/* stack size = 0 */
14
.L__stack_usage = 0
15
  ldi r24,lo8(95)
16
  ldi r25,lo8(4)
17
  out __SP_L__+1,r25
18
  out __SP_L__,r24
19
  out 0x11,__zero_reg__
20
  ldi r24,lo8(12)
21
  out 0x12,r24
22
  ldi r24,lo8(-1)
23
  out 0x17,r24
24
  ldi r24,lo8(10)
25
  out 0x35,r24
26
  ldi r24,lo8(-64)
27
  out 0x3b,r24
28
/* #APP */
29
 ;  17 "main.c" 1
30
  sei
31
 ;  0 "" 2
32
/* #NOAPP */
33
.L2:
34
  rjmp .L2
35
  .size  main, .-main
36
  .text
37
.global  __vector_1
38
  .type  __vector_1, @function
39
__vector_1:
40
  push r1
41
  push r0
42
  in r0,__SREG__
43
  push r0
44
  clr __zero_reg__
45
/* prologue: Signal */
46
/* frame size = 0 */
47
/* stack size = 3 */
48
.L__stack_usage = 3
49
  sbi 0x18,0
50
/* epilogue start */
51
  pop r0
52
  out __SREG__,r0
53
  pop r0
54
  pop r1
55
  reti
56
  .size  __vector_1, .-__vector_1
57
.global  __vector_2
58
  .type  __vector_2, @function
59
__vector_2:
60
  push r1
61
  push r0
62
  in r0,__SREG__
63
  push r0
64
  clr __zero_reg__
65
/* prologue: Signal */
66
/* frame size = 0 */
67
/* stack size = 3 */
68
.L__stack_usage = 3
69
  sbi 0x18,0
70
/* epilogue start */
71
  pop r0
72
  out __SREG__,r0
73
  pop r0
74
  pop r1
75
  reti
76
  .size  __vector_2, .-__vector_2
77
  .ident  "GCC: (GNU) 4.7.2"

Es leuchtet einfach nichts mit dem C-Programm. Egal was passiert.
Und noch etwas: Die Adresse des MCUCR, dessen Wert ich auch im 
C-Beispiel verändere ist 0x35. Im C-Code des Compilers taucht die 
Adresse nirgens auf. Wenn ich im Programm in der leeren while-Schleife 
den Wert von MCUCR mit LED's überprüfe, ist das Register aber wie 
gewünscht gesetzt. Wie kommt das?

Gruß
Joschua
Gast #3405709
Lesenswert?

Um den Inhalt der ISR als Fehlerquelle auszuschließen, ab ich
PORTB |= 0b00000001;
verwendet. Eine Zeile, LED anschalten, wenn eine Routine ausgeführt 
wird. Die Zeile habe ich dann nochmal in main getestet und benutze sie 
jetzt. Das dadurch nichts um- sondern nur angeschaltet wird, ist mir 
schon klar. Ich wollte möglichst alle Fehlerquellen reduzieren und ne 
Menge Google befragen und dann hier rumheulen.
Gast #3405713
Lesenswert?

Es ist sinnvoll die verwendete Hardware zu nenen oder zu beschreiben 
(Schaltplan). Üblicherweise sind LEDs mit Low zum leuchen zu bringen.

Was mir auch merkwürdig vorkommt ist die Zuweisung an den Stack-Pointer 
am Anfang. Lösche die mal raus. Sie ist unnötig.
Gast #3405718
Lesenswert?

Hululu schrieb:
> Es ist sinnvoll die verwendete Hardware zu nenen oder zu beschreiben
> (Schaltplan). Üblicherweise sind LEDs mit Low zum leuchen zu bringen.

wenn das ASM fehlerfrei arbeitet, braucht man wohl nicht über die 
Hardware zu wissen. Es gibt nur um den Vergleich der beiden Programm auf 
der gleichen Hardware.

hp-freund hat vermutlich das Problem schon gefunden
Gast #3405732
Lesenswert?

Hululu schrieb:
> Es ist sinnvoll die verwendete Hardware zu nenen oder zu beschreiben
> (Schaltplan). Üblicherweise sind LEDs mit Low zum leuchen zu bringen.
>
> Was mir auch merkwürdig vorkommt ist die Zuweisung an den Stack-Pointer
> am Anfang. Lösche die mal raus. Sie ist unnötig.

Erledigt. Geht leider auch nicht.
Gast #3405737
Lesenswert?

Hi

>Was mir auch merkwürdig vorkommt ist die Zuweisung an den Stack-Pointer
>am Anfang. Lösche die mal raus. Sie ist unnötig.

Beim ATMega8 wird der Stackpointer nicht automatisch geladen. Also 
notwendig.

MfG Spess
Gast #3405743
Lesenswert?

spess53 schrieb:
> Beim ATMega8 wird der Stackpointer nicht automatisch geladen. Also
> notwendig.

Gut, ist wieder drin.

Und wer einen Blick auf den Schaltplan werfen möchte:
http://www.myavr.info/download/produkte/myavr_board_light/techb_schaltplan-myavr-board-light.png

ICh benutze das myAVR-Board light. Hat das ganze AVR-ASM-Tutorial von 
Mikrocontroller.net anstandslos mitgemacht.

S1 ist an PD3
S2 ist an PD2
LED3 ist an PB0 (mit Vorwiderstand natürlich)
Gast #3405750
Lesenswert?

Peter II schrieb:
> das macht der Compiler, um so etas muss man sich bei C nicht kümmern.

Hui. Ihr antwortet immer so schnell. Schneller als ich tippen kann. 
Danke =D

http://www.rn-wissen.de/index.php/Avr-gcc#Abk.C3.BCrzungen_und_Bezeichnungen

Verstehe ich das richtig: Wenn man am Stackpointer rumfummelt, ohne den 
gcc zu informieren, werden Interrupts deaktiviert? Siehe -mno-interrupts 
unter "Maschinenspezifische Optionen für avr-gcc"
Gast #3405757
Lesenswert?

Also ich gebs jetzt auf, da Du andauern Deine Beiträge so änderst, das 
Deine Fragen und unsere Antworten irrelevant werden. Falls Du auf eine 
Frage antwortest, tue das nach der Frage nicht in dem Beitrag der die 
Frage erst aufgeworfen hat.

Tschüss
Gast #3405758
Lesenswert?

Hululu schrieb:
>>http://www.rn-wissen.de/index.php/Avr-gcc#Abk.C3.B...
>
>>Verstehe ich das richtig: Wenn man am Stackpointer rumfummelt, ohne den
>>gcc zu informieren, werden Interrupts deaktiviert?
>
> Wo steht das in dem von Dir verlinkten Dokument?

"-mno-interrupts
Ändert den Stackpointer ohne Interrupts zu deaktivieren"

Hab den falschen Abschnitt verlinkt. Tschuldigung.
Wenns nicht so wäre, bräuchte man die Option nicht, oder?
#3405770
Lesenswert?

Joschua C. schrieb:
> Wenns nicht so wäre, bräuchte man die Option nicht, oder?

Das bezieht sich darauf, wenn der Compiler den SP verändert. Auf deine 
manuelle Änderung hat das keinen Einfluss. Verbeis dich nicht darin, 
nimmt die Zeile einfach raus, und gut ist. Ursache deines eigentlichen 
Problems ist das höchstwahrscheinlich eh nicht.


Wenn Interrupts nicht funktionieren, obwohl eigentlich alles gut 
aussieht, dann liegt das in der Regel an Problemen im Build-Process 
(z.B. nicht für den richtigen Controller gelinkt). Also poste mal den 
kompletten Build-Output.
Gast #3405778
Lesenswert?

Ok, ist draußen.

avr-gcc -v -Wall -o main.hex -Os -mmcu=atmega8 main.c
Using built-in specs.
COLLECT_GCC=avr-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/avr/4.7.2/lto-wrapper
Target: avr
Configured with: ../src/configure -v --enable-languages=c,c++ 
--prefix=/usr/lib --infodir=/usr/share/info --mandir=/usr/share/man 
--bindir=/usr/bin --libexecdir=/usr/lib --libdir=/usr/lib 
--enable-shared --with-system-zlib --enable-long-long --enable-nls 
--without-included-gettext --disable-libssp --build=x86_64-linux-gnu 
--host=x86_64-linux-gnu --target=avr
Thread model: single
gcc version 4.7.2 (GCC)
COLLECT_GCC_OPTIONS='-v' '-Wall' '-o' 'main.hex' '-Os' '-mmcu=atmega8'
 /usr/lib/gcc/avr/4.7.2/cc1 -quiet -v -imultilib avr4 main.c -quiet 
-dumpbase main.c -mmcu=atmega8 -auxbase main -Os -Wall -version -o 
/tmp/ccZBXFRD.s
GNU C (GCC) version 4.7.2 (avr)
  compiled by GNU C version 4.7.2, GMP version 5.0.5, MPFR version 
3.1.0-p10, MPC version 0.9
warning: MPFR header version 3.1.0-p10 differs from library version 
3.1.1-p2.
GGC heuristics: --param ggc-min-expand=100 --param 
ggc-min-heapsize=131072
ignoring nonexistent directory 
"/usr/lib/gcc/avr/4.7.2/../../../avr/sys-include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/avr/4.7.2/include
 /usr/lib/gcc/avr/4.7.2/include-fixed
 /usr/lib/gcc/avr/4.7.2/../../../avr/include
End of search list.
GNU C (GCC) version 4.7.2 (avr)
  compiled by GNU C version 4.7.2, GMP version 5.0.5, MPFR version 
3.1.0-p10, MPC version 0.9
warning: MPFR header version 3.1.0-p10 differs from library version 
3.1.1-p2.
GGC heuristics: --param ggc-min-expand=100 --param 
ggc-min-heapsize=131072
Compiler executable checksum: ffb40dd2df077290892c2489ab66a6da
COLLECT_GCC_OPTIONS='-v' '-Wall' '-o' 'main.hex' '-Os' '-mmcu=atmega8'
 /usr/lib/gcc/avr/4.7.2/../../../avr/bin/as -mmcu=atmega8 -mno-skip-bug 
-o /tmp/ccERpZf1.o /tmp/ccZBXFRD.s
COMPILER_PATH=/usr/lib/gcc/avr/4.7.2/:/usr/lib/gcc/avr/4.7.2/:/usr/lib/g 
cc/avr/:/usr/lib/gcc/avr/4.7.2/:/usr/lib/gcc/avr/:/usr/lib/gcc/avr/4.7.2 
/../../../avr/bin/
LIBRARY_PATH=/usr/lib/gcc/avr/4.7.2/avr4/:/usr/lib/gcc/avr/4.7.2/../../. 
./avr/lib/avr4/:/usr/lib/gcc/avr/4.7.2/:/usr/lib/gcc/avr/4.7.2/../../../ 
avr/lib/
COLLECT_GCC_OPTIONS='-v' '-Wall' '-o' 'main.hex' '-Os' '-mmcu=atmega8'
 /usr/lib/gcc/avr/4.7.2/collect2 -m avr4 -o main.hex 
/usr/lib/gcc/avr/4.7.2/../../../avr/lib/avr4/crtm8.o 
-L/usr/lib/gcc/avr/4.7.2/avr4 
-L/usr/lib/gcc/avr/4.7.2/../../../avr/lib/avr4 -L/usr/lib/gcc/avr/4.7.2 
-L/usr/lib/gcc/avr/4.7.2/../../../avr/lib /tmp/ccERpZf1.o -lgcc -lc 
-lgcc
#3405786
Lesenswert?

Ursache deines Problems ist das hier:
> avr-gcc ... -o main.hex ...

Der Compiler produziert eine ELF-Datei. Da kommt keine fertig brennbare 
HEX-Datei raus, nur weil du der Datei eine entsprechende Endung 
verpasst. Du musst die HEX-Datei erst aus der ELF-Datei mittels objcopy 
extrahieren.
#3405813
Lesenswert?

Hululu schrieb:
> Da hat es keine Fehlermeldung gegeben, als beim Flashen versucht wurde
> eine ELF-Datei als eine Hex-Datei zu interpretieren?

Das Brenn-Programm wird die Endung ignoriert und die Datei einfach als 
binäres Image betrachtet haben. Einfacher Code funktionieren dann sogar 
meist. Da der Code aber nicht an der richtigen Adresse im Controller 
liegt, gehören Interrupts zu den Dingen, die dann garantiert nicht 
funktionieren.
Gast #3405821
Lesenswert?

>Das Brenn-Programm wird die Endung ignoriert und die Datei einfach als
>binäres Image betrachtet haben.

Das wird wohl vermutlich so sein. Ist schon klar.

Aber es geht um was anderes (Zaunpfahl heraushol): Wir wissen ja 
garnicht was für ein Brenn-Programm der TO verwendet. Warum wissen wir 
das nicht?
Gast #3405823
Lesenswert?

LED blinken usw. hat auch funktioniert. Ich hab mich schon gewundert, 
warum so ein popeliges Programm 3k Flash braucht? Arbeite aber gerade 
zum ersten Mal mit C und Controllern, hab da so keinen schlimmen 
Verdacht geschöpft.

Was muss ich denn mit objcopy für die Quelldatei für bfdname angeben? 
Und wieso kann ich nicht einfach gcc -c verwenden? Dann erkennt avrdude 
das Format nicht.
#3405844
Lesenswert?

Joschua C. schrieb:
> Was muss ich denn mit objcopy für die Quelldatei für bfdname angeben?

Nichts. Eine ELF-Datei ist der "natürliche" Input für objcopy. Nur wenn 
du es mit was anderem füttern willst, musst du das näher spezifizieren.

Joschua C. schrieb:
> Und wieso kann ich nicht einfach gcc -c verwenden?

Weil da kein fertig gelinktes Programm raus kommt, sondern nur ein 
Objekt-Modul.


PS:
Du würdest dich leichter tun, wenn du einfach ein erprobtes Makefile 
verwenden würdest, z.B. eines das von MFile erzeugt wurde.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren