Forum: Mikrocontroller und Digitale Elektronik Wie funktioniert der Interrupt- bzw. Eventaufruf?


von Moe E. (moe_espunkt)



Lesenswert?

Hallo Zusammen,

im Rahmen einer Projektarbeit bin ich gerade dabei den Industriell 
Ethernet Controller "R-IN32M3-CL" der Firma Renesas in Betrieb zunehmen 
und zu verstehen. Für die Inbetriebnahme stellt Renesas einige 
Samplecodes zur Verfügung. Mit den Samplecodes funktioniert der 
Controller problemlos in meinem Netzwerk; ich kann Daten zur SPS(Master) 
senden und von dieser empfangen.

Zur Erklärung des Samplecodes hat Renesas nun ein "Developing Flowchart" 
im Manual (Seite 54)zur Verfügung gestellt. Allerdings gibt es einen 
Funktionsaufruf im Flowchart den ich nicht ganz verstehe. Der Abschnitt 
"Event processing" ist mir ein absolutes Rätsel. Weder der Quellcode 
noch das Flowchart für das "Event processing" (Seite 60) gibt mir 
aufschluss über die Funktionsweise. Besonders die Funktionen 
"gerR_IN32_GetEvent" und "gerR_IN32_Main" bereiten mit Kopfschmerzen ...

Die Funktion "gerR_IN32_GetEvent", greift auf auf die Struktur 
"R_IN32_EVTPRM_INTERRUPT_T" zu (Seite 111), aber was dann passiert, kann 
ich mir nicht erklären. Wie genau arbeitet die Funktion mit der 
Struktur? Überprüft sie ob ein Interrupt ausgelöst wurde?

Ich habe das Manual beigefügt in dem die Funktionen erklärt sind. 
Vielleicht versteht jemand mehr als ich und könnte es mir erklären? Des 
Weiteren habe ich das "Event processing" aus dem Samplecode im Anhang 
hinzugefügt.

Bitte entschuldigt, wenn ich das Problem nur schlecht schildern konnte, 
falls irgendwas unklar ist, erkläre ich es sehr gerne nochmal. Ich 
bedanke mich jedoch recht herzlich für jede Hilfe !

Schöne Grüße
Moe Espunkt

von Moe E. (moe_espunkt)


Lesenswert?

Ich habe schon geahnt, dass ich es viel zu kompliziert und umständlich 
erklärt habe. Ich versuch es mal anders:

Ich habe folgenden Funktionsaufruf:
1
  R_IN32_EVTPRM_INTERRUPT_T  stEvent;
2
        
3
  /* R_IN32M3 get event */
4
  (VOID)gerR_IN32_GetEvent( &stEvent );//This function detects R-IN32M3 events

Und der Datentyp "R_IN32_EVTPRM_INTERRUPT_T" ist als folgende Stuktur 
definiert:
1
/* Interrupt cause  */
2
typedef struct R_IN32_EVTPRM_INTERRUPT_TAG {
3
  union {
4
    ULONG ulAll;
5
    struct {
6
      ULONG b1ZCommConnect:              1;  /**< b0: Connect communication */
7
      ULONG b1ZCommDisconnect:           1;  /**< b1: Disconnect communication */
8
      ULONG b1ZCommConnectToDisconnect:  1;  /**< b2: Connect communication¨ Disconnect communication */
9
      ULONG b1ZCommDisconnectToConnect:  1;  /**< b3: Disconnect communication   ¨ Connect communication  */
10
      ULONG b1ZChangeStNoNetNo:          1;  /**< b4: Change node number and network number */
11
      ULONG b1ZChangeActCommand:         1;  /**< b5: Change run command */
12
      ULONG b1ZPrmFrmRcv_OK:             1;  /**< b6: Parameter frame reception */
13
      ULONG b1ZReserve1:                 1;  /**< b7: Reserved */
14
      ULONG b1ZPrmChkFrmRcv_OK:          1;  /**< b8: ParamCheck frame reception (when parameters match) */
15
      ULONG b3ZReserve2:                 3;  /**< b9-11: Reserved */
16
      ULONG b1ZRecvNonCyclic:            1;  /**< b12: Transient reception */
17
      ULONG b1ZSendFinNonCyclic:         1;  /**< b13: Transient transmission complete */
18
      ULONG b7ZReserve3:                 7;  /**< b14-20: Reserved */
19
      ULONG b1ZMasterWatchTimeout:       1;  /**< b21: Master watchdog timer timeout occurred */
20
      ULONG bAZReserve4:                 10; /**< b22-31: Reserved */
21
                       } stBit;
22
            } uniFlag;
23
} R_IN32_EVTPRM_INTERRUPT_T;

Kann man anhand dieser zwei Quellcodeausschnitte sagen, wie hier der 
Interrupt funktionieren soll? Irgendwas muss ja die Ursache für den 
Interrupt sein?

