FIQ或者快速中断,在一些ARM参考文献中被称为软DMA。 FIQ的特点包括:

独立模式,具有存储器区和堆栈、链接寄存器以及R8-R12。

独立的FIQ使能/禁用位。

向量表的尾部(始终在缓存中,并由MMU映射)。

最后一个特点也比IRQ稍微具有一些优势,因为IRQ需要分支。

'C'语言中的速度演示

有人引用了使用汇编处理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 :

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。它是系统程序员对付愚蠢硬件的一个技巧。它并不适用于每个人