Was ist der Unterschied zwischen FIQ- und IRQ-Interrupt-System?


Antworten:


63

Ein Merkmal moderner ARM-CPUs (und einiger anderer).

Aus dem Patent:

Ein Verfahren zum Durchführen eines schnellen Interrupts in einem digitalen Datenprozessor mit der Fähigkeit, mehr als einen Interrupt zu verarbeiten, wird bereitgestellt. Wenn eine schnelle Interruptanforderung empfangen wird, wird ein Flag gesetzt und der Programmzähler und die Bedingungscoderegister werden auf einem Stapel gespeichert. Am Ende der Interrupt-Wartungsroutine ruft die Rückkehr von Interrupt-Anweisungen das Bedingungscode-Register ab, das den Status des digitalen Datenprozessors enthält, und prüft, ob das Flag gesetzt wurde oder nicht. Wenn das Flag gesetzt ist, zeigt dies an, dass ein schneller Interrupt bedient wurde und daher nur der Programmzähler nicht gestapelt ist.

Mit anderen Worten, eine FIQ ist nur eine Interrupt-Anforderung mit höherer Priorität, die durch Deaktivieren von IRQ und anderen FIQ-Handlern während der Anforderungsbearbeitung priorisiert wird. Daher können während der Verarbeitung des aktiven FIQ-Interrupts keine weiteren Interrupts auftreten.


1
Nicht von der Antwort wegzunehmen, aber was in einem Patent steht, sagt nicht unbedingt etwas darüber aus, was implementiert ist, daher würde ich es nicht wirklich als maßgebliche Referenz betrachten.
abc

164

ARM fordert FIQdie schnelle Unterbrechung , mit der Implikation , die IRQist mit normaler Priorität . In jedem realen System gibt es viel mehr Interruptquellen als nur zwei Geräte, und daher gibt es einen externen Hardware-Interrupt-Controller, der das Maskieren, Priorisieren usw. dieser mehreren Quellen ermöglicht und die Interrupt-Anforderungsleitungen zum Prozessor steuert.

In gewissem Maße macht dies die Unterscheidung zwischen den beiden Interrupt-Modi überflüssig und viele Systeme verwenden sie überhaupt nicht nFIQoder analog zu dem nicht maskierbaren ( NMI) Interrupt, der auf anderen Prozessoren zu finden ist (obwohl er FIQauf den meisten ARM durch Software maskierbar ist) Prozessoren).

Warum nennt ARM FIQ "schnell"?

  1. Der FIQ-Modus verfügt über eigene Bankregister r8-r14. R14 ist das Verbindungsregister, das die Rücksprungadresse (+4) von der FIQ enthält. Wenn Ihr FIQ-Handler jedoch so geschrieben werden kann, dass er nur verwendet wird r8-r13, kann er diese Bankregister auf zwei Arten nutzen:
    • Zum einen entsteht kein Aufwand für das Drücken und Löschen von Registern, die von der Interrupt Service Routine (ISR) verwendet werden. Dies kann eine erhebliche Anzahl von Zyklen sowohl beim Ein- als auch beim Verlassen des ISR einsparen.
    • Außerdem kann sich der Handler auf Werte verlassen, die von einem Aufruf zum nächsten in Registern verbleiben, so dass er beispielsweise r8als Zeiger auf ein Hardwaregerät verwendet werden kann, und der Handler kann sich darauf verlassen , dass beim nächsten Aufruf derselbe Wert verwendet wird r8.
  2. FIQ-Position am Ende der Ausnahmevektortabelle ( 0x1C) bedeutet, dass keine Verzweigung erforderlich ist, wenn der FIQ-Handlercode direkt am Ende der Vektortabelle platziert wird - der Code kann direkt von ausgeführt werden 0x1C. Dies spart einige Zyklen beim Eintritt in den ISR.
  3. FIQ hat eine höhere Priorität als IRQ. Dies bedeutet, dass der Kern, wenn er eine FIQ-Ausnahme ausführt, IRQs automatisch maskiert. Ein IRQ kann den FIQ-Handler nicht unterbrechen. Das Gegenteil ist nicht der Fall - der IRQ maskiert keine FIQs und daher kann der FIQ-Handler (falls verwendet) den IRQ unterbrechen. Wenn sowohl IRQ- als auch FIQ-Anforderungen gleichzeitig auftreten, wird der Kern zuerst die FIQ behandeln.

Warum verwenden viele Systeme FIQ nicht?

  1. FIQ-Handlercode kann normalerweise nicht in C geschrieben werden - er muss direkt in Assemblersprache geschrieben werden. Wenn Sie sich ausreichend um die ISR-Leistung kümmern, um FIQ verwenden zu wollen, möchten Sie wahrscheinlich auf keinen Fall ein paar Zyklen in der Tabelle belassen, indem Sie in C codieren. Noch wichtiger ist jedoch, dass der C-Compiler keinen Code erzeugt, der der Einschränkung von folgt nur Register verwenden r8-r13. Code, der von einem C-Compiler erzeugt wird, der dem ATPCSProzeduraufrufstandard von ARM entspricht, verwendet stattdessen Register r0-r3für Scratch-Werte und erzeugt cpsram Ende der Funktion nicht den richtigen Wiederherstellungs-Rückkehrcode.
  2. Die gesamte Interrupt-Controller-Hardware befindet sich normalerweise am IRQ-Pin. Die Verwendung von FIQ ist nur dann sinnvoll, wenn eine einzige Interruptquelle mit der höchsten Priorität an den nFIQ-Eingang angeschlossen ist und viele Systeme keine einzige Quelle mit der dauerhaft höchsten Priorität haben. Es hat keinen Wert, mehrere Quellen mit dem FIQ zu verbinden und dann die Software zwischen ihnen zu priorisieren, da dadurch fast alle Vorteile des FIQ gegenüber dem IRQ beseitigt werden.

3
FIQ wird für sichere Welten in ARM TrustZone-Implementierungen verwendet, um Interrupts von "sicheren" Interruptquellen zu unterscheiden. Die genaue Bestimmung, was eine sichere Interruptquelle sein könnte und wie dies anders als bei einem normalen Interrupt gehandhabt werden sollte, hängt von den Bedrohungs- und Implementierungsmodellen ab.
Divegeek

1
Sowohl GCC als auch LLVM fehlen die für den FIQ-Code erforderlichen Optimierungen. Sie werden weiterhin die Register r0 bis r7 anstelle von r8 und höher verwenden. Und so drückt / generiert der generierte Code sie auf / vom Stapel. Wenn Sie eine Funktion aufrufen, verwenden die Compiler weiterhin den Standard-ABI (die Funktion kann r0 in r3 ändern). Ziemlich schnell wird die generierte Baugruppe zum Standard und ist ineffizient.
Sven

73

FIQ oder Fast Interrupt wird in einigen ARM-Referenzen häufig als Soft DMA bezeichnet .
Merkmale des FIQ sind:

  1. Separater Modus mit Bankregister einschließlich Stapel, Verbindungsregister und R8-R12.
  2. Separates FIQ-Aktivierungs- / Deaktivierungsbit.
  3. Ende der Vektortabelle (die sich immer im Cache befindet und von der MMU zugeordnet wird).

Das letzte Merkmal bietet auch einen leichten Vorteil gegenüber einem IRQ, der verzweigen muss.

Eine Geschwindigkeitsdemo in 'C'

Einige haben die Schwierigkeit der Codierung in Assembler zitiert, um die FIQ zu handhaben. gcchat Anmerkungen zum Codieren eines FIQ- Handlers. Hier ist ein Beispiel,

void  __attribute__ ((interrupt ("FIQ"))) fiq_handler(void)
{
    /* registers set previously by FIQ setup. */
    register volatile char *src asm ("r8");  /* A source buffer to transfer. */
    register char *uart asm ("r9");          /* pointer to uart tx register. */
    register int size asm ("r10");           /* Size of buffer remaining. */
    if(size--) {
        *uart = *src++;
    }
}

Dies führt zu dem folgenden fast guten Assembler:

00000000 <fiq_handler>:
   0:   e35a0000        cmp     sl, #0
   4:   e52d3004        push    {r3}            ; use r11, r12, etc as scratch.
   8:   15d83000        ldrbne  r3, [r8]
   c:   15c93000        strbne  r3, [r9]
  10:   e49d3004        pop     {r3}            ; same thing.
  14:   e25ef004        subs    pc, lr, #4

Die Assembler-Routine bei 0x1ckönnte wie folgt aussehen:

   tst     r10, #0    ; counter zero?
   ldrbne  r11, [r8]  ; get character.
   subne   r10, #1    ; decrement count
   strbne  r11, [r9]  ; write to uart
   subs    pc, lr, #4 ; return from FIQ.

