Forum: Compiler & IDEs einzelnen Interrupt sperren


von Jochen (Gast)


Lesenswert?

Hallo Leute!

Ich steh' etwas auf dem Schlauch. Ihr kennt das Problem: das Programm
macht einfach nicht das, was man von ihm will. Man schaut sich das
Programm x-mal an und ist irgendwann geneigt, den Fehler dem Compiler
oder dem µC in die Schule zu schieben...
Dann kommt jemand anderes daher und sieht den Fehler auf den ersten
Blick.

Also, ich habe ein Problem mit einem Interrupt.
Nein, nicht das übliche. Der Interrupt läuft super. Sogar zu gut.
Genauer gesagt möchte ich einen Interrupt zeitweise sperren. Klappt
jedoch nicht. :-(

Ok, der Reihe nach:
Kommt ein Signal an INT1 meines Atmega32, wird eine Begrüßung auf das
LCD ausgegeben.
Unter bestimmten Bedingungen gibt der µC eine Fehlermeldung aus.
Diese Fehlermeldung darf jetzt natürlich nicht von der Begrüßung
überschrieben werden.
Am Anfang meiner Fehlermeldung sperre ich deshalb INT1, gebe meine
Fehlermeldung aus, warte auf eine Taste und gebe den Interrupt wieder
frei.
Da andere Interrupts weiterlaufen müssen, darf ich die Interrupt nicht
global sperren, sondern nur den einen.

[Hoffe, soweit war das noch verständlich..]

hier mal ein Ausschitt aus meiner init():

     // ext. Interrupt erlauben
     GICR |= _BV(INT0) | _BV(INT1);
     // bislang aufgelaufene Interrupts loeschen (sicher ist sicher)
und dann Interrupts generell erlauben
     GIFR &= ~( _BV(INTF0) | _BV(INTF1) | _BV(INTF2) );
     sei();

Ok, die Interrupts funktionieren jetzt.

Jetzt meine Fehlermeldungsroutine:

      // Interrupt1 sperren
      GICR &= ~(_BV(INT1));

      [Meldung ausgeben und auf Taste warten]

      // Interrupt1 wieder freigeben,
      GICR |= _BV(INT1);

Der Interrupt INT1 funktioniert trotzdem noch, während er auf die Taste
wartet :-(
Hab ich das Datenblatt des Atmega32 nicht verstanden, bin ich zu blöd
für C oder hab ich ein undokumentiertes Feature entdeckt??

Gruß.. Jochen

von Jörg Wunsch (Gast)


Lesenswert?

Externer Interrupt mit manueller Taste ist immer keine gute Idee.
Tasten prellen und neigen daher dazu, dass du dir deine Interrupts
x-mal auslösen lässt.  Wenn du das schon tun willst, dann erstens wie
üblich in der ISR nur Flags setzen, keine langanhaltenden Aktionen,
zweitens dort (während die Interrupts innerhalb der ISR sowieso noch
gesperrt sind) das interrupt-enable-Bit für diesen Interrupt
zurücknehmen und es erst später wieder (timer-gesteuert) neu setzen.

Du hast völlig richtig erkannt, dass man vor dem Neusetzen alle
eventuell anhängigen Interrupts löschen sollte (geht nur bei
flankengetriggerten, pegelgetriggerte Interrupts werden immer
ausgelöst, solange der Pegel anliegt).

Aber:

> GIFR &= ~( _BV(INTF0) | _BV(INTF1) | _BV(INTF2) );

Hier hast du weder das Datenblatt noch die (avr-libc-)FAQ richtig
gelesen. ;-) Ein anhängiger Interrupt wird gelöscht, indem man ein
1-Bit schreibt, die FAQ erklärt warum das so ist und erklärt auch,
dass man das nicht mit einem read-modify-write macht wie du hier,
sondern einfach:

GIFR = _BV(INTF1);

Für die Modifikation von GICR außerhalb einer ISR würde ich übrigens
unbedingt vorher global die Interrupts sperren, sicher ist sicher.

von Jochen (Gast)


Lesenswert?

Hallo!

> Externer Interrupt mit manueller Taste ist immer keine gute Idee.

Der ext. Interrupt ist keine Taste.
Die Tastenabfrage mache ich über eine Routine, die auch entprellt.

> Ein anhängiger Interrupt wird gelöscht, indem man ein
> 1-Bit schreibt

Oops.. :-)
Danke für den Hinweis. Hab's korrigiert.
Das dürfte jedoch nicht für mein Problem verantwortlich sein.

