uC/OS-II中的中断(转)

中断是指在程序运行过程中,应内部或外部异步事件的请求中止当前任务,而去处理异步事件所要求的任务的过程。

  中断服务函数(ISR)是应中断请求而运行的程序。

  中断向量就是中断服务函数(ISR)的入口地址,即存储中断服务函数的内存地址的首单元。

  在ucos-II中,如果任务在运行中,系统接收到中断请求,并且这时中断响应是打开的,那么系统就会中止正在运行的程序,再按照中断向量的指向转而去执行中断服务程序。中断程序运行完后,系统会引发一次系统调度(OSIntExt()),转而去执行当前优先级别最高的就绪任(不一定是接着运行被中断的任务)。

但是,螳螂捕蝉,黄雀在后。中断服务函数本身也能被其他更高优先级的中断源发出的中断请求中断,这叫做中断嵌套。ucos-II中定义了一个用于记录中断嵌套层数的全局变量OSIntNesting。每当响应一个中断请求的时候,OSIntNesting+1。

  细心的读者可能会发现,上文中提到,在中断服务程序结束后,会引发一次系统调度,而负责这次调度的函数并不是我们在ucos-II的任务一章中提到的OSSched()。下面就来解释一下为什么会出现这种情况。因为ucos-II中定义了两个任务调度器,一个是任务级的调度器(OSSched()),另一个就是中断级的调度器(OSIntExt())。我们再来回忆一下任务级的调度器(OSSched())的工作过程。首先,其要确定任务调度器没有被上锁(OSLockNesting == 0)并且任务的没有进入服务函数(OSIntNesting == 0),当满足的情况下,才找出优先级最高的就绪任务,如果它不是当前任务的话,那么将其任务控制块指针给指向当前最高优先级就绪任务的指针(OSTCBHighRdy),接着调用任务级任务切换函数(OS_TASK_SW())进行任务切换。那么退出中断服务程序(OSIntExit())的时候,我们调用中断级的任务切换函数(OSIntCtxSw())来进行任务的切换。退出中断函数和任务级的任务调度器的功能差不多相同,不同点只是退出中断函数使OSIntNesting先减1,然后再判断任务调度器没有被上锁(OSLockNesting == 0)并且任务的没有进入服务函数(OSIntNesting == 0),其次是调用的任务切换函数不同,一个是任务级的切换函数   OS_TASK_SW(),而另一个是中断级的任务切换函数OSIntCtxSw()。

  OSIntExt的作用?OS_TASK_SW()和OSIntCtxSw()的区别?难道仅仅是因为OSIntCtxSw()调用了RETI(中断返回指令,是PC指向待运行的函数)?其恢复断点数据的过程是否相同?

  在编写中断服务程序时,要用到两个重要的函数OSIntEnter()和OSIntExit()。OSIntEnter()经常在中断服务程序保护被中断任务的中断数据之后,运行用户服务代码之前调用。其作用很简单,就是给全局变量OSIntNesting+1。而OSIntExit()的功能在上面已经说过了,就是进行任务的切换。

有的时候我们在执行某些代码的时候,不希望被中断函数打断。那么我们是否可以让中断在只有被允许的情况下才能被响应呢?很幸运,ucos-II给我们提供了两个这样的宏,宏OS_ENTER_CRITICAL()用来关闭中断。宏OS_EXIT_CRITICAL()用开打开中断。而在OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()中间的部分,我们称其为临界段。这样,当我们执行一些不希望被打断的代码时候,我们可以先关闭中断,当代码执行完毕后,再打开中断。

  ucos-II中的中断大体上就是如上的过程,当然,随着以后的深入。也会有更加详细的描述。

时间: 2024-10-14 22:42:18

uC/OS-II中的中断(转)的相关文章

uC/OS II 任务切换原理

今天学习了uC/OS II的任务切换,知道要实现任务的切换,要将原先任务的寄存器压入任务堆栈,再将新任务中任务堆栈的寄存器内容弹出到CPU的寄存器,其中的CS.IP寄存器没有出栈和入栈指令,所以只能引发一次中断,自动将CS.IP寄存器压入堆栈,再利用中断返回,将新任务的任务断点指针弹出到CPU的CS.IP寄存器中,实现任务切换.虽然明白个大概,但是其中的细节却有点模糊,为什么调用IRET中断返回指令后,弹入CPU的CS.IP寄存器的断点指针是新任务的断点指针,而不是当前任务的,UCOS II是如

uC/OS II 函数说明 之–OSTaskCreate()与OSTaskCreateExt()

