Hallo, folgendes Verständnisproblem. > This flag is set... > Writing a ‘1’ to this bit clears the flag. Wie ist das zu verstehen? Es steht schon eine "1", und um sie zu löschen muss man eine "1" schreiben? Müsste eine "0" geschrieben werden, wäre es aus meiner Sicht selbstverständlich, aber so wie jetzt, brauche ich eine Erläuterung.
Georg M. schrieb: > Wie ist das zu verstehen? Es steht schon eine "1", und um sie zu löschen > muss man eine "1" schreiben? Eben so. > Müsste eine "0" geschrieben werden, wäre es aus meiner Sicht > selbstverständlich, aber so wie jetzt, brauche ich eine Erläuterung. Das ist ein Register, kein Speicher. Es kann alles an Logik hinter dem Bit stecken.
Es ist sehr einfach, aus Versehen eine 0 zu schreiben. Eine 1 zu schreiben musst du schon wollen. Dadurch verringert sich die Gefahr, das Bit versehentlich zu löschen. Und eine 1 lässt sich besser maskieren. Und die internen Flipflops haben evtl. einen Reset-Eingang, der mit einer 1 das FF resettet.
Solche Register haben noch einen Vorteil: Man kann jeweils exakt die Flags löschen, die man zuvor abgefragt hat, und in einer Schleife alle weiter aufgetretenen Flags verarbeiten:
1 | uint8_t flags = INTFLAGS; |
2 | do { |
3 | // Die jetzt bearbeiteten Flags löschen
|
4 | INTFLAGS = flags; |
5 | |
6 | if (flags & (1 << CMP)) { |
7 | // CMP aufgetreten...
|
8 | }
|
9 | if (flags & (1 << OVF)) { |
10 | // OVF aufgetreten...
|
11 | }
|
12 | // Neue Flags abfragen
|
13 | flags = INTFLAGS; |
14 | } while (flags != 0); |
Wenn während der Bearbeitung neue Interrupts auftreten, muss die ISR nicht verlassen und erneut betreten werden (langsam), sondern nur direkt die Schleife neu starten. Wenn nach der Schleife neue Interrupts auftreten, wird die ISR aber doch erneut betreten. So kann man sicherstellen dass kein Ereignis verschluckt wird, es sei denn es tritt in sehr kurzer Folge der gleiche Interrupt noch einmal auf; das lässt sich aber sowieso nur durch schnelle Abarbeitung verhindern. Besonders bei komplexerer Peripherie auf größeren Controllern mit vielen verschiedenen Interrupts (z.B. Timer oder USB-OTG bei den STM32) ist so ein Vorgehen sinnvoll.
Sebastian R. schrieb: > Es ist sehr einfach, aus Versehen eine 0 zu schreiben. Na ja, wenn es nur 0 und 1 gibt, ist die Chance, eins von beiden ausversehen zu schreiben, ziemlich gleich verteilt. Oliver
Man liest das Flag-Register, speichert den Wert temporär und hat alle gesetzten Flags damit erfaßt. Um sie zu löschen, wird der gelesene Wert wieder geschrieben. Wenn zwischendurch noch weitere Flags gesetzt wurden, die noch nicht erkannt wurden, bleiben diese weiterhin gesetzt. Eine ganz saubere Sache!
Nop schrieb: > Das ist ein Register, kein Speicher. Es kann alles an Logik hinter dem > Bit stecken. Das heißt, dieses Byte, diese 8 R/W-Bits, das ist nur eine vereinfachte irreführende Darstellung? In Wirklichkeit ist alles anders und viel komplizierter?
Georg M. schrieb: > Das heißt, dieses Byte, diese 8 R/W-Bits, das ist nur eine vereinfachte > irreführende Darstellung? Es ist nunmal die Schnittstelle, auf die der CPU-Kern zugreift. In diesem Fall sind es ja nichtmal 8 bits. Der AVR-CPU-Kern kann 8 Bits über den Bus lesen und schreiben, und die Peripherie präsentiert ihre Signale eben als 8-Bit-Register. Die interne Logik muss sich aber nicht verhalten wie eine gewöhnliche Speicherzelle...
Georg M. schrieb: > Das heißt, dieses Byte, diese 8 R/W-Bits, das ist nur eine vereinfachte > irreführende Darstellung? Es ist vereinfacht, und die entscheidende Info dabei ist, ob man die Bits nur lesen oder auch schreiben kann. Es gibt ja auch read-only-bits. > In Wirklichkeit ist alles anders und viel komplizierter? Sozusagen. Wenn man in einen Speicher was reinschreibt, wird es da gespeichert und gut. Bei einem Register kann dahinter alles mögliche passieren. Es gibt ja auch Register, wo man eine 1 reinschreiben darf, aber beim Zurücklesen kommt trotzdem immer 0.
Beim AVR ist die Sache recht verzwickt, er kann die meisten Interruptbits nicht atomar löschen. D.h. liest man ein IO-Register, setzt einzelne Bits auf 0 und schreibt es wieder zurück, können in der Zwischenzeit eingetroffene Interrupts im selben IO-Register verloren gehen. Daher der Umweg, daß nur gesetzte Bits gelöscht werden, nicht gesetzte bleiben unverändert. Z.B. beim 8051 ist ein atomares AND/OR im IO-Bereich möglich, daher werden dort die Interrupts mit auf 0 setzen gelöscht. Und man kann sogar Interrupts in SW setzen. Z.B. füllt man eine FIFO und startet dann das erste Byte senden mit dem Setzen des TI-Bits.
Sebastian R. schrieb: > Es ist sehr einfach, aus Versehen eine 0 zu schreiben. Eine 1 zu > schreiben musst du schon wollen. Dadurch verringert sich die Gefahr, das > Bit versehentlich zu löschen. Nein, das ist nicht der Grund für dieses Registerverhalten. Der Grund ist, dass man nur so einzelne Flags löschen kann, ohne gleichzeitig die anderen auch zu beeinflussen. Eine 0 beeinflusst das Bit nicht. Es behält seinen vorherigen Zustand. Auch durch klassisches auslesen-modifizieren-schreiben wäre das Problem nicht lösbar, weil sich in der Zwischenzeit das Bit ändern könnte.
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.