ucos 任务调度与中断的关系
来源:互联网 发布:微信裂变源码 编辑:程序博客网 时间:2024/06/05 14:37
转载自:http://blog.csdn.net/alliswall1/article/details/49701905
在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;#endifif (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()实现中断任务切换的问题,也解决了上面提出的疑问
对于文章首部分提出的问题,如果中断中没有调用操作系统服务函数(如发送信号量之类的函数),中断应该直接返回被中断的任务代码,而不应该是就绪的最高优先级的任务。
void OSIntEnter (void){ if (OSRunning == OS_TRUE) { if (OSIntNesting < 255u) { OSIntNesting++; /* Increment ISR nesting level */ } }}
这个函数执行使变量OSIntNesting自增1,是有作用的。
比如你错误的在中断中调用了OSFlagPend函数,如果这个变量不为0,那么说明此时是在中断里面,
直接返回OS_ERR_PEND_ISR,否则有可能引起程序卡在中断里出不来,因为PEND会导致挂起,一直等待!
而
void OSIntExit (void){#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0;#endif if (OSRunning == OS_TRUE) { OS_ENTER_CRITICAL(); if (OSIntNesting > 0) { /* Prevent OSIntNesting from wrapping */ OSIntNesting--; } if (OSIntNesting == 0) { /* Reschedule only if all ISRs complete ... */ if (OSLockNesting == 0) { /* ... and not locked. */ OS_SchedNew(); if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */ OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];#if OS_TASK_PROFILE_EN > 0 OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */#endif OSCtxSwCtr++; /* Keep track of the number of ctx switches */ OSIntCtxSw(); /* Perform interrupt level ctx switch */ } } } OS_EXIT_CRITICAL(); }
这个函数会判断此OSIntNesting是否已经为0,如果为0,会发生任务调度,如果不为0,那么退出一层中断,
主要是用于在多个中断嵌套的时候防止中断还没结束,就执行任务调度!!
- ucos 任务调度与中断的关系
- ucos的任务调度
- ucos的任务调度
- ucos的任务调度原理
- ucos-ii的任务调度
- 中断与异常的区别,以及他们与任务调度的关系
- 【djyos与uCOS】uCOS 不支持同优先级任务的调度,djyos可以
- VxWorks任务调度与中断
- ucos-ii的任务调度机制
- STM32F207+uCOS II 任务调度的问题
- uCOS-II的任务调度和时钟
- ucos ii任务调度的粗糙认识
- UCOS II的任务调度中的表格
- ucos-ii 任务调度
- UCOS任务调度算法
- ucos中的任务调度
- ucos任务调度
- ucos任务调度
- struts2_day04_08_自定义拦截器介绍
- JavaWeb中路径的写法
- ThreadLocal
- 导入数据到Hive表中的方式
- 【Scikit-Learn 中文文档】数据集加载工具
- ucos 任务调度与中断的关系
- 网络堆栈配置工具
- JavaScript知识点(JSON)
- Python小说爬虫
- 排序算法
- opengl 入门教程
- GitHub的注册与安装
- 线程模型
- oracle表空间创建与数据库导入导出