mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR - Absturz aufgrund zu vieler Interrupts?


Autor: concept (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo allerseits,

in Beitrag "Re: Tiny45 stürzt ab trotz Minimalprogramm" stellte sich die 
Frage, ob zu viele Interrupts (z.B. durch Prellen) einen Absturz 
verursachen können.

Ich bezweifele aber, dass es 'zu viele Interrupts' überhaupt gibt. Wenn 
ein Interrupt auftritt, werden andere Interrupts doch bis zum Ende der 
ISR gesperrt, und dann nach Priorität abgearbeitet. Was kann da zum 
Absturz führen?

Autor: Der Schubi (schubi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du musst dich überhaupt erstmal fragen was ein "Absturz" ist.
--> der uC reagiert z.B. nicht mehr (oder nicht so, wie er soll)
Es kann also bei "zu vielen" Interrupts passieren, dass der uC quasi im 
Interrupt hängen bleibt, da zur Ausführung des Hauptprogramms gar keine 
Zeit mehr bleibt...

Autor: Michael G. (linuxgeek) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Schubi wrote:

> Interrupt hängen bleibt, da zur Ausführung des Hauptprogramms gar keine
> Zeit mehr bleibt...

Nein kann nicht passieren, da nach einem Interrupt mindestens (immer) 
ein paar Befehle aus dem Hauptprogramm abgearbeitet werden. Es kann also 
traege werden, aber nicht vollkommen zum Erliegen kommen.

Autor: Der Schubi (schubi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo steht denn das?
Wenn ein Interrupt abgearbeitet wird und ein neuer Interrupt eintrifft, 
warum sollte dann das Hauptprogramm abgearbeitet werden? Interrupt hat 
Priorität.

Autor: Michael G. (linuxgeek) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein hat er nicht, das soll das Aushungern des Hauptprogramms 
verhindern, was auch Sinn macht. Und wo meinste wohl wird das stehen?

"When the AVR exits from an interrupt, it will always return to the main 
program and execute one more instruction before any pending interrupt is 
served."

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein Problem sind nicht die Interrupts, sondern das Sleep.
Wenn zum Zeitpunkt des Sleep die Interrupts disabled sind, dann wars 
das.
Ohne Interrupts kann nur ein Reset das Sleep beenden.

Du mußt also folgenden Ablauf unbedingt einhalten.

Schau mal in die sleep.h:

Example:
\code
#include <avr/interrupt.h>
#include <avr/sleep.h>

...
  cli();
  if (some_condition) {
    sleep_enable();
    sei();
    sleep_cpu();
    sleep_disable();
  }
  sei();
\endcode


Peter

Autor: Der Schubi (schubi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke.
Wieder was dazugelernt :-)
Allerdings ist ein Befehl im Hauptprogramm pro ausgeführtem Interrupt 
nicht wirklich viel, oder?

Autor: AVRFan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wo steht denn das?
>Wenn ein Interrupt abgearbeitet wird und ein neuer Interrupt eintrifft,
>warum sollte dann das Hauptprogramm abgearbeitet werden? Interrupt hat
>Priorität.

AVRs arbeiten nach Rückkehr aus einem Interrupt vor Sprung auf den 
Vektor eines anstehenden Interrupts noch einen Befehl des Hauptprogramms 
ab.

Zitat aus dem Datenblatt zum ATmega8, Kapitel "AVR CPU Core", Abschnitt 
"Reset and Interrupt Handling", ca. S. 12:

"When the AVR exits from an interrupt, it will always return to the main 
program and execute one more instruction before any pending interrupt is 
served."

Autor: concept (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Verzeihung, ich habe mich unpräzise ausgedrückt - es wird nur der 
aufrufende Pin-Change interrupt deaktiviert, und der sleep mode idle 
aktiviert.

Hier das Programm direkt:

Beitrag "Re: Tiny45 stürzt ab trotz Minimalprogramm"

Oder verstehe ich falsch?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
concept wrote:
> Verzeihung, ich habe mich unpräzise ausgedrückt - es wird nur der
> aufrufende Pin-Change interrupt deaktiviert, und der sleep mode idle
> aktiviert.
>
> Hier das Programm direkt:
>
> Beitrag "Re: Tiny45 stürzt ab trotz Minimalprogramm"


Das Programm sieht o.k. aus.

Es hat bloß kaum Ausgaben.
Einzig die eine LED blitzt kaum merkbar im Timerinterrupt ganz kurz auf 
(~1 µS).
Wie stellst Du also fest, daß es scheinbar abstürzt?

Erzähl mal, was Du wann erwartest und was wie reagiert.


Peter

Autor: concept (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zusammenfassung:

AVR (tiny45) soll aus power-down auf Tastendruck aufwachen.
Datenblatt:
http://www.atmel.com/dyn/resources/prod_documents/...

Problem (wacht nach einigen Tastendrücken nicht mehr auf) wird sehr 
wahrscheinlich verursacht durch PCINT in zusammenhang mit Prellen und 
deaktivieren des PCINT im GIMSK.

Verwendung von INT0 bzw. deaktivieren des einzelnen PCINT-Pins in PCMSK 
ruft keinen 'Absturz' hervor.
Autor: Bernhard R. (barnyhh)
Datum: 30.03.2008 17:36

Hypothese:

Es gibt anscheinend irgendeine Situation, in der folgendes passiert:
- PCIE wird auf 0 gesetzt (disabled) (in der PCINT-Routine)
- PCIE wird auf 1 gesetzt (enabled) (in der Timer-Routine)
>>>>> Die PCINT-Logik glaubt irrtümlich, sie sei disabled
      rsp.
>>>>> Die PCINT-Logik "verschlabbert" alle nachfolgenden Pegelwechsel am Pin.

Ungesichterte Ursache evtl. in 9.2.2 Pin Change Interrupt Timing ?

Ob der AVR tatsächlich im power-down-mode bleibt, ließe sich evtl. durch 
Benutzen eines anderen PCINT-Pins und dann Auslösen von INT0 
herausfinden (wenn er aufwacht, hat er wohl geschlafen :-).

Autor: concept (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach so, es ist übrigens keine LED oder so angeschlossen, ist ein reines 
Testprogramm. Beim Betätigen des Tasters / bei jedem PCINT sollte es 
einen Impuls geben, mit einem wenig prellenden Taster funktioniert das 
häufig, mit einem prellenden (1ms) Mikroschalter gibt es den Impuls nur 
bei der fallenden Flanke (Taster drücken).

Autor: concept (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
.. und dann keine Reaktion auf den Tastendruck mehr.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, ich hab Dein Programm ausprobiert und es funktioniert nicht.

Aber ich hab den Fehler gefunden, es liegt am sleep_mode();

Ersetze Deine Mainloop hiermit:

  for (;;)
  {
    asm volatile("sleep"); // nur Sleep und nichts weiter !
//    sleep_mode();        // das ist nicht Interrupt fest !
  }


und dann läuft es.

Das Kommando sleep_mode(); hat jemand geschrieben, der nicht daran 
gedacht hat, daß Du das MCUCR in nem Interrupt manipulierst.

Es macht noch irgendwas mit dem MCUCR-Register rum und wenn da ein 
Interrupt einschlägt, dann steht der ganze Laden forever.


Peter

Autor: Peter Dannegger (peda)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
P.S.:
Sämtliche sleep Funktionen gehen nicht, wenn Du sie in Interrupts 
verwendest.
Dann mußt Du alles selber machen, siehe Anhang.


Peter

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
P.P.S.:

Das sleep_mode(); muß man so umdefinieren:

#ifdef sleep_mode
#undef sleep_mode
#define sleep_mode()\
    cli();\
    MCUCR |= 1<<SE;\
    sei();\
    asm volatile("sleep");\
    cli();\
    MCUCR &= ~(1<<SE);\
    sei();
#endif

Dann kann man set_sleep_mode(); wieder benutzen.


Peter

Autor: Hagen Re (hagen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oder man arbeitet so
sleep_mode(XYZ);
sleep_enable();
sei();
while (1) {
  sleep_cpu();
}

was das Gleiche macht wie Peters erster Vorschlag.

Du solltest ein *.LST und *.LSS File erzeugen lassen (im Makefile) und 
dir dann dort den erzeugten ASM-Code des Compilers anschauen.

Gruß Hagen

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es steht ja eigentlich alles in der sleep.h:

"As this combined macro might cause race conditions ..."

Man muß es eben bloß lesen, statt einfach so ohne Überlegung die Macros 
hinzuschreiben.


Unverständlich finde ich aber, warum diese tickende Zeitbombe 
sleep_mode(); überhaupt definiert wurde.

Hier hat man ja den Vorteil, daß die Mainloop es schön oft aufruft und 
der Fehler schnell auftritt.

Wenn man aber reale Programme hat und die dann nur alle 24h einfrieren, 
dann legt man sich die Karten (oder schmeißt den ganze AVR-Krempel aus 
dem Fenster und nimmt nen PIC).



Peter

Autor: concept (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Super, danke für die Erklärung!

> Man muß es eben bloß lesen, statt einfach so ohne Überlegung die Macros
> hinzuschreiben.

Das ist richtig, aber als Anfänger ist man noch in unbekannten Gewässern 
- und verläßt sich auf's Tutorial und den Compiler. Nächstesmal weiß 
ich's ein bißchen besser.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
concept wrote:
> Super, danke für die Erklärung!
>
>> Man muß es eben bloß lesen, statt einfach so ohne Überlegung die Macros
>> hinzuschreiben.

War nicht böß gemeint, ich hab ja selber das Grübeln gekriegt.

Ich habs erst beim Anschauen des Assemblerlistings gesehen, daß dieses 
Macro nicht das macht, was ich erwartet hätte.

Ich hab dann sämtliche Macros rausgeschmissen und von Hand gemacht und 
dann gings.

Dann erst hab ich mir die sleep.h gründlicher vorgenommen.


Peter

Autor: concept (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles klar ;-)

Mich wundert allerdings, dass der Fehler nicht (zumindest nicht sofort) 
auftrat, wenn der Interrupt über die Pin-Maske ausgeschaltet worden ist.
Vielleicht, weil das Interrupt-Timing nicht so lange dauert, und die 
Wahrscheinlichkeit der 'race condition' beim Prellen kleiner war.

Jedenfalls schön, dass jetzt Verlaß auf's Programm ist, wenn ich nachher 
daran arbeite / spiele.

Autor: flyingwolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi.
Nur mal so aus Neugier:

> Sämtliche sleep Funktionen gehen nicht, wenn Du sie in Interrupts
> verwendest.

Mal hypothetisch:
Ein Gerät mit Batterie und Stromversorgung soll bei Wegfall der 
Stromversorgung im Batteriebetrieb in den Speep-Modus verfallen um die 
Entladezeit (strom) der Batterie zu reduzieren.
Bei einem System das 20, 30 oder mehr mA an Strom konsumiert, bleibt da 
nicht viel Zeit, den Spannungsausfall zu bemerken und schnell schlafen 
zu gehen.

Wie würde man sowas dann lösen wenn der Sleep-Mode nicht in einer 
Interruproutine ausgelöst werden kann? Polling wäre ja bei den meisten 
Anwendungen viel zu langsam.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Er meinte damit die im Header definierten Sleep-C-Funktionen, nicht die 
Sleep-Funktion des Controllers im allgemeinen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.