Unterbrechen eines Befehls durch ISR Im Unterforum Microcontroller - Beschreibung: Hardware - Software - Ideen - Projekte
Autor |
Unterbrechen eines Befehls durch ISR |
|
|
|
|
BID = 570861
speedo7 Gerade angekommen
Beiträge: 2 Wohnort: Hamburg
|
|
Hallo,
ich frage mich wie das Unterbrechen eines Befehls durch eine ISR abläuft.
Wenn ich folgenden Befehle benutze um den Pin2 des Ports B zu setzen:
(I) PORTB |= _BV(PB2); // 2 Takte
Und ich habe eine ISR die am gleichen Port B aber einen anderen Pin (z.B.: PB3) setzen möchte, dann kann es doch passieren, das der Befehl (I) durch ein Befehl in der ISR nicht erkannt wird, da die ISR eine höhere Priorität hat und der Befehl(I) 2 Takte benötigt?
Ich habe mir das mal so dargestellt, wenn ich die Reihenfolge der von der CPU ausgeführten Schreib- und Leseanweisungen betrachte:
[ PORTB |= _BV(PB2) <=> laden und setzen <=> LDI R1,x + MOV R2,R1 ]
Also es wird erst geladen:
LDI R1, x
Dann tritt die ISR auf...
Die ISR verdrängt erstmal den MOV Befehl für eine Zeitdauer und in dieser Zeit wird das Register R1 überschrieben.
Nachdem die ISR fertig ist, wird der MOV Befehl ausgeführt.
Damit wurde der LDI Befehl nicht erkannt! Oder?
Gruß speedo
|
|
BID = 570872
perl Ehrenmitglied
Beiträge: 11110,1 Wohnort: Rheinbach
|
|
Erstens habe ich keine Ahnung, welchen Prozessor du meinst, zweitens sind die meisten Maschinenbefehle nicht unterbrechbar, und drittens steht es gewöhnlich genauestens in den Datenblättern, in welcher Phase der Befehlsausführung die Interruptbedingung getestet wird.
Manchmal geschiegt das sogar mit einer Verzögerung von einem ganzen Maschinenbefehl, damit man z.B. aus der ISR wieder herauskommt.
_________________
Haftungsausschluß:
Bei obigem Beitrag handelt es sich um meine private Meinung.
Rechtsansprüche dürfen aus deren Anwendung nicht abgeleitet werden.
Besonders VDE0100; VDE0550/0551; VDE0700; VDE0711; VDE0860 beachten ! |
|
BID = 570988
selfman Schreibmaschine
Beiträge: 1681 Wohnort: Seekirchen a. W.
|
Unterbrochen wird, wie perl schon sagt, nach einem vollendeten Befehl (Maschinenzyklus) auch wenn dieser 2,3,.. oder 23 Takte dauert.
Danach wird der Programmcounter auf den Stack gerettet und die Adresse der Interruptroutine in den PC geladen.
Was von jetzt an passiert, bleibt dem Programmierer überlassen. Wenn Registerinhialte verändert werden, dann tut man gut daran, wenn man diese auch auf den Stack oder sonstwohin "rettet", ebenso wie die Statusflags, die Interruptlogik kümmert sich meist nicht darum. Bei manchen Prozessoren kann man auch oft ganz geschickt mit einem "Bankswitch" die Registerbank umschalten und braucht nicht alle Register einzeln sichern.
Danach kann die Rotuine furwerken wie sie will, sie muß nur nach Beedigung der Arbeit alle Registerwert wieder herstellen wie sie waren und mit "RETI" (Return from Interrupt) abschlossen werden. Dieser erledigt dann den Rücksprung ansich.
Schöne Grüße Selfman
_________________
Traue keinem Ding, das du nicht selber vermurkst hast.
|
BID = 571115
hajos118 Schreibmaschine
Beiträge: 2453 Wohnort: Untermaiselstein
|
Zu ergänzen wäre vlt. noch, dass bei Hochsprachen (C, BASIC ...) nicht vorhersagbar ist, ob eine Interruptroutine tatsächlich nach einem (Hochsprachen-)Befehl abgearbeitet wird oder irgendwo dazwischen...
Beispiel:
Eine Float Variable wird gerade abgespeichert .... und mittendrin wird ein Interrupt aktiv. - In der Interrupt - Routine kann man NICHT davon ausgehen, dass diese Float Variable konsistent ist(d.h. einen gültigen Wert hat).
In Deinem Beispiel (Veroderung eines Bits) ist's ähnlich, aber nicht so kritisch, da sich die zu verarbeitenden Daten auf 1 Byte beschränken und auf nur 1 Maschinenbefehl reduziert wurden (und der ist nicht unterbrechbar)
P.S.: Handelt es sich um einen Atmel?
_________________
Interpunktion und Orthographie dieses Beitrags sind frei erfunden.
Eine Übereinstimmung mit aktuellen oder ehemaligen Regeln wäre rein zufällig und ist nicht beabsichtigt.
Wer einen Fehler findet, darf ihn behalten!
|
BID = 571139
speedo7 Gerade angekommen
Beiträge: 2 Wohnort: Hamburg
|
Es handelt sich um einen Atmel.
|
BID = 571243
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Weil es irgendwann wehtut: Atmel ist der Hersteller, und dieses Wort sagt rein garnichts, aber auch überhauptgarnix über die zugrundeliegende Architektur.
Es handelt sich wohl eher um einen AVR-Core, welcher z.B. gänzlich anders aufgebaut ist als z.B. ein ARM. Das dazu.
Nun zum Thema:
Du sagtst, folgender Befehl dauert 2 Zyklen:
PORTB |= _BV(PB2); // 2 Takte
Das ist korrekt, aber auch nur, weil der Compiler das in die für einen gewissen IO-Adressbereich gültige Instruktion sbi a,b kodiert.
Und diese dauert nunmal zwei Zyklen und ist, wie bereits erwähnt wurde, nicht unterbrechbar.
Selbst ein völlig _ischer Compiler würde daraus kein
LDI R1,x
MOV R2,R1
machen, denn das ergibt keinen Sinn. Unter anderem kann in ein Register kleiner 0x10 kein Wert sofort geladen werden.
Normalerweise würde es eher so aussehen:
LDI 0x18, 0x4
IN 0x19, PORTB
OR 0x19, 0x18
OUT PORTB, 0x19
Das auf drei Operationen zu optimieren ist leicht:
IN 0x19, PORTB
ORI 0x19, 0x4
OUT PORTB, 0x19
Auf anderen Adressen kann es auch so aussehen:
LDS 0x19, PORTB
ORI 0x19, 0x4
STS PORTB, 0x19
(Register hexadezimal).
In allen drei Teilstücken kann jeweils zwischen den Instruktionen eine ISR ausgelöst und angesprungen werden.
Kann keine entsprechende Instruktion, die das in einem Rutsch ununterbrechbar erledigt, eingesetzt werden, muss die Operation atomar durchgeführt werden; man schaltet kurz vorher die Ausführung der ISR aus und danach wieder ein - inzwischen eingetretene Interrupt-Ereignisse werden danach dennoch verarbeitet.
_________________
[ Diese Nachricht wurde geändert von: DonComi am 10 Dez 2008 20:26 ]
|
BID = 571259
selfman Schreibmaschine
Beiträge: 1681 Wohnort: Seekirchen a. W.
|
Ganz ruhig brauner! Warum solche Aufregung!
Auch wenn es Unterschiede in der Architektur gibt, so läuft trotzdem fast jeder Interruptaurfruf so ab, wie ich ihn oben beschrieben habe.
Deine Antwort bezieht sich eher darauf, ob dieser einzelene genannte Hochsprachenbefehl in einem Assemblerbefehl umgesetzt werden kann. Das ist dann natürlich abhängig von der Architektur möglich oder nicht.
Aber prinzipell muß ich auch wieder auch meine Antwort verweisen: Wenn die Interruptroutine alles so hinterlässt wie sie es vorgefunden hat, dann hat sie, außgenommen des Zeitverlustes, für die unterbrochene Routine nie stattgefunden. Wenn allerdings es genau auf das Timing ankommt, dann kann und muß den Interrupt sperren.
Aber doch nicht bei solchen unkritischen Pipifaxroutinen. Da könnte man ja jede Verarbeitungskette als solche betrachten. Und wenn man aus der Assemblersprache etwas rausholen will, dann können diese Ketten ganz schön lang werden, wo kein, aber auch gar kein Register, Akku, Statusflag, Datapointer, oder was auch immer verändert werden darf! In jedem diesen Falle den Interrupt zu sperren hat keinen Sinn. Da ist die genannte Taktik der nie dagewesenen Routine schone einfacher.
Schöne Grüße Selfman
_________________
Traue keinem Ding, das du nicht selber vermurkst hast.
|
BID = 571265
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Zitat :
| Ganz ruhig brauner! Warum solche Aufregung! |
Hab ich doch gesagt, es tut weh.
Wenn ich in einen VW-Laden gehe um mir ein Auto zu kaufen und mich der nette Verkäufer fragt, was ich denn gerne hätte, und ich antwortete "einen VW!", dann würde er auch so ähnlich reagieren...
Zum Thema:
Du mit deinen niedagewesenen Routinen hast ja schon Recht, aber wenn es so einfach wäre, bräuchte man keine atomaren Routinen; diese braucht man jedoch, auch was die Ein- und Ausgabe angeht, immer wieder. Z.B. ein Beispiel aus den AVRs: es gibt Datenregister mit 16 Bit Länge, die atomar beschrieben werden müssen. Intern ist das nichts anderes als ein IO-Zugriff, dem ein nächster folgt (folgen muss). Passiert exakt zwischen diesen beiden Schreibzugriffen ein IRQ und die ISR wird gestartet, dann wurde dieser Prozess nicht korrekt abgeschlossen.
Achso, hierzu:
Zitat :
| Also es wird erst geladen:
LDI R1, x
Dann tritt die ISR auf...
Die ISR verdrängt erstmal den MOV Befehl für eine Zeitdauer und in dieser Zeit wird das Register R1 überschrieben.
Nachdem die ISR fertig ist, wird der MOV Befehl ausgeführt.
Damit wurde der LDI Befehl nicht erkannt! Oder? |
Doch, der LDI Befehl wurde ja bereits ausgeführt. Betrachten wir das ganze mal langsam:
LDI r1, x
Angenommen, es würde mit r1 gehen ( ) dann würde x nach R1 geladen werden. Soweit klar.
Nun tritt ein IRQ und die darauffolgende ISR auf:
Der Instruktionszeiger (oder Programmzähler oder PC) wird hardwaremäßig auf den Stapel geworfen, die Programmadresse der ISR geladen und dort hingesprungen.
R1 ist weiterhin noch x.
Sollte die ISR R1 nicht verändern, muss R1 nicht gesichert werden. Jede ISR bzw. der Programmierer, muss dafür sorgen, dass benutze Resourcen gesichert und wieder, in der korrekten Reihenfolge, wiederhergestellt werden:
R1 wird benutzt, daher schmeißen wir den Inhalt auf den Stapel:
push r1.
Da eventuelle Werte im Flaggenregister (Statusregister) den Programmfluss im unterbrochenen Teil benutzen könnten, wird auch es gesichert:
push r0
in r0, SREG.
(push r0)
So oder so ähnlich kann das aussehen.
Die Resourcen sind nutzbar, alte Werte sicher.
Nach Beendigung der ISR muss nurnoch, chronologisch korrekt, der alte Zustand hergestellt werden:
(pop r0)
out SREG, r0
pop r0
pop r1
reti
Das Reti holt sich dann die Rücksprungadresse vom Stack und schreibt sie in den PC zurück, und springt danach dorthin.
Wird die Reihenfolge penibel eingehalten, dann steht nach der ISR in R1 auf jeden Fall wieder x und MOV wird so ausgeführt, wie es beabsichtigt ist.
Ich weiß, hat Selfman alles so beschrieben, ich habs nochmal mit Mnemonics untermalt .
_________________
[ Diese Nachricht wurde geändert von: DonComi am 10 Dez 2008 21:15 ]
|
BID = 571672
selfman Schreibmaschine
Beiträge: 1681 Wohnort: Seekirchen a. W.
|
Haste gut gemacht!
Das was Du nennst ist natürlich ein guter Grund den Interrupt kurz einmal zu sperren. Dazu ist es ja auch gedacht. Allerdings sind das dann schon sehr spezielle Register, die deratig mit Sie angesprochen werden müssen.
Schöne Grüße Selfman
_________________
Traue keinem Ding, das du nicht selber vermurkst hast.
|
BID = 571684
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Klar, und das sollte man auch, wenn es nicht zwingend notwendig ist, sparsam einsetzen, da
* auf ein Interrupt dann nicht mehr sofort reagiert wird, sondern erst auf das Mnemonic sei gewartet werden muss. Oft ist es aber wichtig, sofort auf ein IRQ zu reagieren.
* eine Instruktion sowohl zum An- als auch zum Abschalten je zwei Bytes des Programmspeichers belegt, was nicht sein muss.
* es nicht nötig ist, nicht Echtzeitanwendungen atomar abzuspielen (Ob das Display nun den Wert zwei Mikrosekunden später anzeigt ist egal, das merkt man nicht.)
_________________
|
BID = 571693
perl Ehrenmitglied
Beiträge: 11110,1 Wohnort: Rheinbach
|
Zitat :
| es nicht nötig ist, nicht Echtzeitanwendungen atomar abzuspielen (Ob das Display nun den Wert zwei Mikrosekunden später anzeigt ist egal, |
Ein verbreiteter Irrglaube.
Kennzeichnend für eine Echtzeitanwendung ist nicht, wie schnell auf ein Ereignis reagiert wird, sondern dass die Reaktion innerhalb einer garantierten Zeitspanne stattfindet.
Wenn die Anwendungssoftware, und sei sie noch so schnell, den Interrupt abschalten darf, und sich danach vielleicht in einer Endlosschleife aufhängt, handelt es sich eben nicht mehr um eine Echtzeitanwendung.
_________________
Haftungsausschluß:
Bei obigem Beitrag handelt es sich um meine private Meinung.
Rechtsansprüche dürfen aus deren Anwendung nicht abgeleitet werden.
Besonders VDE0100; VDE0550/0551; VDE0700; VDE0711; VDE0860 beachten !
|
BID = 571769
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Ja, genau, ich habe mich möglicherweise etwas unpräzise ausgedrückt.
Sozusagen instantane Reaktionen sind bekanntlich nicht möglich, und es braucht auch so seine Zeit, bis die ISR überhaupt abgespielt wird, nur darf es nicht passieren, dass ein Teil, der in "Echtzeit" stattfinden muss, zulange warten muss, um eingehende Daten zu verarbeiten, bis irgendein Programmteil mit niedriger Priorität mal wieder die ISR-Ausführung erlaubt... (und dies in gewissen Archiktekturen auch garnicht machen kann...)
Daher sollte man diese nicht atomar ausführen.
Angenommen, ein kleiner Rechenknecht muss alle paar µs einen Analogwert aufnehmen, ihn verarbeiten und wieder analog ausgeben (ok, ist ne Aufgabe für einen DSP, aber lassen wir das ). Dabei hat sinnigerweise diese Aufgabe hohe Priorität, da nur eine ganz bestimmte Latenz zwischen Ein- und Ausgabe erlaubt ist (und das ist auch die Zeit, innerhalb derer, plus Ausführungsgeschwindigkeit, auf die Daten reagiert werden muss, um "echtzeit"-fähig zu bleiben).
Angenommen, weiters hinge an diesem Prozessor ein Display, welches irgendwelche Belanglosigkeiten anzeigen würde. Sämtliche Routinen, die Daten auf dem Display ausgeben sind völlig zeitunkritisch, zumindest in einem bestimmten Rahmen, können also ganz normal unterbrochen werden, und würden danach korrekt weiterlaufen, evtl. bis weitere Interrupts eintreten.
So, nun ist es aber spät..
_________________
|
|
Zum Ersatzteileshop
Bezeichnungen von Produkten, Abbildungen und Logos , die in diesem Forum oder im Shop verwendet werden, sind Eigentum des entsprechenden Herstellers oder Besitzers. Diese dienen lediglich zur Identifikation!
Impressum
Datenschutz
Copyright © Baldur Brock Fernsehtechnik und Versand Ersatzteile in Heilbronn Deutschland
gerechnet auf die letzten 30 Tage haben wir 20 Beiträge im Durchschnitt pro Tag heute wurden bisher 0 Beiträge verfasst © x sparkkelsputz Besucher : 182393443 Heute : 639 Gestern : 7548 Online : 636 25.11.2024 5:55 2 Besucher in den letzten 60 Sekunden alle 30.00 Sekunden ein neuer Besucher ---- logout ----viewtopic ---- logout ----
|
xcvb
ycvb
0.0672359466553
|