本篇介绍以下几个函数:
OSVersion()获得版本号函数、
OS_Dummy()虚拟函数、
OS_EventTaskRdy (OS_EVENT *pevent, void *msg, INT8U msk)使任务进入就绪态的函数、
OS_EventTaskWait (OS_EVENT *pevent)使任务进入等待状态的函数、
OS_EventTaskWaitMulti(OS_EVENT **pevents_wait)使任务进入等待状态的函数(多任务下)、
OSVersion()获得版本号函数:
/*$PAGE*/
/*
*********************************************************************************************************
* GET VERSION
* 获得版本号
* Description: This function is used to return the version number of uC/OS-II. The returned value
* corresponds to uC/OS-II's version number multiplied by 100. In other words, version 2.00
* would be returned as 200.
*这个函数是返回一个uC/OS-II的版本值. 这个返回值乘100是uC/OS-II的版本号.
* Arguments : none
*
* Returns : the version number of uC/OS-II multiplied by 100.
*********************************************************************************************************
*/
INT16U OSVersion(void)
{
return (OS_VERSION);
}
OS_Dummy()虚拟函数:
/*$PAGE*/
/*
*********************************************************************************************************
* DUMMY FUNCTION
* 虚拟函数
* Description: This function doesn't do anything. It is called by OSTaskDel().
*这个函数不做任务工作. 它是随便访问OSTaskDel()函数.
* Arguments : none
*
* Returns : none
*********************************************************************************************************
*/
#if OS_TASK_DEL_EN > 0u
void OS_Dummy(void)
{
}
#endif
OS_EventTaskRdy (OS_EVENT *pevent, void *msg, INT8U msk)使任务进入就绪态的
函数:
/*$PAGE*/
/*
*********************************************************************************************************
* MAKE TASK READY TO RUN BASED ON EVENT OCCURING
* 使一个任务进入就绪态
* Description: This function is called by other uC/OS-II services and is used to ready a task that was
* waiting for an event to occur.
*描述:该功能被其他oc/os-ii服务调用,用来使正在等待事件发生的任务进入就绪态。
* Arguments : pevent is a pointer to the event control block corresponding to the event.
* 参数: --pevent指针指向与事件对应的事件控制块
* pmsg is a pointer to a message. This pointer is used by message oriented services
* such as MAILBOXEs and QUEUEs. The pointer is not used when called by other
* service functions.
* --pmsg指针指向消息,只能面向消息的服务才能使用,例如邮箱和队列。其他的不能调用该函数。
* msk is a mask that is used to clear the status byte of the TCB. For example,
* OSSemPost() will pass OS_STAT_SEM, OSMboxPost() will pass OS_STAT_MBOX etc.
* --msk函数是一个掩码,用来清除TCB的状态字。例如,通过OSSemPost()函数清除OS_STAT_SEM;利用OSMboxPost()函数清除OS_STAT_MBOX。
* pend_stat is used to indicate the readied task's pending status:
* --pend_stat用来表明已准备好的任务的挂起状态。挂起状态有以下两种:
* OS_STAT_PEND_OK Task ready due to a post (or delete), not a timeout or
* an abort.
--挂起结束(正常结束):任务已经准备好进入就绪态。
* OS_STAT_PEND_ABORT Task ready due to an abort.
--取消挂起:任务被取消。
*
* Returns : none
*
* Note : This function is INTERNAL to uC/OS-II and your application should not call it.
这个函数是uC/OS-II内部函数,你不可以在应用程序调用它,调用此函数也应当关闭中断
*********************************************************************************************************
*/
#if (OS_EVENT_EN)
INT8U OS_EventTaskRdy(OS_EVENT *pevent,
void *pmsg,
INT8U msk,
INT8U pend_stat)
{
OS_TCB *ptcb; /*指向TCB列表的指针*/
INT8U y; /*存放字节索引*/
INT8U x; /*存放任务在表中对应的具体位置*/
INT8U prio; /*存放优先级(数字越小,优先级越高)*/
#if OS_LOWEST_PRIO > 63u /*如果最低优先级大于63u(超出了范围)*/
OS_PRIO *ptbl; /*设置一个专门存放超出范围的优先级指针ptb1*/
#endif
#if OS_LOWEST_PRIO <= 63u /*如果最低优先级<=63*/
y = OSUnMapTbl[pevent->OSEventGrp]; /* Find HPT waiting for message首先计算HPT任务在.OSEventTbl[]中的字节索引,其结果是一个从0到OS_LOWEST_PRIO/8+1之间的数 */
x = OSUnMapTbl[pevent->OSEventTbl[y]]; /*判断HPT任务在.OSEventTbl[]中相应位的位置*/
prio = (INT8U)((y << 3u) + x); /* Find priority of task getting the msg 根据以上结果计算出HPT任务的优先级*/
#else /*最低优先级>63*/
if ((pevent->OSEventGrp & 0xFFu) != 0u) /*存在事件控制块所在的组*/
{
y = OSUnMapTbl[pevent->OSEventGrp & 0xFFu]; /*找到事件所在的组*/
}
else
{
y = OSUnMapTbl[(OS_PRIO)(pevent->OSEventGrp >> 8u) & 0xFFu] + 8u;/*没有组,将y置为8(不在组内)*/
}
ptbl = &pevent->OSEventTbl[y]; /*ptb1指针指向上面求出的组的首地址*/
if ((*ptbl & 0xFFu) != 0u) /*如果该指针指向的这一行不为0,即存在有效值*/
{
x = OSUnMapTbl[*ptbl & 0xFFu]; /*得到该任务在表中相应的位置*/
}
else {
x = OSUnMapTbl[(OS_PRIO)(*ptbl >> 8u) & 0xFFu] + 8u;/*为0,将x设为8(不在组内)*/
}
prio = (INT8U)((y << 4u) + x); /* Find priority of task getting the msg找到得到消息的任务的优先级*/
/*因为超过了63,所以此时y占了4位,所以左移4u。上面左移3u是因为y在63内,只占了3位*/
#endif
ptcb = OSTCBPrioTbl[prio]; /* Point to this task's OS_TCB指针指向任务的TCB*/
ptcb->OSTCBDly = 0u; /* Prevent OSTimeTick() from readying task将OSTCBDly清为0*/
/*因为最高优先级任务运行条件已经得到满足,必须停止OSTimeTick()函数对.OSTCBDly域的递减操作*/
#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) || (OS_MBOX_EN > 0u)/*如果生成队列且队列数>0或者生成了邮箱*/
ptcb->OSTCBMsg = pmsg; /* Send message directly to waiting task直接给等待的任务发送消息*/
#else
pmsg = pmsg; /*pmsg不进行变化*//* Prevent compiler warning if not used防止编译警告*/
#endif
ptcb->OSTCBStat &= (INT8U)~msk; /* Clear bit associated with event type清除与事件类型相关的位*/
ptcb->OSTCBStatPend = pend_stat; /* Set pend status of post or abort设置挂起状态*/
/* See if task is ready (could be susp'd)看看任务是否已经准备好了(能否被挂起)*/
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) //已经准备好了,将任务设置为就绪态
{
OSRdyGrp |= ptcb->OSTCBBitY; /* Put task in the ready to run list*/
OSRdyTbl[y] |= ptcb->OSTCBBitX;
}
OS_EventTaskRemove(ptcb, pevent); /* Remove this task from event wait list从事件等待列表中删除任务*/
#if (OS_EVENT_MULTI_EN > 0u) /*如果是多任务*/
if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) /*的确存在多任务*/
{
OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr);/* Remove this task from events' wait lists将该任务从事件的等待列表中移除*/
ptcb->OSTCBEventPtr = (OS_EVENT *)pevent;/* Return event as first multi-pend event read返回读到的第一个多挂起事件*/
}
#endif
return (prio);//返回优先级
}
#endif
流程图为:
关于这个函数中的计算优先级的方法:http://blog.sina.com.cn/s/blog_4a3946360102wlwx.html
计算优先级的方法也显而易见了:就绪列表或事件表中求索引号-》同一个表求相应位的位置-》计算优先级。
这个函数比较费解的,一个是求优先级的方法;一个是查表以及进行的逻辑运算。需要认真研究才可以搞懂。
OS_EventTaskWait (OS_EVENT *pevent)使任务进入等待状态的函数:当某个任务须等待一个事件的发生时,信号量、互斥型信号量、邮箱以及消息队列会通过相应的PEND函数调用本函数,使当前任务从就绪任务表中脱离就绪态,并放到相应的事件控制块ECB的等待任务表中。
/*$PAGE*/
/*2018/2/7
*********************************************************************************************************
* MAKE TASK WAIT FOR EVENT TO OCCUR
* 使一个任务进入等待某事件发生状态
* Description: This function is called by other uC/OS-II services to suspend a task because an event has
* not occurred.
*描述:这个功能被其他uc/os-ii服务调用,当事件没有发生时挂起该任务
* Arguments : pevent is a pointer to the event control block for which the task will be waiting for.
*参数: --pevent是指向事件控制块的指针
* Returns : none
*返回值:无
* Note : This function is INTERNAL to uC/OS-II and your application should not call it.
注释:该功能为内部功能函数,你的应用程序不能调用
*********************************************************************************************************
*/
#if (OS_EVENT_EN) /*如果可以生成事件*/
void OS_EventTaskWait(OS_EVENT *pevent) /*使任务进入等待函数*/
{
INT8U y;
OSTCBCur->OSTCBEventPtr = pevent; /*将指向事件控制块的指针赋给当前任务控制块中指向事件的指针,建立任务与事件控制块ECB之间的链接*/
pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX; /* Put task in waiting list将任务放置在等待列表中*/
pevent->OSEventGrp |= OSTCBCur->OSTCBBitY;
y = OSTCBCur->OSTCBY; /* Task no longer ready任务不再为就绪态*/
OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX;
if (OSRdyTbl[y] == 0u) /*将任务从就绪任务表中删除*/
{
OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;
}
}
#endif
OS_EventTaskWaitMulti(OS_EVENT **pevents_wait)使任务进入等待状态的函数(多任务下):
/*$PAGE*/
/*2018/2/7
*********************************************************************************************************
* MAKE TASK WAIT FOR ANY OF MULTIPLE EVENTS TO OCCUR
* 多事件情况下的任务等待函数
* Description: This function is called by other uC/OS-II services to suspend a task because any one of
* multiple events has not occurred.
*描述:该功能被uc/os-ii服务调用,当多事件中的任何一个发生时,挂起任务
* Arguments : pevents_wait is a pointer to an array of event control blocks, NULL-terminated, for
* which the task will be waiting for.
*参数: --pevents_wait指向事件控制块数组的指针(指针的指针)。以null结尾。
* Returns : none.
*返回值:无
* Note : This function is INTERNAL to uC/OS-II and your application should not call it.
注释:该功能为uc/os-ii内部功能,你的应用程序不能调用它。
*********************************************************************************************************
*/
#if ((OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u)) /*如果可以产生事件并且多事件数量>0*/
void OS_EventTaskWaitMulti(OS_EVENT **pevents_wait) /*调用函数*/
{
OS_EVENT **pevents;
OS_EVENT *pevent;
INT8U y;
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /*当前TCB的事件指针设置为0*/
OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)pevents_wait; /*将事件等待指针赋给当前TCB中的多事件指针*/
pevents = pevents_wait;
pevent = *pevents;
while (pevent != (OS_EVENT *)0) { /* Put task in waiting lists将任务放到等待列表中*/
pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;
pevent->OSEventGrp |= OSTCBCur->OSTCBBitY;
pevents++;
pevent = *pevents;
}
y = OSTCBCur->OSTCBY; /* Task no longer ready 此时该任务不再是就绪态 */
OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX;
if (OSRdyTbl[y] == 0u) { /* Clear event grp bit if this was only task pending */
OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;/*清除*/
}
}
#endif
OS_EventTaskRemove(OS_TCB *ptcb,OS_EVENT *pevent)从事件等待列表中移除任务函数:
/*$PAGE*/
/*2018/2/7
*********************************************************************************************************
* REMOVE TASK FROM EVENT WAIT LIST
* 从事件等待列表中移除任务函数
* Description: Remove a task from an event's wait list.
*描述:将任务从一个事件的等待列表中移除
* Arguments : ptcb is a pointer to the task to remove.
*参数: --ptcb是一个指向要移除任务的指针
* pevent is a pointer to the event control block.
* --pevent是一个指向事件控制块的指针
* Returns : none
*返回值:无
* Note : This function is INTERNAL to uC/OS-II and your application should not call it.
注释:该功能为内部函数,你的应用程序不能调用。
*********************************************************************************************************
*/
#if (OS_EVENT_EN)
void OS_EventTaskRemove(OS_TCB *ptcb,OS_EVENT *pevent)
{
INT8U y;
y = ptcb->OSTCBY;
pevent->OSEventTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX; /* Remove task from wait list将人物从等待列表中移除*/
if (pevent->OSEventTbl[y] == 0u) {
pevent->OSEventGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
}
}
#endif
后面这两个函数在前面的基础上就比较好理解了。不再赘述。
本篇博客重点还是放在两张表的学习上。