www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik [wiki] AVR Flag verodern wirklich falsch?


Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

http://www.mikrocontroller.net/articles/AVR_Checkl...

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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
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:
h = TIFR;
h = h|(1 << TOV0));
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));

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles klar, danke!

Ich glaube, ich brauche doch erstmal nen Kaffee.

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

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.