//----------------------------------------------------------------------
//1.OSSemPend()函数
void OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *perr)
{
INT8U pend_stat;
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr = 0;
#endif
#if OS_ARG_CHK_EN > 0
if (perr == (INT8U *)0) {
return;
}
if (pevent == (OS_EVENT *)0) {
*perr = OS_ERR_PEVENT_NULL;
return;
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {
//确保该event控制块是Sem类型
*perr = OS_ERR_EVENT_TYPE;
return;
}
if (OSIntNesting > 0) {
//ISR中,不能使用OSSemPend()
*perr = OS_ERR_PEND_ISR;
return;
}
if (OSLockNesting > 0) {
//μCOS/II v2.85内核已经被强制锁住
*perr = OS_ERR_PEND_LOCKED;
return;
}
//非法的统统不是,信号正常,所以有必要进一步处理
OS_ENTER_CRITICAL();
if (pevent->OSEventCnt > 0) {
//程序的其他地方已经触发了事件,异或在初始化时设定了n,如:OSSemCreate(2);
//所以该task无需悬停,直接获得事件的使用权
pevent->OSEventCnt--;
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
return;
}
//当前还没有任何事件发生,所以本task需要悬停,让出cpu[gliethttp]
OSTCBCur->OSTCBStat |= OS_STAT_SEM;//是sem事件让本task进入悬停等待的
OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;//假定不是超时,为正常收到信号
//超时,如果timeout=0,那么,本task将一直悬停,仅仅当收到事件触发信号后才重新进入调度队列
OSTCBCur->OSTCBDly = timeout;
//OS_EventTaskWait()函数实现的功能:
//把本task从就绪控制矩阵中摘下,放到pevent事件专有的进程事件控制矩阵表中.
OS_EventTaskWait(pevent);
OS_EXIT_CRITICAL();
//因为本task正在运行,所以本task现在的优先级最高,现在本task已经将自己从就绪控制矩阵--调度器(x,y)矩形阵列中
//把自己摘掉,所以调度函数OS_Sched()一定会切换到另一个task中执行新task的代码[gliethttp]
OS_Sched();//具体参见《浅析μC/OS-II v2.85内核调度函数》
//2007-09-09 gliethttp
//可能因为OSSemPend()中指定的timeout已经超时
//[由OSTimeTick()函数把本task重新置入了就绪控制矩阵,具体参考《浅析μC/OS-II v2.85内核OSTimeDly()函数工作原理》],
//又或者确实在应用程序的某个地方调用了OSSemPost(),以下代码将具体解析是有什么引起的:1.超时,2.收到正常信号
OS_ENTER_CRITICAL()
//1.OSSemPend()函数
void OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *perr)
{
INT8U pend_stat;
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr = 0;
#endif
#if OS_ARG_CHK_EN > 0
if (perr == (INT8U *)0) {
return;
}
if (pevent == (OS_EVENT *)0) {
*perr = OS_ERR_PEVENT_NULL;
return;
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {
//确保该event控制块是Sem类型
*perr = OS_ERR_EVENT_TYPE;
return;
}
if (OSIntNesting > 0) {
//ISR中,不能使用OSSemPend()
*perr = OS_ERR_PEND_ISR;
return;
}
if (OSLockNesting > 0) {
//μCOS/II v2.85内核已经被强制锁住
*perr = OS_ERR_PEND_LOCKED;
return;
}
//非法的统统不是,信号正常,所以有必要进一步处理
OS_ENTER_CRITICAL();
if (pevent->OSEventCnt > 0) {
//程序的其他地方已经触发了事件,异或在初始化时设定了n,如:OSSemCreate(2);
//所以该task无需悬停,直接获得事件的使用权
pevent->OSEventCnt--;
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
return;
}
//当前还没有任何事件发生,所以本task需要悬停,让出cpu[gliethttp]
OSTCBCur->OSTCBStat |= OS_STAT_SEM;//是sem事件让本task进入悬停等待的
OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;//假定不是超时,为正常收到信号
//超时,如果timeout=0,那么,本task将一直悬停,仅仅当收到事件触发信号后才重新进入调度队列
OSTCBCur->OSTCBDly = timeout;
//OS_EventTaskWait()函数实现的功能:
//把本task从就绪控制矩阵中摘下,放到pevent事件专有的进程事件控制矩阵表中.
OS_EventTaskWait(pevent);
OS_EXIT_CRITICAL();
//因为本task正在运行,所以本task现在的优先级最高,现在本task已经将自己从就绪控制矩阵--调度器(x,y)矩形阵列中
//把自己摘掉,所以调度函数OS_Sched()一定会切换到另一个task中执行新task的代码[gliethttp]
OS_Sched();//具体参见《浅析μC/OS-II v2.85内核调度函数》
//2007-09-09 gliethttp
//可能因为OSSemPend()中指定的timeout已经超时
//[由OSTimeTick()函数把本task重新置入了就绪控制矩阵,具体参考《浅析μC/OS-II v2.85内核OSTimeDly()函数工作原理》],
//又或者确实在应用程序的某个地方调用了OSSemPost(),以下代码将具体解析是有什么引起的:1.超时,2.收到正常信号
OS_ENTER_CRITICAL()