Linux如何及时响应外部中断

Linux如何及时响应外部中断,第1张

FPGA每隔100us给运行linux的ARM一个中断,要求在20us内响应中断,并读走200016bit的数据。

目前主要的问题是,当系统同时发生多个中断时,会严重影响linux对FPGA中断的响应时间。如何解决?

1、首先想到了ARM的FIQ,它可以打断IRQ中断服务程序,保证对外部FIQ的及时响应。但是发现linux只实现了IRQ,没有显示FIQ。

linux是从devicetree读取中断号,加入中断向量表的。

interrupts = <0x0 0x32 0x0>;中的第一个字段0表示非共享中断,非零表示共享中断,SDK产生的dts统一为0,此时第二字段的值比XPS中的小32;如果第一字段非零,则第二字段比XPS小16

最后字段表示中断的触发方式。

IRQ_TYPE_EDGE_RISING =0x00000001,

IRQ_TYPE_EDGE_FALLING =0x00000002,

IRQ_TYPE_LEVEL_HIGH =0x00000004,

IRQ_TYPE_LEVEL_LOW =0x00000008,

很明显,devicetree根本没有提供通知linux有FIQ的渠道。

2、再来看linux的IRQ

linux的中断分为上半部和下半部,上半部运行在IRQ模式,会屏蔽所有中断,下半部运行在SVC模式,会重新打开中断。

也就是说,当一个中断的上半部正在运行时(不能再次响应中断),FPGA的中断是不能被linux响应的;

反过来,当FPGA中断的上半部正在运行时(不能再次响应中断),其他的中断也不能被linux响应;

unsigned long flags;

local_irq_save(flags);

local_irq_restore(flags);

3

ARM有七种模式,我们这里只讨论SVC、IRQ和FIQ模式。

我们可以假设ARM核心有两根中断引脚(实际上是看不见的),一根叫 irq pin, 一根叫fiq pin

在ARM的cpsr中,有一个I位和一个F位,分别用来禁止IRQ和FIQ的。

先不说中断控制器,只说ARM核心。正常情况下,ARM核都只是机械地随着pc的指示去做事情,当CPSR中的I和F位为1的时候,IRQ和FIQ全部处于禁止状态。无论你在irq

pin和fiq pin上面发什么样的中断信号,ARM是不会理你的,你根本不能打断他,因为他耳聋了,眼也瞎了。

在I位和F位为0的时候,当irq

pin上有中断信号过来的时候,就会打断arm的当前工作,并且切换到IRQ模式下,并且跳到相应的异常向量表(vector)位置去执行代码。这个过程是自动的,但是返回到被中断打断的地方就得您亲自动手了。当你跳到异常向量表,处于IRQ的模式的时候,这个时候如果irq

pin上面又来中断信号了,这个时候ARM不会理你的,irq

pin就跟秘书一样,ARM核心就像老板,老板本来在做事,结果来了一个客户,秘书打断它,让客户进去了。而这个时候再来一个客户,要么秘书不断去敲门问,要么客户走人。老板第一个客户没有会见完,是不会理你的。

但是有一种情况例外,当ARM处在IRQ模式,这个时候fiq pin来了一个中断信号,fiq

pin是什么?是快速中断呀,比如是公安局的来查刑事案件,那才不管你老板是不是在会见客户,直接打断,进入到fiq模式下,并且跳到相应的fiq的异常向量表处去执行代码。那如果当ARM处理FIQ模式,fiq

pin又来中断信号,又就是又一批公安来了,那没戏,都是执法人员,你打不断我。那如果这个时候irq

pin来了呢?来了也不理呀,正在办案,还敢来妨碍公务。

所以得出一个结论: IRQ模式只能被FIQ模式打断,FIQ模式下谁也打不断。

在打不断的情况下,irq pin 或 fiq pin随便你怎么发中断信号,都是白发。

所以除了fiq能打断irq以外,根本没有所谓中断嵌套的情况。

Linux不用FIQ,只用到了IRQ。但是我们有时候一个中断需要处理很长时间,那我们就需要占用IRQ模式那么长的时间吗?没有,linux在IRQ模式下只是简单的记录是什么中断,马上就切换回了SVC模式,换句话说,Linux的中断处理都是在SVC模式下处理的。

只不过SVC模式下的ISR上半部关闭了当前中断线,下半部才重新打开

void_attribute_(type)

是一个函数 返回值为一个类型名;

interrupt(char)

也是一个函数 作用是将一个有标识作用的字符串转换为void_attribute_(type)可识别参数

SysTick_Handler(void)

仍是一个函数,没有参数,但有返回值,返回值类型由void_attribute_(type) 决定,作用是完成一些内部 *** 作

本语句整体上是SysTick_Handler(void)引领定义的函数体

老城百姓

异常和中断

1ARM

处理器复位后,处理器硬件将进行如下 *** 作:

(1)

强制进入管理模式;

(2)

强制进入到

