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?
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...
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.
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.
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."
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:
>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."
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?
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
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 :-).
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).
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
asmvolatile("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
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
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
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.
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
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.
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.
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