Ich wäre für eure Hilfe sehr dankbar, zumal weil ich kurz vor der 
Verzweiflung bin...

Schöne Grüße und vielen Dank im Voraus.

von Karl H. (kbuchegg)


Lesenswert?

Ich denke, du klammerst dich momentan zusehr am Wort 'Interrupt' fest.

Wenn ein Interrupt auftritt, dann wird von der eigentlichen 
Behandlungsroutine eine entsprechender Eintrag in einer Warteschlange 
gemacht, um festzuhalten, dass dieses Ereignis aufgetreten ist.

gerR_IN32_GetEvent macht nichts anderes, als in dieser Warteschlange 
(auch Queue genannt) nachzusehen, ob es einen Eintrag gibt und wenn ja 
wird die übergebene R_IN32_EVTPRM_INTERRUPT_T Struktur entsprechend 
ausgefüllt. Könnte auch sein, dass die Queue selbst schone entsprechende 
Struktur Objekte enthält. Das ist aber nicht dein Bier, wie das 
systemintern gehandhabt wird.

>  Irgendwas muss ja die Ursache für den Interrupt sein?
Schau dir Flags in der Struktur an. Genau der jeweils damit verbundene 
Vorgang ist es, der von irgendeinem Handler behandelt wird und dazu 
führt, dass ein entsprechender Eintrag in der Event-Queue gemacht wird. 
Das Wort bzw. die Bezeichnung 'Interrupt' im Strukturnamen verführt dich 
jetzt dazu, viel zu kompliziert zu denken. Zu dem Zeitpunkt, an dem du 
mittels gerR_IN32_GetEvent zum ersten mal deine Finger an die 
Information kriegst, dass die Kommunikation unterbrochen wurde (das 
b1ZCommDisconnect Bit ist gesetzt), ist das entsprechende Ereignis bzw. 
der dadurch ausgelöste Interrupt schon lange Vergangenheit. Das Ereignis 
wurde (vom Handler) in der Queue zur geschätzten Kenntnissnahme 
registriert und das wars dann auch schon. Das "Ereignis" lungert dann 
solange in der Queue rum, bis du es mittels gerR_IN32_GetEvent abholst 
und irgendwelche Reaktionen darauf machst.

Das ganze ist von der grundsätzlichen Architektur keineswegs 
ungewöhnlich. Auch Windows arbeitet im Grunde so. Für jeden Prozess gibt 
es eine Queue und wenn irgendetwas auftritt (zb der Benutzer hat mit der 
Maus geklickt, eine Taste wurde gedrückt, ein Fenster wurde verschoben), 
werden entsprechende Nachrichten in diese Queue gestellt. Jeder Prozess 
hat als zentrales Elemente die Behandlung dieser Message Queue, in der 
eine Message von der Queue geholt wird (wenn es eine gibt) und 
entsprechend der Message dann behandelt wird. Auch wenn die diversen 
Frameworks das alles unter vielen Softwareschichten verborgen haben, im 
Grunde funktioniert das alles immer noch so wie anno dazumal zu Windows 
3.0 Zeiten, in der man als C-Programmierer direkt mit dieser 
Message-Pumpe in Berührung kam.

Bei Windows heisst das ganze dann eben 'Message', hier heisst es 'Event' 
und die Struktur würde besser R_IN32_EVTPRM_EVENT_T  heissen und nichts 
mit einem 'INTERRUPT' im Namen. Sieh dir die Verwendung an
1
R_IN32_EVTPRM_INTERRUPT_T  stEvent;

die Variable heißt 'Event' und nicht Interrupt. Die Funktion
1
  ... gerR_IN32_GetEvent
heißt Get Event. Event(!) und nicht Get Interrupt.
Schlussfolgerung: die Struktur hätte besser auch ein EVENT im Namen 
gehabt und kein INTERRUPT. Das solche Events durch Interrupts entstehen 
können, ist ja schön. Interessiert aber den Applikationsprogrammierer 
nicht. Der arbeitet mit Events und nicht mit Interrupts. Wenn die Dinge 
gefühlt falsch benannt sind, führt das des öfteren schon mal zu 
Verwirrung, weil die Dinge scheinbar nicht zusammenpassen.

von stefanus (Gast)


Lesenswert?

> im Grunde funktioniert das alles immer noch so wie anno dazumal zu
> Windows 3.0 Zeiten, in der man als C-Programmierer direkt mit dieser
> Message-Pumpe in Berührung kam.

Genau, und ich bin dankbar, dass ich diese Sachen noch von Grund auf 
lernen durfte.

Heutzutage müssen Programmierer ihren Job so schnell erlernen, dass die 
Zeit fehlt, sich mit solchen Grundlagen überhaupt zu beschäftigen. Das 
finde ich schade.

