📄 os_flag.c
字号:
timeout:任务等待事件标志位的目标时间
*********************************************************************************************************
*/
static void OS_FlagBlock (OS_FLAG_GRP *pgrp, OS_FLAG_NODE *pnode, OS_FLAGS flags, INT8U wait_type, INT16U timeout)
{
OS_FLAG_NODE *pnode_next;
OSTCBCur->OSTCBStat |= OS_STAT_FLAG;
OSTCBCur->OSTCBDly = timeout; /* Store timeout in task's TCB */
//在TCB中保存超时时间
#if OS_TASK_DEL_EN > 0//允许包含任务删除代码
OSTCBCur->OSTCBFlagNode = pnode; /* TCB to link to node */
// 将OSTCBFlagNode数据结构保存在TCB的一个链接中,前提是OS_TASK_DEL_EN为1,可以根据这个
//链接把要删除的任务从对应的事件标志组的等待列表中删除。删除工作由其它函数完成。
#endif
pnode->OSFlagNodeFlags = flags; /* Save the flags that we need to wait for */
//保存任务等待标志组中指定事件标志位和等待方式的信息,
pnode->OSFlagNodeWaitType = wait_type; /* Save the type of wait we are doing */
//保存我们等待的方式
pnode->OSFlagNodeTCB = (void *)OSTCBCur; /* Link to task's TCB */
//将当前任务列入等待事件的TCB
pnode->OSFlagNodeNext = pgrp->OSFlagWaitList; /* Add node at beginning of event flag wait list */
//把新增的OS_FLAG_NODE的添加到双向链表的开始端
pnode->OSFlagNodePrev = (void *)0;
pnode->OSFlagNodeFlagGrp = (void *)pgrp; /* Link to Event Flag Group */
//将此事件标志组反向链接到OS_FLAG_NODE的事件标志组中,当删除一个任务时,
//需要根据这个链接把被删除的任务从对应的事件标志组的等待任务列表中删除
pnode_next = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;
//把前面一个OS_FLAG_NODE指针链接到新添加的OS_FLAG_NODE
if (pnode_next != (void *)0) { /* Is this the first NODE to insert? */
pnode_next->OSFlagNodePrev = pnode; /* No, link in doubly linked list */
}
pgrp->OSFlagWaitList = (void *)pnode;//第一个结点就变成pnode了
/* Suspend current task until flag(s) received */
if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) {
OSRdyGrp &= ~OSTCBCur->OSTCBBitY;//挂起当前任务直到收到事件标志
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* INITIALIZE THE EVENT FLAG MODULE
*
* Description: This function is called by uC/OS-II to initialize the event flag module. Your application
* MUST NOT call this function. In other words, this function is internal to uC/OS-II.
*
* Arguments : none
*
* Returns : none
*
* WARNING : You MUST NOT call this function from your code. This is an INTERNAL function to uC/OS-II.
初始化事件标志模型
描述:由ucos调用初始化事件标志模块,应用程序不能调用
参数:无
返回:无
备注:是内部函数,应用程序不能调用
*********************************************************************************************************
*/
void OS_FlagInit (void)
{
#if OS_MAX_FLAGS == 1//只有一个事件标志组
OSFlagFreeList = (OS_FLAG_GRP *)&OSFlagTbl[0]; /* Only ONE event flag group! */
//只有一个组
OSFlagFreeList->OSFlagType = OS_EVENT_TYPE_UNUSED;
//初始化设置成没有使用
OSFlagFreeList->OSFlagWaitList = (void *)0;
//没有任务在等它
#endif
#if OS_MAX_FLAGS >= 2//多个事件标志组
INT8U i;
OS_FLAG_GRP *pgrp1;
OS_FLAG_GRP *pgrp2;
pgrp1 = &OSFlagTbl[0];
pgrp2 = &OSFlagTbl[1];
for (i = 0; i < (OS_MAX_FLAGS - 1); i++) { /* Init. list of free EVENT FLAGS */
//初始化空闲的事件标志
pgrp1->OSFlagType = OS_EVENT_TYPE_UNUSED;//设置成没有使用
pgrp1->OSFlagWaitList = (void *)pgrp2;//把它们链起来
pgrp1++;
pgrp2++;
}
pgrp1->OSFlagWaitList = (void *)0;//没有任务等它们
OSFlagFreeList = (OS_FLAG_GRP *)&OSFlagTbl[0];//表头
#endif
}
/*$PAGE*/
/*
*********************************************************************************************************
* MAKE TASK READY-TO-RUN, EVENT(s) OCCURRED
*
* Description: This function is internal to uC/OS-II and is used to make a task ready-to-run because the
* desired event flag bits have been set.
*
* Arguments : pnode is a pointer to a structure which contains data about the task waiting for
* event flag bit(s) to be set.
*
* flags_rdy contains the bit pattern of the event flags that cause the task to become
* ready-to-run.
*
* Returns : none
*
* Called by : OSFlagsPost() OS_FLAG.C
*
* Note(s) : 1) This function assumes that interrupts are disabled.
* 2) This function is INTERNAL to uC/OS-II and your application should not call it.
//事件发生,使任务就绪
描述:Ucos内部函数,用于目标事件标志位置位了,使任务就绪
参数:pnode:指向包含等待事件标志位置位的任务数据的指针
flags_rdy:包含事件标志的位模式,它将引起事件就绪
返回:无
由OSFlagsPost() OS_FLAG.C调用
备注:1、调用此函数要关中断
2、内部函数,应用程序不能调用
*********************************************************************************************************
*/
static BOOLEAN OS_FlagTaskRdy (OS_FLAG_NODE *pnode, OS_FLAGS flags_rdy)
{
OS_TCB *ptcb;
BOOLEAN sched;
ptcb = (OS_TCB *)pnode->OSFlagNodeTCB; /* Point to TCB of waiting task */
//取出指向等待事件的PCB指针
ptcb->OSTCBDly = 0;//不延时
ptcb->OSTCBFlagsRdy = flags_rdy;//将需要就绪任务的标志取出来
ptcb->OSTCBStat &= ~OS_STAT_FLAG;//消除事件标志组中挂起状态
if (ptcb->OSTCBStat == OS_STAT_RDY) { /* Put task into ready list *///交它放入就绪列表
OSRdyGrp |= ptcb->OSTCBBitY;
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;//加入就绪列表,具体算法见BLOG
sched = TRUE;//需要任务调度
} else {//否则不需要任务调度
sched = FALSE;
}
OS_FlagUnlink(pnode);//将结点从等待列表中删除
return (sched);
}
/*$PAGE*/
/*
*********************************************************************************************************
* UNLINK EVENT FLAG NODE FROM WAITING LIST
*
* Description: This function is internal to uC/OS-II and is used to unlink an event flag node from a
* list of tasks waiting for the event flag.
*
* Arguments : pnode is a pointer to a structure which contains data about the task waiting for
* event flag bit(s) to be set.
*
* Returns : none
*
* Called by : OS_FlagTaskRdy() OS_FLAG.C
* OSFlagPend() OS_FLAG.C
* OSTaskDel() OS_TASK.C
*
* Note(s) : 1) This function assumes that interrupts are disabled.
* 2) This function is INTERNAL to uC/OS-II and your application should not call it.
*********************************************************************************************************
*/
/*
*********************************************************************************************************
将事件标志结点从等待列表中删除
描述:这个函数是ucos内部的,用于将事件标志结点和等待事件标志的一系列任务解链。
参数:pnode:它是一个结构指针,包含任务等待事件标志位将被设置的数据。
返回:无
由下面函数调用: OS_FlagTaskRdy() OS_FLAG.C
* OSFlagPend() OS_FLAG.C
* OSTaskDel() OS_TASK.C
备注:1、这个函数假定中断不能使
2、此函数属于ucos内部,应用函数不能调用。
*********************************************************************************************************
*/
void OS_FlagUnlink (OS_FLAG_NODE *pnode)
{
#if OS_TASK_DEL_EN > 0//允许 包含任务删除代码
OS_TCB *ptcb;//任务控制块
#endif
OS_FLAG_GRP *pgrp;//事件控制群
OS_FLAG_NODE *pnode_prev;//事件标志等待链表接点前端
OS_FLAG_NODE *pnode_next;//事件标志等待链表接点后端
pnode_prev = (OS_FLAG_NODE *)pnode->OSFlagNodePrev;//等待链表中等待结点指针前端赋给pnode_prev
pnode_next = (OS_FLAG_NODE *)pnode->OSFlagNodeNext;//等待链表中等待结点指针后端赋给pnode_next
if (pnode_prev == (OS_FLAG_NODE *)0) { /* Is it first node in wait list? */
//如果是第一个结点
pgrp = (OS_FLAG_GRP *)pnode->OSFlagNodeFlagGrp;
//等待链表中事件控制群指针赋给事件控制群
pgrp->OSFlagWaitList = (void *)pnode_next; /* Update list for new 1st node */
//事件控制群中下一个指针置于等待链表的第一个结点指针
if (pnode_next != (OS_FLAG_NODE *)0) {
pnode_next->OSFlagNodePrev = (OS_FLAG_NODE *)0; /* Link new 1st node PREV to NULL */
//新结点的前端指向空指针
}
} else { /* No, A node somewhere in the list */
//如果不是第一个结点
pnode_prev->OSFlagNodeNext = pnode_next; /* Link around the node to unlink */
//前端的后端为pnode_next
if (pnode_next != (OS_FLAG_NODE *)0) { /* Was this the LAST node? */
//如果不是是后一个结点
pnode_next->OSFlagNodePrev = pnode_prev; /* No, Link around current node */
//后端的前端为pnode的前端
}
}
#if OS_TASK_DEL_EN > 0//能便删除任务代码
ptcb = (OS_TCB *)pnode->OSFlagNodeTCB;//等待任务控制块指针赋给任务控制块
ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0;//事件标志结点清零
#endif
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -