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


von concept (Gast)


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?

von Der S. (schubi)


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

von Michael G. (linuxgeek) Benutzerseite


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.

von Der S. (schubi)


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.

von Michael G. (linuxgeek) Benutzerseite


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."

von Peter D. (peda)


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:
1
Example:
2
\code
3
#include <avr/interrupt.h>
4
#include <avr/sleep.h>
5
6
...
7
  cli();
8
  if (some_condition) {
9
    sleep_enable();
10
    sei();
11
    sleep_cpu();
12
    sleep_disable();
13
  }
14
  sei();
15
\endcode


Peter

von Der S. (schubi)


Lesenswert?

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

von AVRFan (Gast)


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."

von concept (Gast)


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?

von Peter D. (peda)


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

von concept (Gast)


Lesenswert?

Zusammenfassung:

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

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.
1
Autor: Bernhard R. (barnyhh)
2
Datum: 30.03.2008 17:36
3
4
Hypothese:
5
6
Es gibt anscheinend irgendeine Situation, in der folgendes passiert:
7
- PCIE wird auf 0 gesetzt (disabled) (in der PCINT-Routine)
8
- PCIE wird auf 1 gesetzt (enabled) (in der Timer-Routine)
9
>>>>> Die PCINT-Logik glaubt irrtümlich, sie sei disabled
10
      rsp.
11
>>>>> 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 :-).

von concept (Gast)


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).

von concept (Gast)


Lesenswert?

.. und dann keine Reaktion auf den Tastendruck mehr.

von Peter D. (peda)


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:
1
  for (;;)
2
  {
3
    asm volatile("sleep"); // nur Sleep und nichts weiter !
4
//    sleep_mode();        // das ist nicht Interrupt fest !
5
  }

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

von Peter D. (peda)


Angehängte Dateien:

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

von Peter D. (peda)


Lesenswert?

P.P.S.:

Das sleep_mode(); muß man so umdefinieren:
1
#ifdef sleep_mode
2
#undef sleep_mode
3
#define sleep_mode()\
4
    cli();\
5
    MCUCR |= 1<<SE;\
6
    sei();\
7
    asm volatile("sleep");\
8
    cli();\
9
    MCUCR &= ~(1<<SE);\
10
    sei();
11
#endif
Dann kann man set_sleep_mode(); wieder benutzen.


Peter

von Hagen R. (hagen)


Lesenswert?

oder man arbeitet so
1
sleep_mode(XYZ);
2
sleep_enable();
3
sei();
4
while (1) {
5
  sleep_cpu();
6
}

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

von Peter D. (peda)


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

von concept (Gast)


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.

von Peter D. (peda)


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

von concept (Gast)


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.

von flyingwolf (Gast)


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.

von Stefan E. (sternst)


Lesenswert?

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

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.