Hi, http://www.mikrocontroller.net/articles/AVR_Checkliste#Flag_richtig_gel.C3.B6scht.3F > Zusätzlich ist zu beachten, dass in C die Interrupt-Flags nicht mit einer > Veroderung des Registers (z. B. TIFR |= (1 << TOV0)) gelöscht werden > sollten, da bei dieser Operation alle anderen evtl. gesetzten Flags im > betreffenden Register ebenfalls gelöscht werden. Es ist die Schreibweise > von oben zu benutzen (also TIFR = (1 << TOV0))! ??? !!! Stimmt das wirklich? Wenn ich wirklich nur zu doof bin, löscht dieses Posting bitte.
Tom schrieb: > ??? !!! Stimmt das wirklich? Die Interruptflagregister verhalten sich anders als "normale" Register. Dort wird ein gesetztes Flag gelöscht, indem eine '1' hieneingeschrieben wird (siehe Datenblatt " TOV0 is cleared by writing a logic one to the flag."). Wenn jetzt aber sowas dasteht:
1 | TIFR |= (1 << TOV0)) |
Dann heißt das ja, dass zuerst das Register gelesen wird, dann ein Bit dazuverodert, und dann alles wieder zurückgeschrieben wird (ein Read-Modify-Write eben). Das könnte ausführlich auch so geschrieben werden:
1 | h = TIFR; |
2 | h = h|(1 << TOV0)); |
3 | TIFR = h; |
Wenn jetzt blöderweise andere Interruptbits auch gesetzt sind, dann werden die als Kollateralschaden mit gelöscht. Wenn z.B. TIFR == 0010 0001 ist und dann das alles abgearbeitet wird: h = TIFR; ---> h == 0010 0001 h = h|(1 << TOV0)); ---> h == 0010 0001 Und wenn das zurückgeschrieben wird, dann werden beide Interrupt-Flags gelöscht: TIFR = h; ---> TIFR == 0000 0000 :-o Besser wäre also noch sowas: TIFR &= (1 << TOV0)); Und am einfachsten geht es tatsächlich so: TIFR = (1 << TOV0));
Alles klar, danke! Ich glaube, ich brauche doch erstmal nen Kaffee.
OK, mein Denkfehler war der, dass ich das für eine einfache Zuweisung, nur halt mit invertierter Wirkung, hielt. Bei einer direkten Zuweisung des ganzen Registerinhaltes würden dann durch das Schreiben der Nullen in die Flagpositionen, die nicht ge/löscht/ werden, die Flags dort ge/setzt/ werden werden. Aber das scheint die Hardware zu verhindern.
Tom schrieb: > Bei einer direkten Zuweisung des ganzen Registerinhaltes würden dann > durch das Schreiben der Nullen in die Flagpositionen, die nicht > ge/löscht/ werden, die Flags dort ge/setzt/ werden werden. Nein. Du kannst diese Flags nur löschen. Gesetzt werden sie durch die Hardware. Aber: Du willst immer nur dieses EINE Flag löschen, welches du löchen willst! Alle anderen sollen nicht beeinflusst werden.
Tom schrieb: > OK, mein Denkfehler war der, dass ich das für eine einfache Zuweisung, > nur halt mit invertierter Wirkung, hielt. Richtig, das war der Denkfehler. > Aber das scheint die Hardware zu verhindern. Zum Glück... ;-) Dieses Verhalten findet man bei einigen anderen uC-Familien bei solch kritischen Registern, die auf Read-Modify-Write-Befehle allergisch reagieren (könnten). Es gibt dann evtl. sogar getrennte Register zum Setzen von Flags und Löschen vom Flags. Wenn dann in also das "Setz-Register" eine '1' geschrieben wird, wird das Bit gesetzt, wenn in das "Lösch-Register" eine '1' geschrieben wird, wird das entsprechende Bit im Zielregister zurückgesetzt. Beim AVR gibt es von dieser "Vollausstattung" quasi nur das Lösch-Register.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.