ucos在M3中的中断嵌套机制

M3的中断控制器特性

可嵌套中断支持的作用范围很广,覆盖了所有的外部中断和绝大多数系统异常。外在表现是,这些异常都可以被赋予不同的优先级。当前优先级被存储在xPSR的专用字段中。当一个异常发生时,硬件会自动比较该异常的优先级是否比当前的异常优先级更高。如果发现来了更高优先级的异常,处理器就会中断当前的中断服务例程(或者是普通程序),而服务新来的异常——即立即抢占。 
在CM3内核以及NVIC的深处,就已内建了对中断嵌套的全力支持,根本无需使用汇编去写封皮代码(wrapper code)。事实上,我们要做的就只是为每个中断适当地建立优先级,不用再操心别的。表现在:

第一、 NVIC和CM3处理器会根据优先级的设置来控制抢占与嵌套行为。因此,在某个异常正在响应时,所有优先级不高于它的异常都不能抢占之,而且它自己也不能抢占自己。

第二、 有了自动入栈和出栈,就不用担心在中断发生嵌套时,会使寄存器的数据损毁,从而可以放心地执行服务例程。因为所有服务例程都只使用主堆栈,因此对于中断嵌套最关键的就是计算主堆栈的容量。每发生一次中断嵌套至少需要八个字,且何时嵌套,嵌套多少级不可预知。

另一方面,是相同的异常是不允许重入的。因为每个异常都有自己的优先级,并且在异常处理期间,同级或低优先级的异常是要阻塞的。因此对于同一个异常,只有在上次实例的服务例程执行完毕后,方可继续响应新的请求。

ucos如何管理中断嵌套

ucos对于中断嵌套,提供了两个函数OSIntEnter ()和OSIntExit () 
2.1 OSIntEnter ()

void  OSIntEnter (void)
{
    if (OSRunning == OS_TRUE) {
        if (OSIntNesting < 255u) {
            OSIntNesting++;                      
        }
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

OSIntNesting表示中断嵌套的层数,该函数在ISR开始调用以使ucos跟踪中断嵌套的层数。 
调用OSIntEnter应注意的地方 
1、该函数调用时,应关闭所有中断。 
2、应用程序也可以不使用该函数而直接操作OSIntNesting,但还是得满足1 
3、OSIntEnter和OSIntExit需成对使用 
4、ucos支持255级中断嵌套

2.2 OSIntExit()

void  OSIntExit (void)
{
#if OS_CRITICAL_METHOD == 3u                       
    OS_CPU_SR  cpu_sr = 0u;
#endif
    if (OSRunning == OS_TRUE) {
        OS_ENTER_CRITICAL();
        if (OSIntNesting > 0u) {                           
            OSIntNesting--;
        }
        if (OSIntNesting == 0u) {                         
            if (OSLockNesting == 0u) {                   
                OS_SchedNew();
                OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
                if (OSPrioHighRdy != OSPrioCur) {          
#if OS_TASK_PROFILE_EN > 0u
                    OSTCBHighRdy->OSTCBCtxSwCtr++;     
#endif
                    OSCtxSwCtr++;                       
                    OSIntCtxSw();                         
                }
            }
        }
        OS_EXIT_CRITICAL();
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

该函数主要是用来告知ucos中断ISR服务已经完成。当最后一级中断ISR完成后,ucos将调用调度器进行任务切换。其中,还有一点就是当调度器被锁的时候是不能完成调度的。

为什么不可在OSIntNesting 大于 0时切换任务?

情况1 
假设系统有任务A、B 优先级B>A。任务B在等待信号量sem,系统正在运行任务A。在任务A运行过程成发生先后发生中断INT1,INT2。其中INT2优先级大于INT1。在INT2的ISR中释放了B任务等待的信号量sem。

假设在INT2中使用调度器进行任务切换会发生什么呢? 
在任务A发生中断时,M3自动入栈了R0-R3、R12,SP,LR和xSPR。对于其他寄存器并没有做处理,即使在INT1中使用了除上述之外的寄存器,编译器也只能将它们压入到MSP。如果在INT2的ISR中进行任务调度、任务B可以运行,当再次进行任务调度调度A时问题就出现了。因为任务A的R4-R11没有入栈。调度器根本无法正确获得任务的PC指针,程序只可能跑飞。

情况2 
假设系统有任务A、B 优先级B>A。任务B在等待信号量sem,系统正在运行任务A。在任务A运行过程成发生先后发生中断INT2。在INT2的ISR中又发生了INT1,当INT1优先级小于INT2,INT1被挂起。INT2的ISR中释放了B任务等待的信号量sem。

假设在INT2中使用调度器进行任务切换会发生什么呢? 
系统回到任务B之后,INT1该怎么办了?或者在OS_SW()执行到最后BX LR后,又要去响应INT1?这个值得讨论。

总结

1、中断嵌套:中断嵌套只能发生在中断服务子程序中,在中断服务子程序运行过程中, 当有更高优先级的中断发生且此时中断是打开的,则将发生中断嵌套 。

2、中断服务程序通知任务做事是通过事件使任务处于就绪状态,而并非立即进行任务切换,因为它们都是调OS_Sched(),而函数只能在所有中断服务程序结束运行后才进行切换任务所以任何任务切换都不能发生在ISR中,而必须等到所有ISR 结束运行后,在OSIntExit()中进行.所以任何时刻uCOSII只能有一个任务处于运行态.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值