Ein echter UART hat wahrscheinlich ein fertiges Bit, aber der Code zum Erstellen eines Hochgeschwindigkeits- Soft-DMA mit dem FIQ wäre nur 10-20 Anweisungen. Der Hauptcode muss den FIQ abfragen, r10um festzustellen, wann der Puffer fertig ist. Main (Nicht-Interrupt-Code) kann die Bank- FIQ- Register übertragen und einrichten , indem der msrBefehl zum Umschalten in den FIQ- Modus verwendet und Nicht-Bank-R0-R7 in die Bank-R8-R13-Register übertragen wird.

Normalerweise beträgt die RTOS-Interrupt-Latenz 500-1000 Anweisungen. Für Linux sind es möglicherweise 2000-10000 Anweisungen. Echter DMA ist immer vorzuziehen. Für einfache Hochfrequenz-Interrupts (wie eine Pufferübertragung) kann der FIQ jedoch eine Lösung bieten.

Da es bei der FIQ um Geschwindigkeit geht, sollten Sie dies nicht berücksichtigen, wenn Sie beim Codieren in Assembler nicht sicher sind (oder bereit sind, die Zeit zu verwenden). Assembler, die von einem unendlich laufenden Programmierer geschrieben wurden, sind schneller als ein Compiler. GCC-Unterstützung kann einem Anfänger helfen.

Latenz

Da der FIQ ein separates Maskenbit hat, ist er fast überall aktiviert. Auf früheren ARM-CPUs (wie dem ARM926EJ) mussten einige atomare Operationen durch Maskieren von Interrupts implementiert werden. Selbst bei den fortschrittlichsten Cortex-CPUs gibt es Fälle, in denen ein Betriebssystem Interrupts maskiert. Oft ist die Servicezeit nicht kritisch für einen Interrupt, sondern die Zeit zwischen Signalisierung und Wartung. Auch hier hat der FIQ einen Vorteil.

Die Schwäche

Der FIQ ist nicht skalierbar. Um mehrere FIQQuellen verwenden zu können, müssen die Bankregister von Interruptroutinen gemeinsam genutzt werden. Außerdem muss Code hinzugefügt werden, um festzustellen, was den Interrupt / FIQ verursacht hat. Der FIQ ist im Allgemeinen ein One-Trick-Pony .

Wenn Ihr Interrupt sehr komplex ist (Netzwerktreiber, USB usw.), ist die FIQ wahrscheinlich wenig sinnvoll. Dies ist im Grunde die gleiche Aussage wie das Multiplexen der Interrupts. Die Bankregister geben 6 freie Variablen zur Verwendung an, die niemals aus dem Speicher geladen werden . Register sind schneller als Speicher. Register sind schneller als L2-Cache. Register sind schneller als L1-Cache. Register sind schnell. Wenn Sie keine Routine schreiben können, die mit 6 Variablen ausgeführt wird, ist der FIQ nicht geeignet. Hinweis: Wenn Sie 16-Bit-Werte verwenden, können Sie einige Register mit Verschiebungen und Drehungen, die auf dem ARM frei sind, doppelt ausführen .

Offensichtlich ist der FIQ komplexer. Betriebssystementwickler möchten mehrere Interruptquellen unterstützen. Die Kundenanforderungen für eine FIQ variieren und oft erkennen sie, dass sie den Kunden einfach ihre eigenen rollen lassen sollten . Normalerweise ist die Unterstützung für eine FIQ begrenzt, da jede Unterstützung wahrscheinlich den Hauptnutzen, SPEED , beeinträchtigt .

Zusammenfassung

Schlagen Sie meinen Freund nicht auf den FIQ . Es ist ein Systemprogrammierer ein Trick gegen dumme Hardware. Es ist nicht jedermanns Sache, aber es hat seinen Platz. Wenn alle anderen Versuche, die Latenz zu verringern und die ISR-Servicefrequenz zu erhöhen, fehlgeschlagen sind, kann der FIQ Ihre einzige Wahl sein (oder ein besseres Hardwareteam).

In einigen sicherheitskritischen Anwendungen kann es auch als Panikunterbrechung verwendet werden .


1
Als Ergänzung ist es für ein sicheres Weltbetriebssystem (ARM TrustZone) ziemlich obligatorisch, die FIQ zu verwenden . In diesem Fall fungiert es jedoch als normaler Interrupt-Handler und nicht als herkömmliche SoftDMA- Rolle. Die normale Welt verwendet den normalen IRQ- Mechanismus und die sichere verwendet den FIQ .
Kunstloser Lärm

Ich frage mich nur, warum Sie nicht ACK lesen und EOI in Ihrem Handler
senden