> Für die Modifikation von GICR außerhalb einer ISR würde ich übrigens
> unbedingt vorher global die Interrupts sperren, sicher ist sicher.

Kann zumindest nicht schaden.
Hab's eben ausprobiert. Keine Änderung.

Aber meine Überlegung, daß SIG_INTERRUPT1 durch
"GICR &= ~(_BV(INT1));" blockiert wird ist doch soweit richtig,
oder?

Gruß.. Jochen

von Jörg Wunsch (Gast)


Lesenswert?

> Aber meine Überlegung, daß SIG_INTERRUPT1 durch "GICR &=
> ~(_BV(INT1));" blockiert wird ist doch soweit richtig, oder?

Ja.

von Jochen (Gast)


Lesenswert?

Hallo nochmal!

Ich wollte nur Bescheid sagen, daß ich den Fehler jetzt gefunden habe.

Es lag an meiner LCD-Routine! :)
Ich sperre dort kurzzeitig INT1, um sicherzugehen, daß immmer beide
halb-bytes zum LCD übertragen werden (war nötig, nachdem machmal das
LCD ausging).

Ich bin also doch nicht bekloppt, sondern nur unfähig.. ;-)

Gruß.. Jochen

von Klaus W. (Firma: privat) (texmex)


Lesenswert?

Jörg Wunsch wrote:

> Für die Modifikation von GICR außerhalb einer ISR würde ich übrigens
> unbedingt vorher global die Interrupts sperren, sicher ist sicher.

grübel

Warum würdest Du das?

von Klaus (Gast)


Lesenswert?

> Ich bin also doch nicht bekloppt, sondern nur unfähig.. ;-)

Wenn du aber immerhin noch lernfähig bist, is das kein Problem ;)

Es ist generell ne gute Idee zum temporären sperren der Interrupts am 
anfang den alten Zustand zu speichern, die Interrupts dann zu 
deaktivieren und am ende den alten Zustand wieder herzustellen. Das 
vermeidet viele solche Fehler.

von Klaus W. (Firma: privat) (texmex)


Lesenswert?

Klaus wrote:

> Es ist generell ne gute Idee zum temporären sperren der Interrupts am
> anfang den alten Zustand zu speichern, die Interrupts dann zu
> deaktivieren und am ende den alten Zustand wieder herzustellen. Das
> vermeidet viele solche Fehler.

Hm, darüber denke ich auch gerade nach. Ich versuche das Problem aber 
etwas abstrakter zu erfassen und will mich gar nicht an eine konkrete 
Anwendung klammern.

Eigentlich dürfte das ja nur dann wichtig sein, wenn Funktionen die 
selbst Interrupts sperren, sich gegenseitig aufrufen, oder?

Ich frage mich, ob man das möglicherweise per Design grundsätzlich 
vermeiden sollte? Aber kann man das immer?

von Sven P. (Gast)


Lesenswert?

Klaus W. wrote:
> Jörg Wunsch wrote:
>
>> Für die Modifikation von GICR außerhalb einer ISR würde ich übrigens
>> unbedingt vorher global die Interrupts sperren, sicher ist sicher.
>
> *grübel*
>
> Warum würdest Du das?

Wei aufs GICR nur RMW funktioniert und zwischen den drei Schritten noch 
jemand andres dran rumfummeln könnte.

von Klaus W. (Firma: privat) (texmex)


Lesenswert?

Sven Pauli wrote:
> Klaus W. wrote:
>> Jörg Wunsch wrote:
>>
>>> Für die Modifikation von GICR außerhalb einer ISR würde ich übrigens
>>> unbedingt vorher global die Interrupts sperren, sicher ist sicher.
>>
>> *grübel*
>>
>> Warum würdest Du das?
>
> Wei aufs GICR nur RMW funktioniert und zwischen den drei Schritten noch
> jemand andres dran rumfummeln könnte.

Stimmt! - Aber das könnte dann ja nur eine ISR selbst sein. Und müsste 
dort explizit gemacht werden. Könnte man sowas wollen?
Jedenfalls solange ich das nicht mache, sollte auch nichts passieren, 
oder?

Viele Grüße,
Klaus

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.