OSIntCtxSw()
来源:互联网 发布:中兴毛网络e灯正常亮吗 编辑:程序博客网 时间:2024/06/14 00:50
在µC/OS-II中,由于中断的产生可能会引起任务切换,在中断服务程序的最后会调用OSIntExit()函数检查任务就绪状态,如果需要进行任务切换,将调用OSIntCtxSw()。所以OSIntCtxSw()又称为中断级的任务切换函数。由于在调用OSIntCtxSw()之前已经发生了中断,OSIntCtxSw()将默认CPU寄存器已经保存在被中断任务的堆栈中了。
程序清单L9.5给出的代码大部分与OSCtxSw()的代码相同,不同之处是,第一,由于中断已经发生,此处不需要再保存CPU寄存器(没有PUSHA, PUSH ES, 或PUSH DS);第二,OSIntCtxSw()需要调整堆栈指针,去掉堆栈中一些不需要的内容,以使堆栈中只包含任务的运行环境。图F9.5可以帮助读者理解这一过程。程序清单L 9.5OSIntCtxSw()._OSIntCtxSw PROC FAR; ; Ignore calls to OSIntExit and OSIntCtxSw; ADD SP,8 ; (Uncomment if OS_CRITICAL_METHOD is 1, see OS_CPU.H)(1) ADD SP,10 ; (Uncomment if OS_CRITICAL_METHOD is 2, see OS_CPU.H); MOV AX, SEG _OSTCBCur ; 载入DS MOV DS, AX ; LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP(2) MOV ES:[BX+2], SS MOV ES:[BX+0], SP ; CALL FAR PTR _OSTaskSwHook(3); MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy(4) MOV DX, WORD PTR DS:_OSTCBHighRdy MOV WORD PTR DS:_OSTCBCur+2, AX MOV WORD PTR DS:_OSTCBCur, DX ; MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy(5) MOV BYTE PTR DS:_OSPrioCur, AL; LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr(6) MOV SS, ES:[BX+2] MOV SP, ES:[BX] ; POP DS ; 载入新任务的CPU环境(7) POP ES (8) POPA (9); IRET ; 返回新任务(10);_OSIntCtxSw ENDP当中断发生后,CPU在完成当前指令后,进入中断处理过程。首先是保存现场,将返回地址压入当前任务堆栈,然后保存状态寄存器的内容。接下来CPU从中断向量处找到中断服务程序的入口地址,运行中断服务程序。在µC/OS-II中,要求用户的中断服务程序在开头保存CPU其他寄存器的内容[图F9.5(1)]。此后,用户必须调用OSIntEnter()或着把全局变量OSIntNesting加1。此时,被中断任务的堆栈中保存了任务的全部运行环境。在中断服务程序中,有可能引起任务就绪状态的改变而需要任务切换,例如调用了OSMboxPost(), OSQPostFront(),OSQPost(),或试图唤醒一个优先级更高的任务(调用OSTaskResume()),还可能调用 OSTimeTick(), OSTimeDlyResume()等等。µC/OS-II要求用户在中断服务程序的末尾调用OSIntExit(),以检查任务就绪状态。在调用OSIntExit()后,返回地址会压入堆栈中[图F9.5(2)]。进入OSIntExit()后,由于要访问临界代码区,首先关闭中断。由于OS_ENTER_CRITICAL()可能有不同的操作(见9.03.02节),状态寄存器SW的内容有可能被压入堆栈[图F9.5(3)]。如果确实要进行任务切换,指针OSTCBHighRdy将指向新的就绪任务的OS_TCB,OSIntExit()会调用OSIntCtxSw()完成任务切换。注意,调用OSIntCtxSw()会在再一次在堆栈中保存返回地址[图F9.5(4)]。在进行任务切换的时候,我们希望堆栈中只保留一次中断发生的任务环境(如图F9.5(1)),而忽略掉由于函数嵌套调用而压入的一系列返回地址(图F9.5(2),(3),(4))。忽略的方法也很简单,只要把堆栈指针加一个固定的值就可以了[图F9.5(5)/程序清单L9.5(1)]。如果用方法2实现OS_ENTER_CRITICAL(),这个固定值是10;如果用方法1,则是8。实际操作中还与编译器以及编译模式有关。例如,有些编译器会为OSIntExit()在堆栈中分配临时变量,这都会影响具体占用堆栈的大小,这一点需要提醒用户注意。一但堆栈指针重新定位后,就被保存到将要被挂起的任务OS_TCB中[图F9.5(6)/程序清单L9.5(2)]。在µC/OS-II中(包括µC/OS),OSIntCtxSw()是唯一一个与编译器相关的函数,也是用户问的最多的。如果您的系统移植后运行一段时间后就会死机,就应该怀疑是OSIntCtxSw()中堆栈指针重新定位的问题。当当前任务的现场保存完毕后,用户定义的对外接口函数OSTaskSwHook()会被调用[程序清单L9.5(3)]。注意到OSTCBCur指向当前任务的OS_TCB,OSTCBHighRdy指向新任务的OS_TCB。在函数OSTaskSwHook()中用户可以访问这两个任务的OS_TCB。如果不用对外接口函数,请在头文件中关闭相应的开关选项,提高任务切换的速度。从对外接口函数OSTaskSwHook()返回后,由于任务的更替,变量OSTCBHighRdy被拷贝到OSTCBCur中[程序清单L9.5(4)],同样,OSPrioHighRdy被拷贝到OSPrioCur中[程序清单L9.5(5)]。此时,OSIntCtxSw()将载入新任务的CPU环境,首先从新任务OS_TCB中取出SS和SP寄存器的值[图F9.5(7)/程序清单L9.5(6)],然后运行POP DS [图F9.5(8)/程序清单L9.5(7)], POP ES [图F9.5(9)/程序清单L9.5(8)], POPA[图F9.5(10)/程序清单L9.5(9)]取出其他寄存器的值,最后用中断返回指令IRET [图F9.5(11)/程序清单L9.5(10)]完成任务切换。需要注意的是在运行OSIntCtxSw()和用户定义的OSTaskSwHook()函数期间,中断是禁止的。
图F 9.5 中断级任务切换时的80x86堆栈结构
阅读全文
0 0
- OSIntCtxSw()
- osintctxsw分析
- §4.3.3.2 OSIntCtxSw的编写
- ucOS-II基于ARM920T的OSIntCtxSw实现分析
- linux上传下载工具_整理
- Python读写文件
- java中的byte有什么作用?
- Google File System(Google分布式文件系统译文)
- 负载均衡
- OSIntCtxSw()
- tf.trainable_variables和tf.all_variables的对比
- Dubbo标签参数详解
- gulp输出的css,js,html格式
- Java学习之I/O中的其他功能流
- PyTorch学习系列(一)——加载数据并生成batch数据
- hdf5文件的创建以及读写
- Certified Scrum Master (CSM)认证考试部分题目分析。
- JSON学习笔记(二)- 对象