嵌入式实时操作系统uC/os-II(九)-任务中断

  • uC/OS-II的中断
    1. 中断的定义:任务在运行过程中,应内部或外部异步事件的请求中止当前任务,而去处理异步事件所要的任务过程叫做中断。
    2. 中断服务子程序:应中断请求而运行的程序。
    3. 中断向量:中断服务子程序的入口地址。
    4. uC/OS-II响应中断的过程:系统接收到中断请求后,如果这时CPU处于中断允许状态(即中断是开放的),系统就会中止正在运行的当前任务,而按照中断向量的指向转而去运行中断服务子程序;当中断服务子程序的运行结束后,系统将会根据情况返回到被中止的任务继续运行,或者转向运行另一个具有更高优先级别的就绪任务。

注意:对于可剥夺的uC/OS-II内核来说,中断服务子程序运行结束后,系统将会根据情况进行一次任务调度去运行优先级别最高的就绪任务,而并不一定要继续运行被中断的任务

         uC/OS-II系统运行允许中断嵌套,即高优先级的中断源的中断请求可以中断低优先级别的中断服务程序的运行。系统通过OSIntNesting记录中断嵌套层数。

         uC/OS-II中断响应的过程示意图如图3-1所示。

                                                   嵌入式实时操作系统uC/os-II(九)-任务中断

                                                                                                    图3-1 中断响应过程

uC/OS-II的中断服务程序,要用到两个重要的函数OSIntEnter()OSIntExit().

  1. 函数OSIntEnter()

函数OSIntEnte()的作用就是把全局变量OSIntNesting1,从而用它来记录中断嵌套的层数。源码如下:

void OSIntEnter()

{

         if(OSRunning == TRUE)

          {

                 if(OSIntNesting  <255)

                 {

                          OSIntNesting++;     //中断嵌套层数计数器加1

                  }

             }

}

  1. 函数OSIntExit()

         函数OSIntExit()的流程图如图3-2所示。

                                                     嵌入式实时操作系统uC/os-II(九)-任务中断

                                                                                     图3-2 函数OSIntExit()的流程图

从图3-2中可以看到,这个函数在中断嵌套层数计数器为0,调度器未被锁定且从任务就绪表中查找到的最高级别就绪任务又不是被中断任务的条件下将要进行任务切换,否则就返回被中断的服务子程序。

void  OSIntExit (void)

{

#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */

             OS_CPU_SR  cpu_sr = 0;

#endif

    if (OSRunning == TRUE) {

        OS_ENTER_CRITICAL();

        if (OSIntNesting > 0) {  /* Prevent OSIntNesting from wrapping       */

            OSIntNesting--;

        }

        if (OSIntNesting == 0) {   /* Reschedule only if all ISRs complete ... */

            if (OSLockNesting == 0) {    /*调度器未上锁. */

                OS_SchedNew();              /*获取最高优先级的prio. */

                if (OSPrioHighRdy != OSPrioCur) { /*不是被中断任务*/

                    OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy];

                    OSCtxSwCtr++;     /*上下文切换次数加1  */

                    OSIntCtxSw();      /* 中断级任务切换*/

                }

            }

        }

        OS_EXIT_CRITICAL();

    }

}

  • 中断服务子程序的流程图如图3-3所示。

                                                                              嵌入式实时操作系统uC/os-II(九)-任务中断

                                                                                 图3-3 中断服务子程序的流程图

  • 中断级任务切换函数OSIntCtxSw()

从图3-2中可知,完成这个切换的函数OSIntCtxSw就叫做中断级任务切换函数。其示意性代码如下:

void OSIntCtxSw()

{

    OSTCBCur = OSTCBHighRdy;                     //任务控制块的切换

    OSPrioCur = OSPrioHighRdy;

    SP = (OS_EMU_STK*) OSTCBHighRdy->OSTCBStkPtr;     //使SP指向待运行任务的堆栈

        

    RETI     //中断返回,使PC指向待运行任务

     }

  • 临界段

基本概念:在uC/OS-II中,那些不希望被中断的代码叫做临界段。不要在临界段中调用uC/OS-II提供的功能函数,以免系统崩溃。

  • OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()

其示意性1代码如下:

#define OS_ENTER_CRITICAL()       \

         asm(“DI”)

#define OS_EXIT_CRITICAL()

         asm (“EI”)

示意性2代码如下:

#define OS_ENTER_CRITICAL()                \

         asm (“PUSH PSW”)

         asm (“DI”)

#define OS_EXIT_CRITICAL()

         asm (“POP PSW”)