Hallo Community, mein erster Post hier, deshalb erst einmal ein 'Hallo' in die Runde :) Tolle Seite/Forum. Hab schon viele nützliche Infos bei euch gefunden. Bin gerade dabei was für einen 8051 zu schreiben (AT89C51CC03) und habe zwei grundsätzliche Fragen zur Interruptbehandlung. Hab schon eine ganze Weile gesucht, aber keine wirklich befriedigende Antworten gefunden. In eurem Interrupt Tut steht folgendes: "Beim AVR ist das das I-Bit (Interrupt) im Statusregister (SREG). Dieses Bit wirkt wie ein Hauptschalter und kann global die Ausführung aller Interrupts ein - und ausschalten. Das heisst aber nicht, dass während der Zeit der inaktiven Interrupts diese verloren gehen. Vielmehr wird das jeweilige Interruptbit gesetzt, und wenn die Interrupts wieder freigegeben werden wird der Interrupt ausgeführt. Verloren gehen Interrupts erst dann, wenn die Sperrzeit zu groß ist und währenddessen mehr als ein Interrupt vom selben Typ eintrifft." Ist es auch beim 8051 so, dass ich z.B. kurzzeitig alle Interrupts ausschalte kann und nach dem wieder-einschalten die "angesammelten" Interrupts abgearbeitet werden? Anhand der Strukturschaltpläne des Interruptsystems im Datenblatt kann man eventuell davon ausgehen, aber sicher bin ich mir eben nicht. Eine zweite Frage noch: Der 8051 besitzt nur 1 Interrupt für die UART, der sowohl das Senden als auch das Empfangen bedient. Sehe ich das richtig, das es damit bei Full-Duplex Anwendungen nicht möglich ist 100% sicheren Code zu schreiben (also in Bezug auf das Verschlucken eines Sende- oder Empfangsinterrupts)? In allen Beispielen wird immer nur aufgeführt, dass man den Interrupt durch die beiden Bit's (TI und RI) unterscheiden kann, jedoch steht nirgendwo, dass das eigentlich problematisch ist, egal wie kurz die ISR ist.
> In eurem Interrupt Tut steht folgendes: > ... Wenn du dich mit einem 8051 beschäftigt, schaue nicht bei anderen Controller-Architekturen nach Infos! Das bringt dich durcheinander, weil du die Infos mischen wirst! > Ist es auch beim 8051 so, dass ich z.B. kurzzeitig alle Interrupts > ausschalte kann und nach dem wieder-einschalten die "angesammelten" > Interrupts abgearbeitet werden? Anhand der Strukturschaltpläne des > Interruptsystems im Datenblatt kann man eventuell davon ausgehen, aber > sicher bin ich mir eben nicht. 1) Beim 805x gibt es Interruptprioritäten. Ein höher priorisierter Interrupt unterbricht einen laufenden niederpriorisierten Interrupt. Man kann die Prio eines Interrupts je nach Derivat höher setzen. 2) Interrupts werden durch ihr eigenes Interrupt-Enable-Flag scharf geschalten und zusätzlich durch das globale Interrupt Enable Flag. D.h. wenn das IE-Flag gelöscht ist, gibt's GAR keinen Interrupt. 3) Es ist beim 8051 normalerweise nicht notwendig, einen Interrupt wieder zu deaktivieren. Kommt natürlich auf die Applikation an, aber im Normalfall ist es nicht nötig. > Sehe ich das richtig, das es damit bei Full-Duplex Anwendungen nicht > möglich ist 100% sicheren Code zu schreiben (also in Bezug auf das > Verschlucken eines Sende- oder Empfangsinterrupts)? Siehst du falsch :) > In allen Beispielen wird immer nur aufgeführt, dass man den Interrupt > durch die beiden Bit's (TI und RI) unterscheiden kann, jedoch steht > nirgendwo, dass das eigentlich problematisch ist, egal wie kurz die ISR > ist. Das steht deshalb nirgends, weil nicht problematisch IST. Der Sende-Interrupt wird beim Senden des Stopbits ausgelöst. Entweder schiebst du ein weiteres Byte in den Sendebuffer oder nicht. Wo soll es da Timing-Probleme geben. Genauso beim Empfangen. Byte wegsichern, und gut :) Weitere Fragen? :) Ralf
> Weitere Fragen? :) Jap ;) und Danke erstmal für die flotte Antwort! > 1) Beim 805x gibt es Interruptprioritäten. Ein höher priorisierter > Interrupt unterbricht einen laufenden niederpriorisierten Interrupt. Man > kann die Prio eines Interrupts je nach Derivat höher setzen. > 2) Interrupts werden durch ihr eigenes Interrupt-Enable-Flag scharf > geschalten und zusätzlich durch das globale Interrupt Enable Flag. D.h. > wenn das IE-Flag gelöscht ist, gibt's GAR keinen Interrupt. > 3) Es ist beim 8051 normalerweise nicht notwendig, einen Interrupt > wieder zu deaktivieren. Kommt natürlich auf die Applikation an, aber im > Normalfall ist es nicht nötig. Die Sachen sind mir soweit klar. Nehmen wir aber an ich hab einige Befehle in einer niedrig Priorisierten ISR, für dessen Ausführung es dringend notwendig ist auch höher priorisierte Interrupts kurzzeitig zu deaktivieren. Tritt nun innerhalb dieses Code-Teils ein höher Priorisierter Interrupt auf... ist der dann für immer weg. oder "greift" der dann wieder nachdem ich die Interrupts wieder eingeschaltet habe (EA=1), mal unabhängig davon, ob das vom Code her sinvoll ist oder nicht. > Das steht deshalb nirgends, weil nicht problematisch IST. > Der Sende-Interrupt wird beim Senden des Stopbits ausgelöst. Entweder > schiebst du ein weiteres Byte in den Sendebuffer oder nicht. Wo soll es > da Timing-Probleme geben. > Genauso beim Empfangen. Byte wegsichern, und gut :) Folgende Überlegung: RxD Interrupt kommt -> Sprung in die entsprechende ISR -> Überprüfung TI == 1 -> nein, also weiter -> TxD Interrupt kommt zufällig gerade jetzt (es passiert natürlich nix, weil wir noch in der ISR sind) -> SBUF auf Empfangspuffer sichern, weil TI ja 0 war -> ISR verlassen So verschwindet der TxD Interrrupt im Nirvana, oder hab ich einen Denkfehler in der Überlegung?
Weder der TxD noch der RxD verschwindet im Nirwana. Es genügt am Anfang der Seriellen ISR zu Prüfen ob RxD oder TxD ausgelöst hat. Ich ziehe den RxD vor, weil es nicht stört ein Byte etwas später zu senden, als ein Empfangenes zu spät zu sichern. Der serielle Int ist die Veroderung des RxD und TxD-Ints. Ein neuer! TxD kann erst kommen, wenn ein Byte rausgeschoben wurde, also kein Byte senden, kein Interrupt. Hat während der Abarbeitung des einen Int, egal ob RxD oder TxD, der andere Int. ausgelöst, wird nach der ISR ein weiterer Befehl des Progs abgearbeitet und sofort wieder die Serielle ISR aufgerufen.
> Hat während der Abarbeitung des einen Int, egal ob RxD oder TxD, > der andere Int. ausgelöst, wird nach der ISR ein weiterer Befehl des > Progs abgearbeitet und sofort wieder die Serielle ISR aufgerufen. Ok. Das ist eindeutig! (auch wenn ich mir nicht erklären kann wie das dann hardwaremäßig realisiert wird, wenn es einfach eine Veroderung ist, wie es auch in den Datenblättern immer steht). Danke für die Hilfe!
> ...oder "greift" der dann wieder nachdem ich die Interrupts wieder > eingeschaltet habe (EA=1), mal unabhängig davon, ob das vom Code her > sinvoll ist oder nicht. Richtig erkannt, wobei ich es (wenn ich es denn mal machen müsste) vorziehen würde, nur den relevanten (=höher priorisierten) Interrupt zu sperren. Aber nochmal: Wenn die Interrupts richtig geschrieben sind besteht dazu m.E. keine Notwendigkeit. Durch das Sperren des Interrupts wird ja nur verhindert, dass die Interrupt-Service-Routine angesprungen wird, die Flags, die den Interrupt auslösen sind ja nach wie vor aktiv, d.h. nach dem Freischalten wird der entsprechende Interrupt angesprungen. Aber Vorsicht, man sollte nicht zu lange sperren, weil nur ein Interrupt gespeichert wird, d.h. wenn du beispielsweise solange sperrst wie zwei Bytes brauchen, um empfangen zu werden, dann geht eins davon sicher flöten! > auch wenn ich mir nicht erklären kann wie das dann hardwaremäßig > realisiert wird, wenn es einfach eine Veroderung ist, wie es auch in den > Datenblättern immer steht) Nicht so kompliziert denken :) Die Sendeschaltung löst setzt ein Flag (TI), wenn das Byte den seriellen Port inklusive Stopbit verlassen hat. Die Empfängerschaltung setzt ein Flag (RI) nach dem gemäß der eingestellten Baudrate erwarteten Zeitpunkt des Stopbits. Beide Flags zusammen werden verodert und das Ergebnis der Interrupt-Schaltung zugeführt. Ralf
Ralf schrieb: > Die Sendeschaltung löst setzt ein Flag (TI), wenn das Byte den seriellen > Port inklusive Stopbit verlassen hat. Die Empfängerschaltung setzt ein > Flag (RI) nach dem gemäß der eingestellten Baudrate erwarteten Zeitpunkt > des Stopbits. > Beide Flags zusammen werden verodert und das Ergebnis der > Interrupt-Schaltung zugeführt. Das ist je gerade mein Problem. Wenn ich davon ausgehe, das die Interruptlogik in irgend einer Weise auf steigende Flanken dieser Bit's triggert, wie kann sie dann indem oben beschriebenen Fall triggern, wenn durch das ODER der Pegel auf der "Leitung" die ganze Zeit auf High gehalten wird. Aber im Grunde ist das ja auch erst einmal nicht so wichtig, solange es so funktioniert, wie ich es haben möchte :).
> Wenn ich davon ausgehe, das die Interruptlogik in irgend einer Weise auf > steigende Flanken dieser Bit's triggert, wie kann sie dann indem oben > beschriebenen Fall triggern, wenn durch das ODER der Pegel auf der > "Leitung" die ganze Zeit auf High gehalten wird. Wer sagt denn, dass die Interruptlogik auf steigende Flanken reagiert? :) Mal angenommen, es kommt ein Byte rein und setzt RI. Du bist noch in einem höher priorisierten Interrupt, währenddessen wird das aktuell zu sendende Byte auch rausgepustet. Du verlässt den höher priorisierten Interrupt. Der UART-Interrupt kommt dran, mit RI und TI gesetzt. Die ISR sieht, dass RI gesetzt ist, löscht das RI-Flag, holt das empfangene Byte aus dem Empfangsregister und speichert es weg. Somit ist nur noch TI am "Oder" aktiv. Das gleiche Spiel: TI wird gelöscht, und nach Bedarf ein weiteres Byte geholt und in das Senderegister geschoben. Fertig. Alle Eingänge des "Oders" auf Low. Besser jetzt? :) Ralf
Tobias H. schrieb: > Nehmen wir aber an ich hab einige > Befehle in einer niedrig Priorisierten ISR, für dessen Ausführung es > dringend notwendig ist auch höher priorisierte Interrupts kurzzeitig zu > deaktivieren. Nun, dann hast Du was falsch gemacht. Die höhere Priorität weist man ja gerade deshalb zu, damit er andere Interrupts unterbrechen darf. Willst Du das nicht, weise einfach die gleiche Priorität zu. Natürlich kann man für atomare Zugriffe jederzeit das EA-Bit kurz mal löschen. Tobias H. schrieb: > Tritt nun innerhalb dieses Code-Teils ein höher > Priorisierter Interrupt auf... ist der dann für immer weg. Jede Interruptquelle hat ein Pending-Flag und solange dieses gesetzt ist, wird geprüft, ob der Interrupt ausgeführt werden darf. Einige Interrupts löschen das Flag automatisch beim Eintritt, bei anderen muß man es manuell löschen. Der Begriff Priorität hat beim AVR und 8051 unterschiedliche Bedeutung, daher gibt es oftmals große Verwirrung. Beim 8051 legt die Priorität wirklich fest, welcher Interrupt einen anderen unterbrechen darf. Beim AVR ist damit aber nur die Abarbeitungsfolge gemeint, wenn bei der Interruptfreigebe mehrere Interrupts anhängig sind (Pending-Bit gesetzt). Das nennt sich beim 8051 Polling Sequence. Daher gibt es beim AVR regelmäßig Fragen, wo man denn nun die Priorität einstellt. Die Antwort ist: garnicht. Peter
> Wer sagt denn, dass die Interruptlogik auf steigende Flanken reagiert? > :) Hast du natürlich recht.. > Besser jetzt? :) Ja :) > Natürlich kann man für atomare Zugriffe jederzeit das EA-Bit kurz mal > löschen. Genau dafür brauche ich es auch! Mit den AVR's hab ich (kaum) praktische Erfahrung. Nur halt schon viel gelesen, weil ich da demnächst auch mal ein bisschen mit rumspielen will. Muss aber sagen, dass das mit den vielen (wirklich priorisiebaren) Interrupts beim 8051 schon 'ne tolle Sache ist :). Vielen Dank nochmal für eure Antworten. Hat mir sehr geholfen!
> Vielen Dank nochmal für eure Antworten. Jederzeit wieder :) > Hat mir sehr geholfen! Freut uns ^^ Ralf
Für weitere Erklärungen guggst Du hier (ab S. 52): www.atmel.com/atmel/acrobat/doc0499.pdf ([PDF] AT89 Series Hardware Description - Atmel Corporation)
Nachtrag: der ..CC03 ist im Dokument nicht explizit gelistet. Das mag daran liegen, dass die Doku schon einige Jahre auf dem Buckel hat und der uC damals noch nicht im Protfolio war. Es ist davon auszugehen, dass die dargestellte Struktur auch in den ..CC03 übernommen wurde.
Tobias H. schrieb: >> Natürlich kann man für atomare Zugriffe jederzeit das EA-Bit kurz mal >> löschen. > Genau dafür brauche ich es auch! Wobei ein Datenaustausch direkt zwischen Interrupts ein äußerst seltener Fall sein dürfte. In der Regel müssen Daten erstmal verarbeitet werden und Interrupts sollten aber kurz gehalten sein. Üblich ist daher, Daten zwischen Main und Interrupts zu übertragen, d.h. nur das Main muß atomare Zugriffe machen: - 1.Interrupt empfängt Daten - Main verarbeitet Daten - 2.Interrupt gibt Daten aus Peter
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.