Interrupt aktivieren, aber kein ISR

Ich würde gerne wissen, was passiert, wenn ein Interrupt aktiviert ist (z. B. Arbitration Lost Interrupt im CAN-Modul des LPC1778 von NXP), aber für den Interrupt wurde kein ISR definiert.

Wenn ein solcher Interrupt auftritt, weiß ich, dass das entsprechende Interrupt-Flag gesetzt wird, aber da ich keine ISR definiert habe, wird keine Interrupt-Vektor-Offset-Adresse für die Steuerungsübertragung für einen solchen Interrupt gespeichert, und daher wird die Steuerung zurückgegeben zur Hauptroutine, und ich kann das Interrupt-Flag zurücksetzen, indem ich es in der Hauptroutine abfrage (das denke ich). Wird es eine Latenz geben, wenn die CPU herausfindet, dass es keine ISR gibt, zu der sie springen kann?

Alle Lösungen, was passieren könnte, können mir wirklich helfen.

Vielen Dank.

Aktualisieren:

Ich habe CAN Interrupt auf meinem uC aktiviert, aber keine ISR definiert. Als ich einen internen Loopback-Test durchführte, trat der Code in eine Endlosschleife ein. Hier ist der Disassemblierungscode der Endlosschleife, die auf LPC1778 ausgeführt wird:

B       .
ENDP

Wenn Sie also Interrupts verwenden, verwenden Sie die ISR.

Sie müssen den Interrupt nicht aktivieren, um Flags in Ihrer Hauptfunktion abzufragen. Wenn die Bedingung eintritt, die das Flag setzt, wird dieses Flag gesetzt, unabhängig davon, ob Sie den zugehörigen Interrupt aktiviert haben oder nicht.
Sagen Sie, dass ein Interrupt-Flag für Bus-Arbitration verloren gesetzt wird, auch wenn ich "Interrupt on Bus Arbitration lost" nicht aktiviere (obwohl es kein Statusregister gibt, das die verlorene Bus-Arbitration anzeigen kann, außer dem Interrupt-Statusregister)?
Ja. In jeder MCU, mit der ich gearbeitet habe, werden die Interrupt-Flags immer dann gesetzt, wenn die Bedingung eintritt, die sie setzen sollte. Das Aktivieren des Interrupts bewirkt, dass die MCU zum Handler vektorisiert, wenn das zugehörige Flag gesetzt ist, und das Deaktivieren des Interrupts bewirkt, dass sie das Flag ignoriert und nicht zum Handler vektorisiert, obwohl das Flag gesetzt ist . Das Deaktivieren/Aktivieren des Interrupts wirkt sich nur auf das Verhalten des Jump-to-Interrupt-Handlers aus, nicht auf das Verhalten des Flag-Setzens.
Wow. Das wusste ich nicht. Danke vielmals. Daher muss jeder Treiber regelmäßig auch nach den Interrupt-Statusregistern suchen und sie zurücksetzen, obwohl Interrupts nicht aktiviert wurden :)
@AkshayImmanuelD nur wenn es darauf ankommt. Wenn der Interrupt immer deaktiviert ist und sich sonst nichts um das Flag kümmert, ist es unerheblich, ob es gesetzt oder gelöscht ist.
@hobbs- Ja das stimmt. :)
Für Ihre Anwendung scheint es möglich zu sein, ohne die Interrupts zu aktivieren. Dies ist die sicherere Methode, anstatt einen Interrupt zu aktivieren und die ISR nicht zu initialisieren. Das Problem dabei ist, dass es für Sie "definiert" wird, wenn Sie es nicht tun, was zu unvorhersehbarem uC-Verhalten führen kann!

Antworten (2)

Wenn kein ISR definiert ist, ist die Stelle für den Sprungbefehl im Interrupt-Vektor entweder null, es kann ein Sprung zu einer Ausnahmeroutine sein, es kann zum Anfang des Programms springen oder es kann ein "return from Interrupt" (z. B. RTI) Befehl.

Hier ist eine Zerlegung einer Interrupt-Tabelle für einen ATMega 16-Prozessor, die drei unbenutzte Interrupts zeigt, die zu einer Routine geleitet werden, die solche Fälle behandelt (sie kann einfach in eine Endlosschleife gehen), und einen legitimen Vektor.

  28:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  2c:   0c 94 5c 00     jmp 0xb8    ; 0xb8 <__vector_11>   // <-- ISR
  30:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  34:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>

