关于ucosII中断中任务调度
2015-11-07 15:36
375 查看
在ucos的中断函数中是每次写中断函数都需要OSIntEnter()和OSIntExit()
用来判断中断嵌套层数和进行任务调度,有些情况是这样的,例如有的书上的程序中有RTC中断服务函数,但是并没有调用操作系统的进入中断服务函数OSIntEnter()和退出中断服务函数OSIntExit(),
解释是因为在RTC中断服务函数中没有调用任何操作系统的服务函数(如发送信号量之类的函数),故不需要操作系统干预
下面就上述解释,以源码为依据进行阐述个人理解
void OSIntEnter (void)
{
if (OSRunning == OS_TRUE)
{
if (OSIntNesting < 255u)
{
OSIntNesting++;//对OSIntNesting变量进行了加1操作
}
}
}
注释部分代码对全局变量OSIntNesting进行了加1操作
INT8U OSSemPost (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr = 0;
#endif
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) {
return (OS_ERR_PEVENT_NULL);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {
return (OS_ERR_EVENT_TYPE);
}
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0) {
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM);
OS_EXIT_CRITICAL();
OS_Sched(); //进行了调度
return (OS_NO_ERR);
}
if (pevent->OSEventCnt < 65535u) {
pevent->OSEventCnt++;
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
OS_EXIT_CRITICAL();
return (OS_SEM_OVF);
}
而OSSempost函数而言,对照其源码发现,当有任务对OSSempost()的event进行等待,则会使高优先级的任务处于就绪状态,并调用OSSched()对任务进行调度,如上边代码的注释部分
void OS_Sched (void)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
INT8U y;
OS_ENTER_CRITICAL();
if ((OSIntNesting == 0) && (OSLockNesting == 0)) {
//如果函数不是在中断服务子程序中调用的,且调度允许的,则任务调度函数将找出进入就绪态的
//最高优先级任务,进入就绪态的任务在就绪表中OSRdyTbl[]中相应位置位。
y = OSUnMapTbl[OSRdyGrp];
*/
OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
if (OSPrioHighRdy != OSPrioCur) {
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
OSCtxSwCtr++;
OS_TASK_SW();
}
}
OS_EXIT_CRITICAL();
}
对照源码注释部分可见,如果函数不是中断服务程序中调用并且调度是允许的,才会使高优先级的任务就绪, 用OS_TASK_SW();完成恢复高优先级任务的运行,假设调用OSSempos()的函数是在中断中的话,由于OSIntEnter
(void)函数对OSIntNesting进行加1操作,这里就不会进行任务切换
那问题就来了,必须有个函数能够实现在中断结束后任务切换的功能呀!!!!!!!
下面分析OSIntExit()函数
void OSIntExit (void)
{
#if OS_CRITICAL_METHOD == 3;
OS_CPU_SR cpu_sr;
#endif
if (OSRunning == TRUE) {
OS_ENTER_CRITICAL();
if (OSIntNesting > 0){
OSIntNesting--;
}
if ((OSIntNesting == 0) &&(OSLockNesting == 0)) {
OSIntExitY = OSUnMapTbl[OSRdyGrp];
OSPrioHighRdy = (INT8U)((OSIntExitY<< 3) + UnMapTbl[OSRdyTbl[OSIntExitY]]);
if (OSPrioHighRdy != OSPrioCur){
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
OSCtxSwCtr++;
OSIntCtxSw(); //调用了切换函数
}
}
OS_EXIT_CRITICAL();
}
}
注释部分函数代码调用OSIntCtxSw()实现中断任务切换的问题,也解决了上面提出的疑问
对于文章首部分提出的问题,如果中断中没有调用操作系统服务函数(如发送信号量之类的函数),中断应该直接返回被中断的任务代码,而不应该是就绪的最高优先级的任务。
相关文章推荐
- 自定义视图
- 显示和隐藏动作栏(Action Bar)
- TCP/IP基础知识
- libevent代码阅读(12)——event_base中的一些事件处理器容器
- JNI中如何在C++文件中调用java中的对象,举例说明
- C语言学习笔记0
- Android开发中用于替代Enum的@IntDef的使用
- shell设置系统环境变量的问题
- 语音简介
- 典型用户和场景
- 方格取数(2)(最大点权独立集)
- java 抽象类
- JUnite4总结
- 深入透析Android事件分发机制
- 管理员账户遇到“操作需要管理员权限”解决方法
- [笔记] Convex Optimization 2015.10.21
- Windows下Mysql解压缩版配置安装与卸载
- 【回顾整理】就是实现弹出登录框并且检验输入值
- C++中,指针数组和数组指针
- Delphi 原生ADO(二)