Ren*_*h G 69 drivers arm interrupt isr microprocessors
我想知道任何微处理器中FIQ和IRQ中断系统之间的区别,例如:ARM926EJ.
man*_*m-n 162
ARM调用FIQ
的快速中断,与寓意IRQ
是正常优先级.在任何实际系统中,将存在比仅仅两个设备更多的中断源,因此将存在一些外部硬件中断控制器,其允许这些多个源的屏蔽,优先级等,并且将中断请求线驱动到处理器.
在某种程度上,这使得两种中断模式之间的区别是冗余的,并且许多系统根本不使用nFIQ
它,或者以类似于NMI
其他处理器上发现的不可屏蔽()中断的方式使用它(尽管FIQ
在大多数ARM上是软件可屏蔽的)处理器).
那么为什么ARM会"快速"调用FIQ?
r8-r14
.R14是链接寄存器,它保存来自FIQ的返回地址(+4).但是如果你的FIQ处理程序能够被编写为只使用r8-r13
它,它可以通过两种方式利用这些存储寄存器:
r8
可以用作指向硬件设备的指针,并且处理程序可以依赖于r8
下次调用它时的相同值.0x1C
)末尾的FIQ位置意味着如果FIQ处理程序代码直接放在向量表的末尾,则不需要分支 - 代码可以直接从中执行0x1C
.这样可以在进入ISR时节省几个周期.那么为什么许多系统不使用FIQ?
r8-r13
.由符合ARM ATPCS
过程调用标准的C编译器生成的代码将使用寄存器r0-r3
作为暂存值,并且不会cpsr
在函数末尾生成正确的恢复返回代码.art*_*ise 69
在某些ARM参考中,FIQ或快速中断通常称为软DMA.FIQ的
特点是,
最后一个功能也比必须分支的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++;
}
}
Run Code Online (Sandbox Code Playgroud)
这转换为以下几乎好的汇编程序,
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
Run Code Online (Sandbox Code Playgroud)
汇编程序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.
Run Code Online (Sandbox Code Playgroud)
实际的UART可能有一个就绪位,但使用FIQ 制作高速软DMA的代码只能是10-20条指令.主代码需要轮询FIQ r10
以确定缓冲区何时完成.主(非中断代码)可以通过使用指令切换到FIQ模式并将非存储的R0-R7传送到存储的R8-R13寄存器来传送和设置存储的FIQ寄存器.msr
通常,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位值,您可以对一些带有移位的寄存器进行双重操作,并在ARM上自由旋转.
显然,FIQ更复杂.OS开发人员希望支持多个中断源.FIQ的客户要求会有所不同,通常他们会意识到他们应该让客户自己动手.通常对FIQ的支持是有限的,因为任何支持都可能减损主要利益SPEED.
不要猛击我的朋友FIQ.这是一个系统程序员针对愚蠢硬件的一招.它不适合所有人,但它有其自己的位置.当所有其他减少延迟和提高ISR服务频率的尝试都失败时,FIQ可能是您唯一的选择(或更好的硬件团队).
它也可以在某些安全关键应用中用作恐慌中断.
Cha*_*aos 59
现代ARM CPU(以及其他一些CPU)的一个特性.
来自专利:
提供了一种在具有处理一个以上中断的能力的数字数据处理器中执行快速中断的方法.当接收到快速中断请求时,标志置位,程序计数器和条件代码寄存器存储在堆栈中.在中断服务程序结束时,中断指令返回检索包含数字数据处理器状态的条件代码寄存器,并检查该标志是否已设置.如果该标志置位,则表示快速中断被服务,因此只有程序计数器被取消堆栈.
换句话说,FIQ只是一个优先级较高的中断请求,通过在请求服务期间禁用IRQ和其他FIQ处理程序来确定优先级.因此,在处理活动FIQ中断期间不会发生其他中断.
混沌已经得到了很好的回答,但到目前为止还没有涉及的另一点是FIQ位于向量表的末尾,因此在那里启动例程是常见的/传统的,而IRQ向量通常就是这样.(即跳到其他地方).完全存储和上下文切换后立即避免额外的分支是一个轻微的速度增益.