Ich möchte den Unterschied zwischen FIQ- und IRQ-Interrupt-System in jedem Mikroprozessor kennen, z. B.: ARM926EJ.
Ich möchte den Unterschied zwischen FIQ- und IRQ-Interrupt-System in jedem Mikroprozessor kennen, z. B.: ARM926EJ.
Antworten:
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.
ARM fordert FIQ
die schnelle Unterbrechung , mit der Implikation , die IRQ
ist 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 nFIQ
oder analog zu dem nicht maskierbaren ( NMI
) Interrupt, der auf anderen Prozessoren zu finden ist (obwohl er FIQ
auf den meisten ARM durch Software maskierbar ist) Prozessoren).
Warum nennt ARM FIQ "schnell"?
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:
r8
als 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
.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.Warum verwenden viele Systeme FIQ nicht?
r8-r13
. Code, der von einem C-Compiler erzeugt wird, der dem ATPCS
Prozeduraufrufstandard von ARM entspricht, verwendet stattdessen Register r0-r3
für Scratch-Werte und erzeugt cpsr
am Ende der Funktion nicht den richtigen Wiederherstellungs-Rückkehrcode.FIQ oder Fast Interrupt wird in einigen ARM-Referenzen häufig als Soft DMA bezeichnet .
Merkmale des FIQ sind:
Das letzte Merkmal bietet auch einen leichten Vorteil gegenüber einem IRQ, der verzweigen muss.
Einige haben die Schwierigkeit der Codierung in Assembler zitiert, um die FIQ zu handhaben. gcc
hat 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 0x1c
kö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, r10
um festzustellen, wann der Puffer fertig ist. Main (Nicht-Interrupt-Code) kann die Bank- FIQ- Register übertragen und einrichten , indem der msr
Befehl 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.
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.
Der FIQ ist nicht skalierbar. Um mehrere FIQ
Quellen 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 .
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 .
ACK
und aus EOI
, wenn dies der Controller ist, den Sie haben.
src
im Register sein muss, r8
wenn die Funktion zurückkehrt. Hier scheinen jedoch globale Registervariablen geeignet zu sein, da sie die Register reservieren.
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.
Ich glaube, das ist es, wonach Sie suchen:
http://newsgroups.derkeiler.com/Archive/Comp/comp.sys.arm/2005-09/msg00084.html
Im Wesentlichen hat FIQ die höchste Priorität mit mehreren IRQ-Quellen mit niedrigerer Priorität.
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 .
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.
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.
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.