Aber genau deswegen begrüße ich den inzwischen leicht gewordenen Zugang 
zu Mikrocontrollern. Denn wenn man die programmiert, kommt man doch 
wieder zu den Grundlagen - nur über einen anderen Weg. Ich finde, dass 
jeder Programmierer sich irgendwann mal mit einer Mikrocontroller 
Anwendung OHNE SOFTWARE FRAMEWORK beschäftigen sollte.

von Moe E. (moe_espunkt)


Lesenswert?

Hallo Karl Heinz,

also erst einmal vielen vielen Dank für deine wirklich sehr hilfreiche 
Antwort!!

Also wenn ich das jetzt richtig verstanden habe, dann wird (irgednwo... 
ist auch erst einmal egal wo und wie)ein Interrupt ausgelöst. Dieser 
Interrupt hinterlässt einen Eintrag in der Queue und 
"gerR_IN32_GetEvent" macht nichts anderes als nach zu schauen ob in der 
Queue ein Eintrag (von einem Interrupt) hinterlassen wurden ist.
Wenn sich ein Eintrag in der Queue befindet, so wird das in die Strukur 
eingetragen (bzw. das Bit wird gesetzt).


Dann macht der Funktionsaufruf, welcher nach "gerR_IN32_GetEvent" kommt:
1
  /* main process of R_IN32M3 event detection */
2
  gerR_IN32_Main( &stEvent );

auch völlig sinn!! Denn diese Funktion überprüft nämlich, ob etwas in 
der Struktur eingetragen ist und wenn ja , dann führt diese Funktion die 
passende Reaktion auf diesen Eintrag aus. Dann ist natürlich fraglich, 
wo die Reaktion auf das jeweilige gesetzte Bit in der Strukur, definiert 
ist? Ist mein Gedankengang denn soweit richtig?

Karl Heinz schrieb:
> im
> Grunde funktioniert das alles immer noch so wie anno dazumal zu Windows
> 3.0 Zeiten, in der man als C-Programmierer direkt mit dieser
> Message-Pumpe in Berührung kam.

Ich behaupte mal dass ich 21 jähriger in einer Zeit lebe, in der man 
sich die elementaren Grundlagen selbst erarbeiten muss. Korrigiert mich 
bitte wenn ich falsch liege, aber der Trend geht immer mehr in Richtung 
"fertige Bausteine !! Fertige Funktionen!! Bloß nicht mit den Grundlagen 
beschäftigen!!"
Finde ich sehr schade ...

von Karl H. (kbuchegg)


Lesenswert?

Moe Espunkt schrieb:

> Dann macht der Funktionsaufruf, welcher nach "gerR_IN32_GetEvent" kommt:
>
>
1
  /* main process of R_IN32M3 event detection */
2
>   gerR_IN32_Main( &stEvent );
>
> auch völlig sinn!! Denn diese Funktion überprüft nämlich, ob etwas in
> der Struktur eingetragen ist und wenn ja , dann führt diese Funktion die
> passende Reaktion auf diesen Eintrag aus. Dann ist natürlich fraglich,
> wo die Reaktion auf das jeweilige gesetzte Bit in der Strukur, definiert
> ist? Ist mein Gedankengang denn soweit richtig?

Klingt logisch.

Das hier ist zb die zentrale Message-Pump in einem Windows-Programm
1
   while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
2
   {
3
     if(bRet == -1)
4
     {
5
         // Handle Error
6
     }
7
     else
8
     {
9
         TranslateMessage(&msg);
10
         DispatchMessage(&msg);
11
     }
12
   }

Im Grunde sind alle Zutaten völlig analog zu deinen vorhanden.
Einziger Unterschied: die Windows Message Pump läuft durch die 
while-Schleife solange, bis sie einen WM_QUIT erhält, der dem Programm 
signalisiert, sich zu beenden, wodurch es aus der while-Schleife 
rausfällt und damit auch aus main().

Bei dir ist das eben ein bischen anders organsiert. Aber die 
Bestandteile "Event (Message) holen", "Event (Message) bearbeiten" sind 
da wie dort genau gleich vorhanden. Da gibt es keinen prinzipiellen 
Unterschied.

von Moe E. (moe_espunkt)


Lesenswert?

Ahh!! Ich verstehe! Zwar ist die Struktur eine andere aber die 
prinzipielle Funktionsweise ist im Grunde die selbe !! Ich danke dir 
recht herzlich für deine Bemühungen Karl Heinz.

Aber mal Hand auf's Herz: Woher weiß man sowas, wenn man nicht gerade 
Software Engineering studiert?

von Karl H. (kbuchegg)


Lesenswert?

Moe Espunkt schrieb:

> ... aber die prinzipielle Funktionsweise ist im Grunde die selbe !! ...

Ganz wichtiges Prinzip:
Alle kochen schon seit Jahrzehnten auch nur mit immer dem gleichen 
Wasser :-)



> Aber mal Hand auf's Herz: Woher weiß man sowas, wenn man nicht gerade
> Software Engineering studiert?

:-)
'Man' ist damit aufgewachsen.

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
Noch kein Account? Hier anmelden.