@Charvak Das ist Interrupt-Controller-spezifisch; Sie denken GIC . Einige Interrupt-Controller werden automatisch gelöscht (d. H. Uart ready wird nicht fertig, wenn ein Zeichen geschrieben wird). Es ist ein hypothetisches Beispiel (für eine generische Antwort; das OP hatte einen ARM926) und kein tatsächliches Arbeitsbeispiel. Legen Sie die GIC- Basis in ein FIQ-Register und führen Sie das ACKund aus EOI, wenn dies der Controller ist, den Sie haben.
Kunstloser Lärm

Lokale Registervariablen tun nicht das, was Sie vielleicht denken. Sie reservieren das Register nicht für eine bestimmte Variable. Tatsächlich garantiert gcc nur, dass sich der Wert der Variablen in der angegebenen Registrierung befindet, wenn eine Inline-Assembly ausgeführt wird, deren angegebene Variable ein Eingabe- oder Ausgabeparameter ist. Zu jedem anderen Zeitpunkt kann das Register für andere Daten verwendet werden. Insbesondere glaube ich, dass gcc nicht versteht, dass von srcim Register sein muss, r8wenn die Funktion zurückkehrt. Hier scheinen jedoch globale Registervariablen geeignet zu sein, da sie die Register reservieren.
Sven

1
Es ist bekannt, dass GCC dazu neigt, die Register r0 bis r7 zu verwenden, obwohl r8 und Freunde verwendet werden könnten. Schade, aber GCC ist meiner Meinung nach noch nicht optimal für das Schreiben von FIQ-Handlern. Als Referenz: gcc.gnu.org/bugzilla/show_bug.cgi?id=48429
Sven

6

Chaos hat bereits gut geantwortet, aber ein zusätzlicher Punkt, der bisher nicht behandelt wurde, ist, dass FIQ am Ende der Vektortabelle steht und es daher üblich ist, die Routine genau dort zu starten, während der IRQ-Vektor normalerweise genau das ist. (dh ein Sprung zu woanders). Das Vermeiden dieses zusätzlichen Zweigs unmittelbar nach einem vollständigen Stash- und Kontextwechsel ist eine leichte Geschwindigkeitssteigerung.


5

Ein weiterer Grund ist, dass im Fall von FIQ eine geringere Anzahl von Registern erforderlich ist, um den Stapel einzuschieben. Der FIQ-Modus verfügt über R8- bis R14_fiq-Register


3

FIQ hat eine höhere Priorität und kann eingeführt werden, während ein anderer IRQ verarbeitet wird. Die kritischsten Ressourcen werden von FIQs verwaltet, der Rest von IRQs.



1

FIQs haben zweifellos eine höhere Priorität, verbleibende Punkte Ich bin mir nicht sicher ..... FIQs unterstützen die Hochgeschwindigkeitsdatenübertragung (oder) Kanalverarbeitung, wenn Hochgeschwindigkeitsdatenprozesse erforderlich sind, verwenden wir FIQs und im Allgemeinen werden IRQs als normale Interrupt-Behandlung verwendet .


0

Keine Magie über FIQ. FIQ kann nur jeden anderen IRQ unterbrechen, der bedient wird. Deshalb wird es als "schnell" bezeichnet. Das System reagiert schneller auf diese Interrupts, der Rest ist jedoch der gleiche.


0

Es hängt davon ab, wie wir Interrupt-Handler entwerfen, da FIQ endlich keinen Verzweigungsbefehl benötigt. Außerdem verfügt es über einen eindeutigen Satz von r8-r14-Registern, sodass wir das nächste Mal, wenn wir zum FIQ-Interrupt zurückkehren, den Push / Popup nicht benötigen Stapel. Natürlich spart es einige Zyklen, aber es ist auch nicht ratsam, mehr Handler zu haben, die eine FIQ bedienen, und ja, FIQ hat mehr Priorität, aber es gibt keinen Grund zu sagen, dass es den Interrupt schneller behandelt, beide IRQ / FIQ laufen mit derselben CPU-Frequenz. Sie müssen also mit der gleichen Geschwindigkeit laufen.


-5

Dies kann falsch sein. Ich weiß nur, dass FIQ für Fast Interrupt Request und IRQ für Interrupt Request steht. Nach diesen Namen zu urteilen, werde ich vermuten, dass ein FIQ schneller behandelt (geworfen?) Wird als ein IRQ. Es hat wahrscheinlich etwas mit dem Design des Prozessors zu tun, bei dem ein FIQ den Prozess schneller unterbricht als ein IRQ. Ich entschuldige mich, wenn ich falsch liege, aber normalerweise programmiere ich auf höherer Ebene. Ich rate gerade.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.