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


von Joschua C. (Gast)


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

von hp-freund (Gast)


Lesenswert?

Joschua C. schrieb:
> ISR(INT0_vect){
>   PORTB |= 0b00000001;
> }
>
> ISR(INT1_vect){
>   PORTB |= 0b00000001;
> }

???

von STK500-Besitzer (Gast)


Lesenswert?

mach mal den PortB zum Ausgang, wenn du ihn benutzen willst.

von Peter II (Gast)


Lesenswert?

STK500-Besitzer schrieb:
> mach mal den PortB zum Ausgang, wenn du ihn benutzen willst.

was soll er denn da noch machen?

> DDRB=0xFF;  //Port B als LED-Ausgang (LED an PB0)

von Joschua C. (Gast)


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.

von Hululu (Gast)


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.

von Peter II (Gast)


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

von hp-freund (Gast)


Lesenswert?

Wir sollten nur noch wissen ob die LED gegen GND oder VCC angeschlossen 
ist.


Joschua C. schrieb:
> 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.

  ldi r24,lo8(10)
  out 0x35,r24

von Joschua C. (Gast)


Lesenswert?

Mmh. Das Setzen von MCUCR hab ich wohl übersehen. Danke.

Die LED ist gegen GND angeschlossen. Den Inhalt von den ISRs habe ich 
auch schon mal in die Endlosschleife geschrieben => LED hat geleuchtet.

von Joschua C. (Gast)


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.

von spess53 (Gast)


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

von Peter II (Gast)


Lesenswert?

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

das macht der Compiler, um so etas muss man sich bei C nicht kümmern.

von Joschua C. (Gast)


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)

von Peter II (Gast)


Lesenswert?

Joschua C. schrieb:
> Gut, ist wieder drin.

machst wieder raus. Man müsste es wenn man es selber macht vor main 
machen. Denn main ist selber schon eine Funktion die etwas auf dem Stack 
ablegt.

von Hululu (Gast)


Lesenswert?

@ Spess53

Reden wir beide vom C-Code? Ich war auch der Meinung, das der 
runtime-Code den SP lädt.

von Joschua C. (Gast)


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"

von Hululu (Gast)


Lesenswert?

>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?

von Hululu (Gast)


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

von Joschua C. (Gast)


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?

von Joschua C. (Gast)


Lesenswert?

Jedenfalls funktionieren Funktionsaufrufe bei mir auch ohne explizierte 
Stackpointerinitialisierung.

von Stefan E. (sternst)


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.

von Joschua C. (Gast)


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

von Stefan E. (sternst)


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.

von Hululu (Gast)


Lesenswert?

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

von Stefan E. (sternst)


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.

von Hululu (Gast)


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?

von Joschua C. (Gast)


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.

von Stefan E. (sternst)


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.

von Joschua C. (Gast)


Lesenswert?

ICH FASS ES NICHT!!!!!
DER ROTZ LEUCHTET
SO EIN DRECK

Vielen Dank euch allen.

von Joschua C. (Gast)


Lesenswert?

avr-objcopy -O binary main.hex main

Das hats gelöst.

Ja, makefile klingt gut. Habe ich mir bei der C-Entwicklung für Linux 
auch irgendwann gebaut. Wird halt später immer zu viel.

von Stefan E. (sternst)


Lesenswert?

Joschua C. schrieb:
> avr-objcopy -O binary main.hex main
>
> Das hats gelöst.

Nur dass deine Namenswahl für den Compiler-Output mit main.hex immer 
noch sehr unglücklich ist.

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.