Welche der oben beschriebenen Methoden zur Behandlung einer fehlenden ISR ist, hängt sowohl von der Architektur des Mikrocontrollers als auch des Compilers ab. Im Fall einer RTI- oder gleichwertigen Anweisung wird sofort zur Anwendung zurückgekehrt. Wenn der Interrupt jedoch pegelgesteuert und nicht flankengesteuert ist, wird dies wahrscheinlich dazu führen, dass der Interrupt erneut ausgelöst wird, sodass Sie in einer Endlosschleife landen.

Ich denke, es kann von der Architektur des Chips abhängen, ob interne Interrupts (z. B. ein von einem UART empfangenes Zeichen) als pegelgesteuert oder flankengesteuert betrachtet werden. Externe Interrupts können normalerweise als das eine oder das andere konfiguriert werden.

Es gibt auch einen anderen Fall, manchmal werden mehrere Interrupts zusammen gruppiert und verwenden denselben Vektor. Dies galt insbesondere für ältere Prozessoren, die möglicherweise nur ein paar Interrupts hatten. In diesem Fall wurde die Unterbrechungsursache durch Abfragen des Status der Unterbrechungsregister ermittelt, was in etwa dem entspricht, was Sie vorschlagen.

Aber es ist auf jeden Fall schlechte Praxis, Interrupts in einem System zu haben und keine ISR zu definieren. Tu es nicht.

...., oder es kann undefiniert sein.
@WoutervanOoijen das meinte ich damit, dass der Interrupt-Vektor null ist.
Die Statusregister können einige Fehler wie den oben erwähnten nicht anzeigen. Aber solche Fehler haben einen Interrupt. Daher dachte ich daran, den Interrupt nur zu aktivieren, um den Fehler zu identifizieren und keine ISR zu verwenden. Bei der Simulation des LPC1778 mit Keil habe ich eine Ausnahme erhalten, also denke ich, dass der uC den RTI verwenden muss, wie Sie erwähnt haben
Beachten Sie Folgendes: Wenn Sie einen Interrupt aktivieren, Ihr Handler das Flag jedoch nicht löscht (oder es keinen Handler gibt und das Standardverhalten eine einfache Rückkehr ist), werden Sie höchstwahrscheinlich feststellen, dass Ihre MCU für immer endet in einer Interrupt-Schleife stecken.
@brhans Guter Punkt, ich werde meine Antwort aktualisieren. Dies würde nur bei Level-getriggerten Interrupts passieren, nicht bei Flanken-Triggern. Ich denke, es kann von der Architektur des Chips abhängen, ob interne Interrupts (z. B. ein von einem UART empfangenes Zeichen) als pegelgesteuert oder flankengesteuert betrachtet werden. Externe Interrupts können normalerweise als das eine oder das andere konfiguriert werden. Ich werde meine Antwort aktualisieren.
Die PIO-Interrupts auf dem ATSAM3X8E können flankengetriggert werden, aber die einmal gesetzte Interrupt-Bedingung wird nicht gelöscht, bis Sie das ISR (Interrupt-Statusregister) im Interrupt-Handler lesen - was zu der erwähnten Schleife @brhans führt.
@brhans- Ich habe nicht verstanden, wie es in einer Interrupt-Schleife sein wird? Liegt es daran, dass das Interrupt-Flag immer noch gesetzt ist (ich habe es nach dem 1. Interrupt nicht gelöscht), so dass der uC denkt, dass ein neuer Interrupt aufgetreten ist (nach dem RTI-Befehl) und wieder in die ISR eintritt und diese weiterschleift?

Es hängt von Ihrer MCU, Ihrem Compiler und dem Rest des Codes ab.

Meiner Erfahrung nach:

  1. AVR - Wenn Sie keine ISR angeben, ist der Interrupt-Vektor im Flash standardmäßig 0x0000, was bedeutet, dass Ihre Anwendung bei jedem Auftreten dieses Interrupts in den Reset springt.

    Wenn Sie den Interrupt wirklich benötigen, aber den Handler nicht benötigen (z. B. ADC-Low-Noise-Power-Down-Modus verwenden und den Interrupt nur zum Aufwecken der MCU verwenden), sollten Sie das EMPTY_INTERRUPT- Makro verwenden

  2. NXP Kinetis (ARM) - Alle Vektoren zeigen standardmäßig auf einen Standardhandler mit einem Haltepunkt. Die CPU stoppt einfach und teilt dies Ihrem Debugger mit.