ARM

状态;

(3)

跳转到绝对地址

PC=0x00000000

出执行;

(4)

禁止

IRQ

中断和

FIQ

中断。

复位后

CPSR

中最后

4

位状态为

0011,并且进入管理模式,执行 *** 作系统程序,

一般用做对系统的初始化,然后切换到用户模式,开始执行正常的用户程序,切

换到用户模式可以使用如下程序:

MRS

R0,CPSR

;读程序状态寄存器

BIC

R0,R0,#03

;把末两位清零

MSR

CPSR_c

,R0

;把修改后的值加载给状态寄存器,切换结束

ADD

R1,R2,R3

;用户程序

2未定义异常

ARM

处理器中有很多没有定义的代码,因为

ARM

使用

32

位代码,包含

2

31

次幂种。所以

ARM

指令集不能用尽所有的代码。

ARM

的未定义异常有两种情况:

(1)

遇到一条无法执行的指令,此指令没有定义;

(2)

执行一条协处理器的 *** 作指令,在正常情况下,协处理器应该应答,但是

没有,可能是因为干扰等原因。

但是一般情况下是不希望产生异常的,如果是由于干扰引起的异常,那么在

异常中断处理中有一段专门的程序,让程序返回再重新执行该条指令,以判

断异常是否是由干扰引起。

当然也要注意哪种单片机应该使用哪种合适的指令集版本,因为还是约

有差异的,否则某些编译通过的指令也不能执行。

3

软件中断异常

软件中断异常是由指令

SWI

引起的,

程序执行这一条指令后,

进入异常中断。

处理器响应中断,硬件执行图如下:

软件中断处理程序完成后,使用下列返回指令返回到原中断处:

MOVS

PC

,

R14

软件中断异常把程序导入管理模式,而子程序调用属于用户模式。

4

预取指中断异常

。。。

。。

预取指中断异常和未定义指令异常都是由于不正常的指令国产引起,但是也

有区别:

(1)

未定义指令异常是内部异常中断,而他是外部信号引起的异常中断;

(2)

他并没有成功地取得一条指令。

他中断返回时,应该执行指令:SUBS

PC

,

R14

,

#4

5数据中止异常

。。。

。。。

6中断请求(IRQ)异常

ARM

处理器中,有一个输入逻辑

nIRQ

称为中断请求信号,这个输入信

号是由

ARM

处理器外围控制模块(片内)控制,当有满足中断条件的事件发生

时,

外围控制模块向

ARM

处理器发错

IRQ

信号,

ARM

处理器进入异常,

使

IRQ

中断是常用的中断,就像

51

系列单片机中定时器中断、串口中断、外部中断等。

CPSR[7]

IRQ

完成中断处理后,

程序应该执行下列指令返回到原中断处:

SUBS

PC

,

R14

,

#4

7

快速中断(FIQ)请求异常

ARM

处理器中,有一个输入逻辑

nFIQ

称为中断请求信号,这个输入信

号是由

ARM

处理器外围控制模块(片内)控制,当有满足中断条件的事件发生

时,

外围控制模块向

ARM

处理器发错

FIQ

信号,

ARM

处理器进入异常。

使

FIQ

中断可以通过

CPSR[6]来屏蔽。

注意:进入异常会引起处理器模式转换。

这个有几个原因,请参考下面分析:

1,ucos

是多任务 *** 作系统,当系统正常运行时,必须建立一个以上的任务,否则系统处于死机崩溃状态,程序运行出现异常。

2,你的系统时钟中断程序有问题,应该关中断,调用过系统时钟后再开中断,否则系统时钟异常导致程序运行异常,具体程序如下:

void

Tmr_TickISR_Handler

(void)

{

T0IR

=

0xFF;

//清零中断标志位

OSIntEnter(

);

//

关中断,必须有

OSTimeTick();

OSIntExit();

//临界代码完成,与关中断成对使用

}

3,看你上面的程序里面,你想使用定时器1中断来处理一些信息,而程序无法运行到其中,可能的原因有:1)你的定时器1初始化异常。2)你系统里面的中断使能关掉了。其实多任务的时候,你完全可以将它分配到一个任务里处理,这样既可以充分利用多任务,又不会因为中断没处理好而出现异常,如果你想要求实时性较高,那你可以将这个人物的优先级设为最高。

4,UCOS初始化异常,UCOS系统初始化有固定的顺序以及模式,颠倒了就会出现异常。

5,系统时钟tick一般建议为10hz-50hz,太高的话在你初始化的时候,还没创建任务的时候都已经进行任务切换了而导致ucos崩溃。

以上就是关于Linux如何及时响应外部中断全部的内容,包括:Linux如何及时响应外部中断、C++中ARM Stm32的中断问题 extern "C" { void __attribut、ARM处理器中,引起异常的原因是什么等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9809960.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-02
下一篇 2023-05-02

发表评论

登录后才能评论

评论列表(0条)

保存