Hallo,
ich habe da mal eine kleine Frage bezüglich Interrupt-Handler.
Warum können einem Interrupt grundsätzlich keine Parameter übergeben
werden, bzw. warum hat er keine Rückgabewerte?
Also es handelt sich hierbei um eine Frage aus einer Klausur.
Ich hätte jetzt einfach gedacht, dass das Problem ist, dass der
Interrupt irgendwann auslöst und mein main-Programm dadurch unterbrochen
wird.
Da er an einer X-beliebigen Stelle unterbrochen wird und ich ihn nicht
gezielt also z.B. genau in der Codezeile 77 im Programmcode aufrufen
kann, also nicht irgendwelchen Variablen angeben kann, die dessen
Rückgabewerte speichern sollen, hat es auch keinen Sinn
Rückgabeparameter zu verwenden.
Außerdem habe ich oft etwas von einem Stack und Variablen sollten
volatile sein gelesen und deshalb kann man keine Parameter angeben.
Über Hilfe in einfachen und verständlichen Worten wäre ich sehr erfreut!
;)
Schonmal Danke an die Leute die sich dafür die Zeit nehmen!
Funktionsparameter werden auf dem Stack uebergeben. Da der Interrupt
irgendwann kommt, wie sollten da Parameter auf dem Stack uebergeben
werden koennen ? Wenn ein Interrupt vorbei ist, ist alles wie vorher,
daher kann auch kein Interrupt resultat auf dem Stack sein.
Variablen, die ein Interrupt benoetigt, muessen daher global sein.
Noch nicht Rentner schrieb:> Funktionsparameter werden auf dem Stack uebergeben. Da der Interrupt> irgendwann kommt, wie sollten da Parameter auf dem Stack uebergeben> werden koennen ?
die Begründung ist falsch. Das Parameter auf dem Stack übergeben werden
ist nirgends festgelegt und je nach Plattform auch nicht (immer) der
Fall.
Also erstmal würde nichts dagegen sprechen, daß Parameter an ISRs
übergeben würden. Voraussetzung dafür ist allerdings, daß
- die Hardware das könnte (da der ISR nicht unter Entwicklerkontrolle
aufgerufen wird, muß es der Controller machen) und
- die Vorgaben des ABI eingehalten würden (also der/die Paramter an den
lt. ABI erwarteten Stellen werden, richtiger Punkt von Peter II).
Wie "NochNichtRentner" richtig schreibt, ist das Problem hier des
Kontextes; da der ISR nicht kontrolliert aufgerufen wird, muß der
Prozessorzustand nach Beendigung des ISRs exakt dem vor Eintritt des
ISRs entsprechen. Für Parameter wäre das sogar denkbar (der
Prozessorkern müßte je nach ABI nur vor dem Setzen der Parameter die
entsprechenden Register pushen und danach wieder poppen oder einen
größeren Exception stack frame nutzen), aber der Rückgabewert wäre ein
echtes Problem, da der einen Anderen Prozessorzustand impliziert.
Parametrierte ISRs würden in gewissen Szenarien sogar Sinn machen, z.B.
könnte ein Prozessorkern verschiedene Instanzen von ISRs gleichartiger
Funktionalität (z.B. USARTs) über einen gemeinsamen ISR abbilden und
Instanzinformationen an den gemeinsamen ISR übergeben (das wird
normalerweise über Software gemacht, d.h. jeder ISR hat einen eigenen
Eintrag in der IVT, aber jeder Eintrag pusht seine
Identifikationsparameter und ruft gemeinsamen Code auf). Allerdings
überwiegen m.M. nach die Nachteile so einer möglichen Architektur
(größerer Stackbedarf oder ISR Umlaufzeiten, erzwungene ABI Konformität,
Fallunterscheidungen je nach benötigter Parameteranzahl etc) die
Vorteile (kleinere IVTs, Softwareunterstützung in HW).
Mußt Du die Klausur vor oder nach diesem thread schreiben? ;-)
Ok. Anderer Ansatz.
Woher sollen die Parameter an die Interrupt Procedur denn ueberhaupt
kommen ? Funktionsparameter kommen aus einem Kontext heraus. Welchen
Kontext hat eine Interrupt Prozedur ?
Genau. Der Kontext ist global. Daher sind auch Interrupt Variablen dort.
Noch ein kleines Detail zum OP: Ein ISR unterbricht nicht
notwendigerweise die main() Funktion, sondern irgendwas im Thread Mode,
d.h. main() nur wo kein RTOS im Betrieb ist, sonst in der Regel eine vom
OS gemanagte task - oder einen anderen, bereits laufenden ISR. Mag wie
Haarspalterei klingen, aber in der Praxis werden diese Unterschiede sehr
schnell sehr wichtig... ;-)
Es gibt sogar Interrupts mit Parametern -- aber das sind dann sogenannte
"Softwareinterrupts", die werden zum Aufrufen von
Betriebssystemfunktionen o.ä. verwendet.
Der "gute alte" IBM-PC nutzt dieses Konzept zur Kommunikation mit dem
BIOS und zum Aufruf von Funktionen von DOS. Die Parameter werden vor
Aufruf des Interrupthandlers in Prozessorregistern untergebracht und
etwaige Resultate nach Ende des Interrupthandlers wiederum in
Prozessorregistern zurückgegeben.
Das setzt naturgemäß einen Prozessor voraus, der Softwareinterrupts
kennt; die 8-Bit-AVRs kennen so etwas nicht.
Hardwareinterrupts hingegen, die völlig asynchron zum Programmablauf
auftreten, können keine vom Programm vorgegebenen Parameter übergeben
bekommen. Warum das nicht geht, wurde ja schon ausführlich beschrieben.
Ethernut registiert Interrupts mit
extern int NutRegisterIrqHandler(IRQ_HANDLER * irh, void (*handler)
(void *), void *arg);
Die Parameter werden also vorher gespeichert und wenn der Interrupt dann
erfolgt, wird der Interruptnutzcode mit Parametern angesprungen.
Rufus Τ. F. schrieb:> Der "gute alte" IBM-PC nutzt dieses Konzept zur Kommunikation mit dem> BIOS und zum Aufruf von Funktionen von DOS.
Ja, INT 0x13.
Aber abgesehen davon, dass es ein Software-Interrupt ist, funktioniert
das nur mit DOS, in WINDOWS wird der abgefangen und umgeroutet.
ARMAnfänger schrieb:> Warum können einem Interrupt grundsätzlich keine Parameter übergeben> werden, bzw. warum hat er keine Rückgabewerte?
Also, das stimmt schon mal nicht.
Rückgabewerte sind kein Problem, nur - wie sollen diese ausgewertet
werden ?
Und Parameter könnte nur die CPU übergeben, nur - wie soll die CPU
wissen, welche Parameter für Zeile 77 und welche Parameter für Zeile
1234 übergeben werden sollen ?
Rufus Τ. F. schrieb:> Hardwareinterrupts hingegen, die völlig asynchron zum Programmablauf> auftreten, können keine vom Programm vorgegebenen Parameter übergeben> bekommen.
Naja, ganz so ist es nicht. Erstens gibt es Hardwareinterrupts, die
durchaus synchron zum Programmablauf sind (oder zumindest sein können,
wenn man das so will, siehe z.B. Timerinterrupts beim AVR) und zweitens
gibt es bei praktisch jeder Architektur die Möglichkeit, die
Interruptausführung mittels Interruptsperren zu synchronisieren. In
beiden Szenarios sind die Interrupts aus Sicht des zu unterbrechenden
Codes nicht mehr unvorhersehbar, sondern deterministisch.
Dementsprechend wäre auch in beiden Szenarien eine Parameterübergabe
realisierbar.
Nur einen Sinn ergibt so ein Konstrukt wohl selten bis garnicht. Da
hätte man ja mit mehr oder weniger viel zusätzlichem Aufwand letztlich
nur die Funktionalität einer normalen Funktion erreicht und das ganze
Konzept von Interrupts ad absurdum geführt. Ich kann mir keinen
Anwendungsfall vorstellen, wo das nützlich sein könnte...
c-hater schrieb:>> Naja, ganz so ist es nicht. Erstens gibt es Hardwareinterrupts, die> durchaus synchron zum Programmablauf sind (oder zumindest sein können,> wenn man das so will, siehe z.B. Timerinterrupts beim AVR) und zweitens> gibt es bei praktisch jeder Architektur die Möglichkeit, die> Interruptausführung mittels Interruptsperren zu synchronisieren. In> beiden Szenarios sind die Interrupts aus Sicht des zu unterbrechenden> Codes nicht mehr unvorhersehbar, sondern deterministisch.> Dementsprechend wäre auch in beiden Szenarien eine Parameterübergabe> realisierbar.>
? Stimmt so nicht, wenn ich die obige Aussage richtig interpretiere - es
ist im zweiteren Fall deterministisch, wann die Interrupts nicht
auftreten können, aber solange die interrupts nicht gesperrt sind,
können sie indeterministisch auftreten. Außer man würde sich die Mühe
machen, Interrupts so zu sperren, daß sie nur an genau einer Stelle
offen sind, aber das würde nun überhaupt keinen Sinn machen...
Okay vielen Dank für die ausführlichen Antworten!
Also ich muss die Klausur noch schreiben und die Frage ist mal in einer
Klausur gefallen, wurde aber nicht richtig beantwortet.
Ich hätte vielleicht präziser sein sollen:
Warum kann ein Interrupthandler, der in C wie eine Funktion geschrieben
wird - keine Parameter haben oder Rückgabewerte zurückgeben?
Also ich nehme jetzt kurz und knapp mit, dass:
- es mit "speziellen" Softwareinterrupts durchaus möglich wäre
- bei den "normalen/einfachen" ISR jedoch nicht, da der Kontext eine
wichtige Rolle spielt.
Die CPU kann nicht zuordnen, was mitübergeben werden soll und wer was
mit dem Ergebnis anfangen kann.
Vielen Dank für die Antworten, ich bewundere es immer wieder, dass es
Leute wie euch gibt, die sich die Zeit nehmen um anderen bei solchen
Dingen zu helfen! Respekt und Danke! ;)
ARMAnfänger schrieb:> es mit "speziellen" Softwareinterrupts durchaus möglich wäre
Softwareinterrupts sind definitiv keine Interrupts, sondern normale
Prozeduraufrufe mit einer festen Aufrufaddresse. Sie unterbrechen den
Programmablauf auch nicht, sondern werden genau da ausgeführt wo der
Programmierer sie aufruft. Wer immer sich die Bezeichnung ausgedacht hat
(Intel? Microsoft?) hatte mehr Verschleierung im Sinn als logische
Klarheit.
Georg
Georg schrieb:> Wer immer sich die Bezeichnung ausgedacht hat
Spätestens Intel, mit Einführung des INT-Befehls im Befehlssatz des
8086. Eine Vorform davon war der RST-Befehl des 8080.
ARMAnfänger schrieb:> Warum kann ein Interrupthandler, der in C wie eine Funktion geschrieben> wird - keine Parameter haben oder Rückgabewerte zurückgeben?
Es hängt ganz grundsätzlich NICHT von irgend einer Programmiersprache
ab.
In einem µC oder auf dem PC oder eben sonstwo, wo ein Prozessor werkelt,
hat man Maschinencode und der wird abgearbeitet und irgendwann zumeist
eben nicht präzise vorhersagbar durch einen Interrupt unterbrochen.
Deswegen heißt der auch so: Interrupt.
Dabei ist es sonnenklar, daß der Zustand des Systems (Register, Flags
und so weiter) bei einem Interrupt, der von der Hardware ausgelöst wird,
ebenfalls nicht präzise vorhersagbar ist und deshalb alles, was im
Interrupt-Handler benutzt wird, eben zuvor in irgend einer Weise
gerettet und hinterher restauriert werden muß. Da gibt es ganz
grundsätzlich KEINEN Platz für irgendwelche Datenübergaben. Wenn man mit
einem Interrupt-Handler kommunizieren will, dann eben NUR per globalen
Variablen und auch nur in einer Art, daß beide Seiten nach irgend einem
Schema ihre Kommunikation miteinander synchronisieren. Sonst geht das
schief und produziert zufällige Fehler.
Eine Ausnahme machen eben die erwähnten Soft-Interrupts, bei ARM werden
die SVC's genannt (Supervisor Calls). Das sind aber spezielle
Maschinenbefehle (die der GCC nicht kann). Sowas ist gut für das
Aufrufen von Funktionalitäten aus Betriebssystemen und so, also immer
dann, wenn man eine geordnete Schnittstelle zwischen mehreren separat
übersetzten Programmteilen benötigt, denn die tatsächliche Adresse des
SVC-Handlers und seiner nachgeordneten Funktionen braucht der
aufrufenden Anwendung garnicht bekannt zu sein. Hatte ich vor Jahren bei
der Lernbetty schon mal vorgeturnt.
W.S.
Marc V. schrieb:> ARMAnfänger schrieb:>> Warum können einem Interrupt grundsätzlich keine Parameter übergeben>> werden, bzw. warum hat er keine Rückgabewerte?>> Also, das stimmt schon mal nicht.> Rückgabewerte sind kein Problem, nur - wie sollen diese ausgewertet> werden ?> Und Parameter könnte nur die CPU übergeben, nur - wie soll die CPU> wissen, welche Parameter für Zeile 77 und welche Parameter für Zeile> 1234 übergeben werden sollen ?
Streng genommen haben Interrupts teilweise schon gewisse "Parameter",
nur nicht in Form von C-Funktionsparametern, sondern zumeist in
irgendwelchen I/O-Registern - beispielsweise bei einer UART-Receive-ISR
das empfangene Byte.
ARMAnfänger schrieb:> Warum können einem Interrupt grundsätzlich keine Parameter übergeben> werden, bzw. warum hat er keine Rückgabewerte?
Leider ist es etwas aus der Mode gekommen (Programm)Flussdiagramme zu
zeichnen.
Leider...
Denn, wenn man das mal tun würde, dann würde sich fix zeigen, dass für
die Anwendung und für die (Hardware)ISR, 2 völlig unabhängige Abläufe
gezeichnet werden wollen. Da diese keinen Kontakt haben, ist eine
direkte Parameterübergabe unmöglich.
Zum Glück, durfte ich mich Damals (TM) noch mit Datenflussdiagrammen
rumschlagen. Ein solches würde zeigen, dass sich durch einfügen
irgendeiner "shared Memory" Variante, sehr wohl ein Datenfluss
realisieren lässt.
z.B. der Ringbuffer der Seriellen ist ein typisches Beispiel dafür.
Rolf M. schrieb:> Streng genommen haben Interrupts teilweise schon gewisse "Parameter",> nur nicht in Form von C-Funktionsparametern, sondern zumeist in> irgendwelchen I/O-Registern - beispielsweise bei einer UART-Receive-ISR> das empfangene Byte.
Streng genommen sind das keine Parameter, sondern der Zustand der
CPU und deren Register. Eine UART-ISR benutzt normalerweise nicht die
Timer-Register und eine Timer-ISR interessiert UDR nicht, obwohl sich
bei beiden der Zustand wahrscheinlich geändert hat.