电子说
1. 概述
中断是指MCU在运行过程中,出现某些意外情况需处理时,MCU能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。中断提供了应用程序与现实世界中发生的事情之间的接口。例如,我们可以使用中断来捕获触发的按钮、看门狗喂狗操作或计算发生的时间等。
当中断发生时,处理器通常查看内存中的一个预先定义好的位置,称为中断向量。向量通常包含相关中断处理程序的地址,而包含应用程序中所有向量的内存块称为中断向量表。
2. 基本概念
2.1 中断的分类
中断可按优先级划分为单级中断与多级中断,也可按OS是否参与处理将中断分为一类与二类中断:
2.1.1 单级与多级中断
单级:即所有的中断处于同一优先级,这也就意味着当一个中断正在执行时,其他中断必须排队等待直到当前中断处理完成。
多级:类似于Task中断也区分不同的优先级,低优先级的中断可以被高优先级的中断抢占。
2.1.2 一类与二类中断
一类中断:不与OS进行交互,是优先级最高的中断,需要用户正确的配置硬件、编写处理程序并从中断中返回,用不好的话出错概率高,一般应用较少。
二类中断:一般项目中使用的都是此类中断,中断发生时,RTA-OS执行内部代码,然后调用用户提供的ISR。中断执行从ISR的指定入口点开始,一直持续到入口函数返回。
2.2 中断优先级
在中断的一般应用中,中断以多级中断应用为主,按中断优先级(IPL-Interrupt Priority Level)执行,RTA-OS对IPL进行了标准化,其中IPL 0表示用户级别,其中所有任务都执行,IPL为1或更多表示中断级别。
在单级平台上有两个IPL,0和1。IPL 0表示目标不被中断,任务按优先级顺序运行。IPL 1表示目标正在为中断提供服务。由于只有一个非零IPL,所有中断(类别1和类别2)都以相同的优先级运行。这意味着所有中断都是序列化的,如下图(a)。
在多级平台上,高优先级中断可以抢占低优先级中断,因此ISRs处理程序可以嵌套,但ISR不能被低优先级任务抢占,如下图(b)。
根据优先级顺序,一类中断优先级更高,其不能被二类中断抢占,所有的2类中断都比最低级的一类中断低。
也可进一步对中断的优先级按Task及OS级别继续划分为User Level和OS Level,此两种中断划分也是宏观级别的划分,具体如下:
2.2.1 User Level
所谓User level,即是用户可以控制的级别,即Task级别,用户级别是允许处理所有中断的最低中断优先级。所有任务都从其入口点开始在用户级别执行。
任务有时需要在用户级别以上运行,例如,它可能需要访问与ISR共享的数据。当数据被访问时,必须防止中断被调用。实现这一点的最简单方法是,可以在任务在访问数据时禁用中断。另一种方法是使用Resource机制,即当Task或2类中断已经获得资源后,其他任务或ISR无法获得该资源,防止任何其他任务或ISR同时进入同一关键部分,如修改同一处变量导致程序出错。
2.2.2 OS Level
由于二类中断是需要OS参与,这样2类ISR的最高优先级定义了OS级别。如果执行发生在OS级别或更高级别(一类中断),则不会发生其他类别2中断。RTA-OS使用OS Level来防止并发访问内部操作系统数据结构。
3. 中断的应用
3.1 中断常用API
对于RTA-OS,在StartOS()后默认所有中断都打开,实际使用中,一般常用API为使能或禁用中断,挂起、恢复中断,可以调用如下API来启用或禁用中断:
DisableAllInterrupts():禁用所有中断
EnableAllInterrupts():使能所有中断
SuspendAllInterrupts() :挂起所有中断
ResumeAllInterrupts():恢复所有中断
SuspendOSInterrupts() :挂起OS级别中断
ResumeOSInterrupts():恢复OS级别中断
以上API在实际使用中,需注意:
1) DisableAllInterrupts() and EnableAllInterrupts()在硬件层面启用或禁用中断,这两个API不能嵌套;
在DisableAllInterrupts()后必须再调用EnableAllInterrupts();
2) SuspendAllInterrupts() and ResumeAllInterrupts(),挂起及恢复所有中断,可以被嵌套;
3) SuspendOSInterrupts() and ResumeOSInterrupts(),可以嵌套使用;
4)Suspend与Resume需要成对出现,Resume不要比Suspend多;
5) 一类中断在关闭期间,不可以调用OS的API;
6) 如果2类ISR将中断级别提高到OS级别以上,并调用DisableAllInterrupts( ),则它可能不会进行任何其他RTA-OS API调用,但用于恢复中断优先级的EnableAllInterrupts( )调用除外。执行ISR时,不允许将中断优先级降低到初始级别以下。
3.2 一/二类中断的处理
3.2.1一类中断的处理
用户必须确保一类ISR输入功能的名称与用户在配置期间为ISR指定的名称相同。
对于一类ISR,在定义输入函数时,通常必须使用编译器特定的关键字,RTA-OS提供了一个名为CAT1_ISR的宏,该宏可扩展为编译器工具链的正确指令,用户应使用该指令将函数标记为一类ISR。
3.2.2 二类中断的处理
二类中断在RTA-OS控制下执行,但不得在2类ISR中放置“中断返回”命令,中断返回由RTA-OS处理。当二类中断需要执行时,由RTA-OS调用中断的入口函数,二类中断的入口函数如下:
#includeISR(isr_identifier){ /* Handler body. */ }
3.3 中断解除
当硬件检测到中断时,它通常会设置一个挂起位,告诉中断控制器中断已经发生。然后,中断控制器将通过中断向量表跳转到处理程序,挂起位的处理取决于目标,但有两个基本方式:
1)中断处理后(即中断处理程序的分支发生时),挂起位自动清除。当处理程序退出时,如果在处理当前中断时中断变为挂起状态,它将自动重新触发。
2)挂起位必须由中断处理程序中的用户代码手动清除。中断处理程序的主体,无论是一类还是二类都需要包含清除挂起位的代码,并向硬件发送中断已被处理的信号。
3.4 中断实际配置
RTA-OS使用的是静态配置,项目实际开发中,需要OS开发人员在OS模块开始配置前对各模块(Adc、Pwm、Gpt等)的中断需求进行分析,如一类/二类中断?中断优先级?回调函数名称?等,OS开发人员还需要对中断优先级进行评估,是否会影响系统中其他模块工作。
此外,RTA-OS使用指定的向量为中断生成向量表条目。与中断优先级一样,中断向量配置也是MCU特有(不同MCU,对应的向量表不同)的,因此在配置中断向量之前需要特别注意MCU选择。
3.5 更高效的中断处理方式
每个中断处理程序将在代码执行期间阻止所有优先级相同或较低的中断。在编写中断处理程序时,最好将处理程序尽可能短。长时间运行的处理程序会为低优先级中断的服务增加额外的延迟。
使用中如果需要在中断中处理较多的代码,可以采用:将代码写到Task中,再通过中断来激活Task,这样低优先级的任务可以打断该Task从而减少延迟,示例代码如下:
#includeISR(EfficientHandler) { ActivateTask(Task1); } TASK(Task1) { /* Long handler code. */ TerminateTask(); }
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !