我想了解在任何微处理器中(例如ARM926EJ),FIQ和IRQ中断系统之间的区别。
我想了解在任何微处理器中(例如ARM926EJ),FIQ和IRQ中断系统之间的区别。
ARM将FIQ
称为快速中断,这意味着IRQ
是普通优先级。在任何实际系统中,除了两个设备外,还会有许多其他的中断源,因此会有一些外部硬件中断控制器,它允许对这些多个源进行屏蔽、优先级等控制,并驱动中断请求线到处理器。
在某种程度上,这使得两种中断模式之间的区别变得多余,许多系统根本不使用nFIQ
,或者以与其他处理器上找到的非可屏蔽(NMI
)中断类似的方式使用它(尽管在大多数ARM处理器上,FIQ
是可以被软件屏蔽的)。
那么为什么ARM将FIQ称为“快速”?
r8-r14
。R14是链接寄存器,保存从FIQ返回地址(+4)。但是,如果您的FIQ处理程序能够被编写成只使用r8-r13
,它可以通过两种方式利用这些储存器组:
r8
可以用作指向硬件设备的指针,处理程序可以信赖下一次被调用时r8
中有相同的值。0x1C
),这意味着如果FIQ处理程序代码直接放置在向量表的末尾,则不需要分支-代码可以直接从0x1C
执行。这可以在进入ISR时节省几个周期。那为什么许多系统不使用FIQ?
r8-r13
的限制的代码。符合ARM的 ATPCS
过程调用标准的C编译器生成的代码将使用寄存器 r0-r3
作为临时值,并且不会在函数结尾处生成正确的cpsr
还原返回代码。FIQ或者快速中断,在一些ARM参考文献中被称为软DMA。
FIQ的特点包括:
最后一个特点也比IRQ稍微具有一些优势,因为IRQ需要分支。
有人引用了使用汇编处理FIQ的编码难度。 gcc
有注释来编写FIQ处理程序。以下是一个示例:
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++;
}
}
这将翻译成以下几乎良好的汇编代码:
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
地址为0x1c
的汇编程序可能如下所示:
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.
一个真正的UART可能会有一个准备位,但用于实现高速软件DMA和FIQ的代码通常只需要10-20条指令。主要代码需要轮询FIQ r10
来确定缓冲区何时完成。主(非中断)代码可以通过使用msr
指令切换到FIQ模式并将非分行的R0-R7转移到分行的R8-R13寄存器来传输和设置分行的FIQ寄存器。
通常RTOS中断延迟为500-1000条指令。对于Linux, 可能是2000-10000条指令。实际DMA总是更可取的,但对于高频简单中断(如缓冲区传输),FIQ可以提供解决方案。
由于FIQ是关于速度的,如果你不确定自己能否在汇编语言中编码(或愿意投入时间),则不应考虑它。由无限运行的程序员编写的汇编程序比编译器更快。使用GCC可以帮助新手。
由于FIQ有一个单独的掩码位,因此几乎普遍启用。在早期的ARM CPU(如ARM926EJ)中,一些原子操作必须通过屏蔽中断来实现。即使是最先进的Cortex CPU,仍有时候操作系统会屏蔽中断。通常服务时间对于中断并不重要,但信号和服务之间的时间很重要。在这里,FIQ也具有优势。
FIQ不可扩展。为了使用多个FIQ源,分行寄存器必须在中断例程之间共享。还必须添加代码以确定引起中断/FIQ的原因。 FIQ通常是一个“万能选手”。
如果你的中断非常复杂(网络驱动程序、USB等),那么FIQ可能就没有意义了。这与多路复用中断的说法基本相同。分行寄存器提供了6个免费变量可供使用,它们不需要从内存中读取。寄存器比内存快。寄存器比L2缓存快。寄存器比L1缓存快。寄存器很快。如果你无法编写一个使用6个变量运行的例程,那么FIQ就不适合。注意:如果使用16位值,可以使用移位和旋转来同时双重处理某些寄存器。
显然,FIQ更为复杂。操作系统开发人员希望支持多个中断源。客户对FIQ的要求也各不相同,他们往往意识到应该让客户自己去实现。通常,对FIQ的支持是有限的,因为任何支持都可能削弱其主要优势——速度。
不要抨击我的朋友FIQ。它是系统程序员对付愚蠢硬件的一个技巧。它并不适用于每个人
ACK
和 EOI
。 - artless noisesrc
必须在寄存器 r8
中。然而,全局寄存器变量似乎很适合这里,因为它们确实保留了寄存器。 - Sven现代ARM CPU(和一些其他CPU)的一个特性。
来自专利文件:
提供了一种在数字数据处理器中执行快速中断的方法,该数字数据处理器具有处理多个中断的能力。当接收到快速中断请求时,将设置一个标志并将程序计数器和条件代码寄存器存储在堆栈上。在中断服务例程结束时,从中断返回指令检索包含数字数据处理器状态的条件代码寄存器,并检查标志是否已设置。如果设置了标志,则表示已服务于快速中断,因此只需取消堆栈上的程序计数器。
换句话说,FIQ就是更高优先级的中断请求,在请求处理期间通过禁用IRQ和其他FIQ处理程序来优先处理。因此,在处理活动FIQ中断时不会发生其他任何中断。
另一个原因是在FIQ情况下,只需要较少的寄存器推入堆栈,FIQ模式具有R8到R14_fiq寄存器。
FIQ是更高优先级的,可以在处理另一个IRQ时引入。 FIQ处理最关键的资源,其余资源由IRQ处理。
FIQ(快速中断请求)具有更高的优先级,毫无疑问,其他方面我不确定...... FIQ将支持高速数据传输或通道处理,在需要高速数据处理时我们使用FIQ,通常IRQ(普通中断请求)用于正常的中断处理。
我相信这就是你要找的内容:
http://newsgroups.derkeiler.com/Archive/Comp/comp.sys.arm/2005-09/msg00084.html
基本上,FIQ将具有最高优先级和多个较低优先级的IRQ源。
关于FIQ没有任何魔法。FIQ可以中断正在服务的任何其他IRQ,这就是为什么它被称为“快速”的原因。系统对这些中断的反应更快,但其余部分保持不变。
这取决于我们如何设计中断处理程序,因为FIQ是最后一个,它可能不需要一个分支指令,而且它有独特的r8-r14寄存器集,所以下一次我们回到FIQ中断时,我们不需要将栈推入/弹出。当然,它节省了一些周期,但再次,让更多的处理程序为一个FIQ服务并不明智,是的,FIQ的优先级更高,但这并不意味着它处理中断更快,IRQ/FIQ都在相同的CPU频率下运行,所以它们必须以相同的速度运行。