uCOSii中断处理过程详解(一)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一. UCOSII的中断过程简介

系统接收到中断请求后,如果CPU处于开中断状态,系统就会中止正在运行的当前任务,而按中断向量的指向去运行中断服务子程序,当中断服务子程序运行完成后,系统会根据具体情况返回到被中止的任务继续运行,或转向另一个中断优先级别更高的就绪任务。

由于UCOS II是可剥夺型的内核,所以中断服务程序结束后,系统会根据实际情况进行一次任务调度,如果有优先级更高的任务,就去执行优先级更高的任务,而不一定要返回被中断了的任务。

二.UCOSII的中断过程的示意图

三.具体中断过程

1.中断到来,如果被CPU识别,CPU将查中断向量表,根据中断向量表,获得中断服务子程序的入口地址。

2.将CPU寄存器的内容压入当前任务的任务堆栈中(依处理器的而定,也可能压入被压入被中断了的任务堆栈中。

3.通知操作系统将进入中断服务子程序。即:调用OSIntEnter()或OSIntNesting直接

加1。

4.If(OSIntNesting==1){OSTCBCur->OSTCBStrPtr=SP;} //如果是第一层中断,则将堆栈指针保存到被中断任务的任务控制块中

5.清中断源,否则在开中断后,这类中断将反复的打入,导致系统崩贵

6.执行用户ISR

7.中断服务完成后,调用OSIntExit().如果没有高优先级的任务被中断服务子程序激活而进入就绪态,那么就执行被中断了的任务,且只占用很短的时间.

8.恢复所有CPU寄存器的值.

9.执行中断返回指令.

四.相关代码

与编译器相关的数据类型:

typedef unsigned char BOOLEAN;

typedef unsigned char INT8U;

typedef unsigned int OS_STK; //堆栈入口宽度为16 位(一) void OSIntEnter (void)的理解

uCOS_II.H中定义:

#ifdef OS_GLOBALS

#define OS_EXT

#else

#define OS_EXT extern

#endif //定义全局宏OS_EXT

#ifndef TRUE

#define TRUE 1

#endif

OS_EXT BOOLEAN OSRunning; //定义外部BOOLEAN类型全局变量,用来指示

//核是否在运行

OS_EXT INT8U OSIntNesting;//定义外部8位无符号整型数全局变量,用来表

//示中断嵌套层数

OS_CORE.C中的OSIntEnter()函数原型:

void OSIntEnter (void)

{

if (OSRunning == TRUE) //如果内核正在运行则进入if

{

if (OSIntNesting < 255) //如果嵌套层数小于255,则可以继//续{

OSIntNesting++; //嵌套层数加1

}

}

}

(二)在中断服务子程序中加if ( OSIntNesting == 1){…}的原因

uCOS_II.H中定义:

typedef struct os_tcb {

OS_STK *OSTCBStkPtr;//声明指向任务堆栈栈顶的16位指针………………

} OS_TCB;//定义名为OS_TCB的结构体数据类型,即任务控制块的数据结构

OS_EXT OS_TCB *OSTCBCur;//声明一个指向任务控制块的全局指针变量

//用于指向当前任务的任务控制块

中断服务程序中添加的代码:

if ( OSIntNesting == 1)

{

OSTCBCur->OSTCBStkPtr = SP; // 如果是第一层中断,则将被中断任务

//的堆栈指针保存在被中断任务的任务

//任务控制块

}

关于uCOS-II的中断服务程序(ISR)中必须加“OSIntNesting == 1”的原因==避免调整堆栈指针.

出现这个问题的根源是当低优先级的任务被中断,当中断完成后由于有高优先级的任务就绪,则必须调度高优先级的任务,原来的低优先级任务继续被中断着,但是此时的低优先级任务的堆栈已经被破坏,已不能被调度程序直接调度了,要想被调度而必须调整堆栈指针。如下图所示的场景:

问题分析:

要想理解加上上面两句的原因,不妨假设有下面场景出现:

void MyTask(void)

{

...

}

该任务在执行过程中被中断打断,下面是它的服务子程序

void MyISR(void)

{

保存现场(PUSHA)

OSIntEnter();

// 此时的堆栈指针是正确的,再往下就不对了,应该在此处保存用户任务堆栈指针

OSIntExit();

恢复现场(POPA)

中断返回

}

OSIntExit(),大体如下:

OSIntExit()

{

OS_ENTER_CRITICAL();

if( OSIntNesting==0 && OSLockNesting == 0 ) { 找到目前系统中就绪表中优先级最的任务

如果不是当前任务,则调度它执行

OSIntCtxSw();

}

OS_EXIT_CRITICAL();

}

综上所述,任务调用链如下:

MyTask --> MyISR -->

①OSIntExit -->

②OS_ENTER_CRITICAL(); ③

OSIntCtxSw(); ④

相关文档
最新文档