Interrupt Routine stoppt die Ausführung

OP #4382613
Hallo Leute,

ich habe folgendes einfaches Programm für meinen Atmega328p:
1
#define F_CPU 16000000UL
2

3
#include <avr/io.h>
4
#include <util/delay.h>
5
#include <avr/interrupt.h>
6

7

8

9
void main (void) {
10
    DDRD = (1<<PD3);
11
    DDRB = (1<<PB0);
12
    cli();
13
    TCCR2A = (1<<WGM21) | (1<<WGM20) | (1<<COM2B1);
14
    OCR2B = 0;
15
    TIMSK2 = 0x01;
16
    sei();
17
  TCCR2B = (1 << CS20);
18
  
19
  while(1){
20
    //PORTD ^= (1<<PD3);
21
    PORTB ^= (1<<PB0);
22
    _delay_ms(1000);
23
    OCR2B +=10;
24
    //PORTD ^= (1<<PD3);
25
    PORTB ^= (1<<PB0);
26
    _delay_ms(1000);
27
  
28
  }
29
}
30

31
/*
32
ISR (TIMER2_OVF_vect)
33
{
34
  _delay_ms(1000);
35
  reti();
36
}
37

38
*/
Ein shell Skript erstellt und sendet das Programm:
1
echo "Compiler Object"
2
avr-gcc -c -Os -mmcu=atmega328p -o SimpleIO.o SimpleIO.c
3
echo "Compiler ELF"
4
avr-gcc SimpleIO.o -o SimpleIO.elf
5
echo "Compiler HEX"
6
avr-objcopy -O ihex -j .data -j .text SimpleIO.elf SimpleIO.hex
7
echo "AVRDUDE"
8
sudo avrdude -patmega328p -P usb -cusbasp-clone -Uflash:w:SimpleIO.hex:a

Wenn ich die ISR auskommentiert lasse wie oben, dann funktioniert es das 
PB0 blinkt und PD3 mittels Fast-PWM in 10er Schritten alle zwei Sekunden 
hochgezählt wird.

Sobald ich ISR verwende (egal ob mit delay, reti() oder leer) bleiben 
alle LED dunkel. Bisher konnte ich es also auf die Existenz der ISR 
zurück führen.

Bitte um eure Hilfe da ich dieses Problem noch nicht im Netz gefunden 
habe.

Danke im voraus,
Roman
Gast
Ist doch klar, der µC  triggert die ISR schneller, als deren Laufzeit 
beträgt. Somit ist das Ding immer in der ISR und kommt vielleicht pro 
ISR-Ausführung 1 Takt in der Hauptschleife weiter. Eine Wartesekunde in 
der Hauptschleife kostet 16000000 Takte, d.h. nach ca. 185 Tagen wird 
die LED zu leuchten beginnen :D
Musst nur etwas länger aufbleiben.1
Wenn deine ISR aktiv ist, dann wird sie praktisch dauerhaft aktiv sein.
Das delay(1000) sorgt dafür, daß nach RETI() schon der nächste Int 
ansteht. In so einem Fall führt ein AVR genau einen Befehl in der 
Hauptschleife aus, bevor wieder die ISR dran ist. Und ein delay(1000) in 
der Hauptschleife muß 1..20 Millionen Taktzyklen "vernichten", von denen 
dann aber nur einer je Sekunde ausgeführt wird. Dauert also etwas 
länger!
Zudem wird Reti() dafür sorgen, daß je ISR-Aufruf einige Bytes auf dem 
Stack liegen bleiben. Nach einiger Zeit endet das bestenfalls in einem 
"Soft-Reset".

Also:
- ISR() braucht kein reti(), das macht es schon selbst
- delay() in ISR ist böse, denn
- delay() in Mainloop erwartet, daß die geplanten Takt auch von der
  Mainloop ausgeführt werden. Werden 50% davon in der ISR ausgeführt,
  dann dauert das delay doppelt so lang. Werden 99.999% der Takte in der
  ISR ausgeführt, dann ...
Gerade in anbetracht der Programmgröße:
Wirf einen Blick ins .lss File, da kann man sehen, wie falsch einem der 
Compiler verstanden hat. (Wobei er es in konkreten Fall sehr einfach 
hatte. Das Falschverstehen.)
OP
MWS schrieb:
> Falsches Target?

Ich habe auch eine Vermutung das irgend eine Compiler Option diesen 
Effekt bewirkt. Welches wäre das richtige Target?

Kann sich jemand mein sh ansehen bzgl. der Optionen?

MWS schrieb:
> Eine Wartesekunde in
> der Hauptschleife kostet 16000000 Takte, d.h. nach ca. 185 Tagen wird
> die LED zu leuchten beginnen :D

Mit ist klar das dieser delay Unsinn ist. Eigentlich hatte ich auch noch 
die Led zum Toggeln drinnen. Etwas so:
1
ISR (TIMER2_OVF_vect)
2
{
3
  _delay_ms(1000);
4
  PORTB ^= (1<<PB0);
5
}
Später hab ich auch geschrieben das ich die ISR leer hatte und trotzdem 
das Problem aufgetaucht ist.
Eigentliches Ziel ist im Interrupt einfach eine Zählervariable zu 
erhöhen.
1
ISR (TIMER2_OVF_vect)
2
{
3
  someCounter++;
4
}

lg
Roman
> Wenn ich die ISR auskommentiert lasse wie oben, dann funktioniert es das
> PB0 blinkt und PD3 mittels Fast-PWM in 10er Schritten alle zwei Sekunden
> hochgezählt wird.

Die "auskommentierte ISR", bei eingeschaltetem Timer2OverflowInterrupt 
sorgt für einen Neustart bei Überlauf des Timer2. Das führt auch zu 
"LED-Flackern", aber nicht zum gewünschten Programmablauf. Troll?
OP
Carl D. schrieb:
> Die "auskommentierte ISR", bei eingeschaltetem Timer2OverflowInterrupt
> sorgt für einen Neustart bei Überlauf des Timer2. Das führt auch zu
> "LED-Flackern", aber nicht zum gewünschten Programmablauf. Troll?

Led flackern hab ich auch gesehen, kann mich aber nicht mehr erinnern in 
welchem Status da ich vieles ausprobiert habe. Kann gut sein dass ich 
auch die Timer Mask auskommentiert hatte um die PWM Funktion zu sehen.
Warum geht nix wenn ich ISR aktiv habe? Zumindest flackert die Led wenn 
der Timerüberlauf resetet. Hatte ich bisher nicht gewußt aber es zeigt 
immerhin das der µC bis dahin richtig funktioniert.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 10 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.