FIQ和IRQ中断系统有什么区别?

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?

  1. FIQ模式有自己的专用存储寄存器r8-r14.R14是链接寄存器,它保存来自FIQ的返回地址(+4).但是如果你的FIQ处理程序能够被编写为只使用r8-r13它,它可以通过两种方式利用这些存储寄存器:
    • 一个是它不会产生推送和弹出中断服务程序(ISR)使用的任何寄存器的开销.这可以在进入和退出ISR时节省大量周期.
    • 此外,处理程序可以依赖于从一个调用到下一个调用的寄存器中持久存储的值,因此例如r8可以用作指向硬件设备的指针,并且处理程序可以依赖于r8下次调用它时的相同值.
  2. 异常向量表(0x1C)末尾的FIQ位置意味着如果FIQ处理程序代码直接放在向量表的末尾,则不需要分支 - 代码可以直接从中执行0x1C.这样可以在进入ISR时节省几个周期.
  3. FIQ的优先级高于IRQ.这意味着当核心获取FIQ异常时,它会自动屏蔽掉IRQ.IRQ无法中断FIQ处理程序.相反的情况并非如此 - IRQ不会屏蔽FIQ,因此FIQ处理程序(如果使用)可以中断IRQ.此外,如果IRQ和FIQ请求同时发生,核心将首先处理FIQ.

那么为什么许多系统不使用FIQ?

  1. FIQ处理程序代码通常不能用C编写 - 它需要直接用汇编语言编写.如果你非常关心ISR性能想要使用FIQ,你可能不希望在任何情况下通过C编码在表上留下几个周期,但更重要的是C编译器不会产生遵循限制的代码仅使用寄存器r8-r13.由符合ARM ATPCS过程调用标准的C编译器生成的代码将使用寄存器r0-r3作为暂存值,并且不会cpsr在函数末尾生成正确的恢复返回代码.
  2. 所有中断控制器硬件通常都在IRQ引脚上.如果您将单个最高优先级的中断源连接到nFIQ输入并且许多系统没有一个永久性最高优先级源,则仅使用FIQ才有意义.将多个源连接到FIQ并且然后让软件在它们之间进行优先级排序没有任何价值,因为这消除了FIQ相对于IRQ的几乎所有优点.

  • FIQ用于ARM TrustZone实现中的Secure Worlds,以区分中断与"安全"中断源.准确确定什么是安全中断源以及如何以正常中断的方式处理它取决于威胁和实现模型. (3认同)

art*_*ise 69

在某些ARM参考中,FIQ快速中断通常称为软DMA.FIQ的
特点是,

  1. 具有存储寄存器的独立模式,包括堆栈,链接寄存器和R8-R12.
  2. 单独的FIQ启用/禁用位.
  3. 矢量表尾(总是在缓存中并由MMU映射).

最后一个功能也比必须分支的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++;
    }
}
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可能是您唯一的选择(或更好的硬件团队).

它也可以在某些安全关键应用中用作恐慌中断.

  • +1.不敢相信没有人在此之前投票. (3认同)

Cha*_*aos 59

现代ARM CPU(以及其他一些CPU)的一个特性.

来自专利:

提供了一种在具有处理一个以上中断的能力的数字数据处理器中执行快速中断的方法.当接收到快速中断请求时,标志置位,程序计数器和条件代码寄存器存储在堆栈中.在中断服务程序结束时,中断指令返回检索包含数字数据处理器状态的条件代码寄存器,并检查该标志是否已设置.如果该标志置位,则表示快速中断被服务,因此只有程序计数器被取消堆栈.

换句话说,FIQ只是一个优先级较高的中断请求,通过在请求服务期间禁用IRQ和其他FIQ处理程序来确定优先级.因此,在处理活动FIQ中断期间不会发生其他中断.

  • 并不是要回避答案,但专利中的内容并不一定说明所实施的内容,所以我不会真正认为它是权威参考。 (2认同)

Pod*_*Pod 6

混沌已经得到了很好的回答,但到目前为止还没有涉及的另一点是FIQ位于向量表的末尾,因此在那里启动例程是常见的/传统的,而IRQ向量通常就是这样.(即跳到其他地方).完全存储和上下文切换后立即避免额外的分支是一个轻微的速度增益.


小智 5

另一个原因是在 FIQ 的情况下,需要较少数量的寄存器压入堆栈,FIQ 模式有 R8 到 R14_fiq 寄存器