1. OSTaskCreate()    OSTaskCreate()建立一个新任务,能够在多任务环境启动之前,或者执行任务中建立任务.注意,ISR中禁止建立任务,一个任务必须为无限循环结构.        源码例如以下: #if OS_TASK_CREATE_EN > 0                    /* 条件编译,是否同意任务的创建               */INT8U  OSTaskCreate (void (*task)(void *pd), /* 函数指针,void *

【原创】uC/OS 中LES BX,DWORD PTR DS:_OSTCBCur的作用及原理

1 LES BX, DWORD PTR DS:_OSTCBCur ;取得任务堆栈指针ES:[BX] 2 MOV ES:[BX+2], SS ;将当前SS(栈的基地址)寄存器值存放至当前任务堆栈的2,3内存单元 3 MOV ES:[BX+0], SP ;将当前SP(栈顶的偏移量)存放至当前任务堆栈的0,1内存单元 首先讲讲LES指针的功能:LES的功能有点像C语言的*. LES REG,MEM 参与操作的寄存器不仅有REG,还有ES寄存器.在16位系统中,寄存器为16位,很显然,MEM所指向的内存

uC/OS 的任务调度解析 (转)

uC/OS 的任务调度解析 1.任务调度器启动之后(初始化,主要是TCB的初始化),就可以创建任务,开始任务调度了,实际上第一个任务准确的说不是进行任务切换,而是进行启动当前最高优先级任务.uC/OS使用的是OSStartHighRdy OSStartHighRdy LDR R0, =NVIC_SYSPRI14 ; Set the PendSV exception priority LDR R1, =NVIC_PENDSV_PRI STRB R1, [R0] MOVS R0, #0 ; Set

关于uC/OS的简单学习(转)

1.微内核 与Linux的首要区别是,它是一个微内核,内核所实现的功能非常简单,主要包括: 一些通用函数,如TaskCreate(),OSMutexPend(),OSQPost()等. 中断处理函数,且处理函数非常简单,一般仅是向相应的Task发消息,唤醒该Task来处理中断任务. 一个高效的调度器,这是OS的灵魂,实现多任务间的调度(包括调度点.调度算法.任务切换等). 好像就这么点,呵呵.它不支持内存保护,即不像Linux那样分用户空间.内核空间.如一个Task运行时,可调用内核函数Task

uc/os iii移植到STM32F4---IAR开发环境

也许是先入为主的原因,时钟用不惯Keil环境,大多数的教程都是拿keil写的,尝试将官方的uc/os iii 移植到IAR环境. 1.首先尝试从官网上下载的官方移植的代码,编译通过,但是执行会报堆栈溢出警告(为何keil没有报堆栈溢出??),网上有人说不用理会,但是实际使用时发生了错误(定义的常量数组值被改变,怀疑是堆栈溢出导致),发现使用的IAR版本不能完美支持使用的STM32芯片,换用高版本测试..(高版本正确,与低版本对芯片的支持有关) 2.开始时虽然会堆栈溢出,但是能够进入异常中断,进入

uc os相关的C语言知识点1-函数指针

开始读uc os的代码了,发现很多C语言的东西,之前没搞懂的,慢慢积累. 就象某一数据变量的内存地址可以存储在相应的指针变量中一样,函数的首地址也以存储在某个函数指针变量里的.这样,我就可以通过这个函数指针变量来调用所指向的函数了. 形式1:返回类型(*函数名)(参数表) ,例子如下: #include<stdio.h> void (*funp)(int); //定义一个函数指针,注意函数的返回类型和参数类型和指针的一致,才可以用. void print(int n); //函数申明 int

Mac OS X中,有三种方式来实现启动项的配置

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: center; font: 22.0px "Times New Roman"; color: #000000 } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px "Times New Roman"; color: #000000 } p.p3 { margin: 0.0px 0.0px 0.0px 0.0p

S5PV210-arm裸机-异常中的中断实现过程

210中的异常中的中断实现过程: 首先异常分为很多种,异常中包含了中断异常,有一个东西叫做异常向量表,在异常向量表中有很多相应异常的的地址.异常向量表中的所有异常中断的地址是不会变化的.地址都是固定的,但这些地址都是一个基于基地址的一个地址.不同的CPU中,基地址是不同的. 在210中,CPU内部给了一个发生异常时的异常向量的基地址,查阅官方资料知道,这个基地址为0XD0037400,所以我们需要自己把异常向量表中的地址加在210给的发生异常时的异常向量的基地址上.比如:reset(复位异常)在