您的位置:首页 > 房产 > 建筑 > 客服在线为您服务_世界互联网峰会2022_如何在网上推广产品_竞价排名推广

客服在线为您服务_世界互联网峰会2022_如何在网上推广产品_竞价排名推广

2025/7/1 21:06:24 来源:https://blog.csdn.net/sherlock_cp/article/details/144455494  浏览:    关键词:客服在线为您服务_世界互联网峰会2022_如何在网上推广产品_竞价排名推广
客服在线为您服务_世界互联网峰会2022_如何在网上推广产品_竞价排名推广

快速回顾

μC/OS-Ⅱ中的多任务

μC/OS-Ⅱ源码学习(1)---多任务系统的实现

μC/OS-Ⅱ源码学习(2)---多任务系统的实现(下)

μC/OS-Ⅱ源码学习(3)---事件模型

μC/OS-Ⅱ源码学习(4)---信号量

μC/OS-Ⅱ源码学习(5)---消息队列

        本文进一步解析事件模型中,事件标志组类型的函数源码。

简单介绍

        事件标志组(Event flag group)是一种特殊的事件,其事件控制块为:

//ucos_ii.h
typedef struct os_flag_grp {INT8U         OSFlagType;         /* 事件标志组类型 */void         *OSFlagWaitList;     /* 等待链表,里面的每一个节点都记录了相关任务等待事件标志位的信息 */OS_FLAGS      OSFlagFlags;        /* 当前存在的标志 */
#if OS_FLAG_NAME_EN > 0uINT8U        *OSFlagName;
#endif
} OS_FLAG_GRP;

        与其他事件不同,事件标志组不共享OS_EVENT结构,而是有自己特殊的结构OS_FLAG_GRP。其中OS_FLAGS的长度是可以设定的,表示一个事件标志组内最多有多少种标志:

//ucos_ii.h
#if OS_FLAGS_NBITS == 8u
typedef  INT8U    OS_FLAGS;
#endif#if OS_FLAGS_NBITS == 16u
typedef  INT16U   OS_FLAGS;
#endif#if OS_FLAGS_NBITS == 32u
typedef  INT32U   OS_FLAGS;
#endif

        OSFlagWaitList链表用来记录等待该事件标志组的所有任务及其需求,通常通常用一个节点对象OS_FLAG_NODE来保存这些信息:

//ucos_ii.h
typedef struct os_flag_node {void         *OSFlagNodeNext;          /* 等待列表的下一个节点 */void         *OSFlagNodePrev;          /* 等待列表的前一个节点 */void         *OSFlagNodeTCB;           /* 指向等待该事件标志组的任务,和下一个成员相匹配 */void         *OSFlagNodeFlagGrp;       /* 指向等待的事件标志组          */OS_FLAGS      OSFlagNodeFlags;         /* 等待的标志位 */INT8U         OSFlagNodeWaitType;      /* 等待类型,即任意匹配或全部匹配等 */
} OS_FLAG_NODE;

       回忆其它事件(如信号量、消息队列,以下简称普通事件)的等待表,都是使用类似就绪表的方式来快速检索。这是因为普通事件类型在pend时,无需记录其它的等待信息,例如一个任务通过pend函数等待一个普通事件时,该普通事件只需要记录该任务的优先级,当普通事件发生后,直接查表来通知对应的任务即可。

        而事件标志组在pend过程中需要记录的信息就多了一些,比如不同任务执行所需要的标志位可能是不一样的,这就导致简单使用等待表的方式会丢失这些信息。μC/OSⅡ将这些信息记录在一个个节点中,并用遍历链表的方式查找满足条件的任务。

        可以说,不同的等待结构和方式,是事件标志组区分于其它事件的根本原因,也因此,μC/OSⅡ使用了额外的控制块类型OS_FLAG_GRP来实现事件标志组。

事件标志组的创建

        对应函数为OSFlagCreate(OS_FLAGS flagsINT8U *perr),需要传入一个标志作为初始值,返回一个初始化后的事件标志组控制块。

//os_flag.c
OS_FLAG_GRP  *OSFlagCreate (OS_FLAGS  flags,INT8U    *perr)
{OS_FLAG_GRP *pgrp;
#if OS_CRITICAL_METHOD == 3u        /* 初始化临界区变量 */OS_CPU_SR    cpu_sr = 0u;
#endif#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0) {OS_SAFETY_CRITICAL_EXCEPTION();}
#endif#ifdef OS_SAFETY_CRITICAL_IEC61508if (OSSafetyCriticalStartFlag == OS_TRUE) {OS_SAFETY_CRITICAL_EXCEPTION();}
#endifif (OSIntNesting > 0u) {         /* 不能在中断中调用 */*perr = OS_ERR_CREATE_ISR;   return ((OS_FLAG_GRP *)0);}OS_ENTER_CRITICAL();pgrp = OSFlagFreeList;        /* 获取一个新的事件标志组控制块 */if (pgrp != (OS_FLAG_GRP *)0) {       /* 查看是否是有效控制块 *//* 如果是一个有效控制块,则将原链表头指向下一个,完成首个控制块的脱离 */OSFlagFreeList       = (OS_FLAG_GRP *)OSFlagFreeList->OSFlagWaitList;pgrp->OSFlagType     = OS_EVENT_TYPE_FLAG;  /* 设置为事件标志组类型 */pgrp->OSFlagFlags    = flags;               /* 设置初始值 */pgrp->OSFlagWaitList = (void *)0;           /* 等待表初始化为0 */
#if OS_FLAG_NAME_EN > 0upgrp->OSFlagName     = (INT8U *)(void *)"?";
#endifOS_EXIT_CRITICAL();*perr                = OS_ERR_NONE;} else {     //没有有效的任务控制块了OS_EXIT_CRITICAL();*perr                = OS_ERR_FLAG_GRP_DEPLETED;}return (pgrp);                                  /* 返回创建的事件标志组控制块 */
}

事件标志组的操作

OS_FLAGS OSFlagPend(OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U wait_typeINT32U timeout, INT8U *perr)

        功能描述:等待事件flags的到来,如果已经存在这些事件标志,则直接继续执行,否则阻塞等待。该函数有很多可选功能:

wait_type可以是以下值及其组合:

//os_flag.c
#define  OS_FLAG_WAIT_CLR_ALL           0u  /* 等待所有传入的事件标志的清除(0有效) */
#define  OS_FLAG_WAIT_CLR_AND           0u#define  OS_FLAG_WAIT_CLR_ANY           1u  /* 等待任意传入的事件标志的清除(0有效) */
#define  OS_FLAG_WAIT_CLR_OR            1u#define  OS_FLAG_WAIT_SET_ALL           2u  /* 等待所有传入的事件标志的出现(1有效) */
#define  OS_FLAG_WAIT_SET_AND           2u#define  OS_FLAG_WAIT_SET_ANY           3u  /* 等待任意传入的事件标志的出现(1有效) */
#define  OS_FLAG_WAIT_SET_OR            3u#define  OS_FLAG_CONSUME             0x80u  /* 当pend得到满足后,这些标志会消耗掉 */

timeout等待超时时长,当大于0时,表示等待timeout时长后系统会将该任务就绪。传入等于0时,表示一直等待直到事件标志的出现。

        接着看源码:

//os_flag.c
OS_FLAGS  OSFlagPend (OS_FLAG_GRP  *pgrp,OS_FLAGS      flags,INT8U         wait_type,INT32U        timeout,INT8U        *perr)
{OS_FLAG_NODE  node;OS_FLAGS      flags_rdy;INT8U         result;INT8U         pend_stat;BOOLEAN       consume;
#if OS_CRITICAL_METHOD == 3u       /* 初始化临界区变量 */OS_CPU_SR     cpu_sr = 0u;
#endif#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0) {OS_SAFETY_CRITICAL_EXCEPTION();}
#endif#if OS_ARG_CHK_EN > 0uif (pgrp == (OS_FLAG_GRP *)0) {       /* 事件标志组不能为空 */*perr = OS_ERR_FLAG_INVALID_PGRP;return ((OS_FLAGS)0);}
#endifif (OSIntNesting > 0u) {        /* 不能在中断中调用 */*perr = OS_ERR_PEND_ISR;return ((OS_FLAGS)0);}if (OSLockNesting > 0u) {        /* 调度器上锁时无法调用 */*perr = OS_ERR_PEND_LOCKED;return ((OS_FLAGS)0);}if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) {       /* 必须是事件标志组类型 */*perr = OS_ERR_EVENT_TYPE;return ((OS_FLAGS)0);}result = (INT8U)(wait_type & OS_FLAG_CONSUME);if (result != (INT8U)0) {                 /* 是否需要消耗掉这些flags */wait_type &= (INT8U)~(INT8U)OS_FLAG_CONSUME;   //清除消耗(consume)标志consume    = OS_TRUE;     //消耗标志为真} else {consume    = OS_FALSE;}
/*$PAGE*/OS_ENTER_CRITICAL();switch (wait_type) {case OS_FLAG_WAIT_SET_ALL:       /* 需要所有指定标志都出现 */flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags);    /* 通过按位与获取我们想要的位 */if (flags_rdy == flags) {         /* 这些位必须值为1(与所需标志相同) */if (consume == OS_TRUE) {pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy;   /* 如果需要消耗掉这些位,通过按位与取反对应位即可 */}OSTCBCur->OSTCBFlagsRdy = flags_rdy;     /* 将准备好的标志位传递给任务TCB */OS_EXIT_CRITICAL();*perr                   = OS_ERR_NONE;return (flags_rdy);} else {         /* 若标志位不满足条件,则创建节点并进行任务和标志组的双向绑定 */OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);OS_EXIT_CRITICAL();}break;case OS_FLAG_WAIT_SET_ANY:     //任意指定的标志位出现flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags);    /* 通过按位与互殴去我们想要的位 */if (flags_rdy != (OS_FLAGS)0) {      /* 只要有任意位满足,整个flags就不为0 */if (consume == OS_TRUE) {      /* 是否需要消耗掉这些标志 */pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy;    /* 按位与取反对应位进行清除 */}OSTCBCur->OSTCBFlagsRdy = flags_rdy;     /* 将已有的标志位传递给任务TCB */OS_EXIT_CRITICAL();*perr                   = OS_ERR_NONE;return (flags_rdy);} else {       /* 若标志位不满足条件,则创建节点并进行任务和标志组的双向绑定 */OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);OS_EXIT_CRITICAL();}break;#if OS_FLAG_WAIT_CLR_EN > 0u        /* 0有效,和上面代码逻辑是一样的 */case OS_FLAG_WAIT_CLR_ALL:flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags;    /* Extract only the bits we want     */if (flags_rdy == flags) {                     /* Must match ALL the bits that we want     */if (consume == OS_TRUE) {                 /* See if we need to consume the flags      */pgrp->OSFlagFlags |= flags_rdy;       /* Set ONLY the flags that we wanted        */}OSTCBCur->OSTCBFlagsRdy = flags_rdy;      /* Save flags that were ready               */OS_EXIT_CRITICAL();                       /* Yes, condition met, return to caller     */*perr                   = OS_ERR_NONE;return (flags_rdy);} else {                                      /* Block task until events occur or timeout */OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);OS_EXIT_CRITICAL();}break;case OS_FLAG_WAIT_CLR_ANY:flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags;   /* Extract only the bits we want      */if (flags_rdy != (OS_FLAGS)0) {               /* See if any flag cleared                  */if (consume == OS_TRUE) {                 /* See if we need to consume the flags      */pgrp->OSFlagFlags |= flags_rdy;       /* Set ONLY the flags that we got           */}OSTCBCur->OSTCBFlagsRdy = flags_rdy;      /* Save flags that were ready               */OS_EXIT_CRITICAL();                       /* Yes, condition met, return to caller     */*perr                   = OS_ERR_NONE;return (flags_rdy);} else {                                      /* Block task until events occur or timeout */OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);OS_EXIT_CRITICAL();}break;
#endifdefault:     //其他情况是非法的,返回空标志(0)OS_EXIT_CRITICAL();flags_rdy = (OS_FLAGS)0;*perr      = OS_ERR_FLAG_WAIT_TYPE;return (flags_rdy);}
/*$PAGE*/OS_Sched();        /* 尝试切换上下文 */OS_ENTER_CRITICAL();     //再次回到这里时,表明任务由于以下原因重新就绪了if (OSTCBCur->OSTCBStatPend != OS_STAT_PEND_OK) {      /* 非标志位满足条件导致就绪 */pend_stat                = OSTCBCur->OSTCBStatPend;OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;    //pend恢复OK状态OS_FlagUnlink(&node);      //将上面绑定的节点进行解绑OSTCBCur->OSTCBStat      = OS_STAT_RDY;      /* 使任务状态变为就绪态 */OS_EXIT_CRITICAL();flags_rdy                = (OS_FLAGS)0;     //这种情况下,标志位没有意义,直接清空switch (pend_stat) {case OS_STAT_PEND_ABORT:*perr = OS_ERR_PEND_ABORT;     /* 因使用Abort函数导致的pend结束 */break;case OS_STAT_PEND_TO:default:*perr = OS_ERR_TIMEOUT;      /* 超时导致的pend结束 */break;}return (flags_rdy);}flags_rdy = OSTCBCur->OSTCBFlagsRdy;     //将外部传入的标志位赋值flags_rdy,做其它处理if (consume == OS_TRUE) {         /* 消耗标志位 */switch (wait_type) {case OS_FLAG_WAIT_SET_ALL:case OS_FLAG_WAIT_SET_ANY: pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy;     /* 将事件标志组对应位清除 */break;#if OS_FLAG_WAIT_CLR_EN > 0ucase OS_FLAG_WAIT_CLR_ALL:case OS_FLAG_WAIT_CLR_ANY:      pgrp->OSFlagFlags |=  flags_rdy;   /* 0有效,将事件标志组对应位置位 */break;
#endifdefault:    //其他情况为非法,返回空标志OS_EXIT_CRITICAL();*perr = OS_ERR_FLAG_WAIT_TYPE;return ((OS_FLAGS)0);}}OS_EXIT_CRITICAL();*perr = OS_ERR_NONE;     /* 没有错误发生,表明一定有标志位出现 */return (flags_rdy);     //返回获得的标志位
}

        具体看看事件标志组与任务的双向绑定函数OS_FlagBlock()

//os_flag.c
static  void  OS_FlagBlock (OS_FLAG_GRP  *pgrp,OS_FLAG_NODE *pnode,OS_FLAGS      flags,INT8U         wait_type,INT32U        timeout)
{OS_FLAG_NODE  *pnode_next;INT8U          y;OSTCBCur->OSTCBStat      |= OS_STAT_FLAG;      //任务状态:等待标志位OSTCBCur->OSTCBStatPend   = OS_STAT_PEND_OK;OSTCBCur->OSTCBDly        = timeout;       /* 填装等待超时 */
#if OS_TASK_DEL_EN > 0uOSTCBCur->OSTCBFlagNode   = pnode;       /* 任务等待标志位指针指向该事件标志组结点结构 */
#endif/* 标志组节点(pnode)是一个全新的空白节点,开始填装,并将其加到OSFlagWaitList链表首,原来的链表接在新节点后 */pnode->OSFlagNodeFlags    = flags;        /* 保存我们需要等待的标志位 */pnode->OSFlagNodeWaitType = wait_type;       /* 保存等待类型 */pnode->OSFlagNodeTCB      = (void *)OSTCBCur;     /* 保存当前任务的TCB */pnode->OSFlagNodeNext     = pgrp->OSFlagWaitList; /* 将新节点下一个指向原链表首 */pnode->OSFlagNodePrev     = (void *)0;pnode->OSFlagNodeFlagGrp  = (void *)pgrp;         /* 保存事件标志组 */pnode_next                = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;if (pnode_next != (void *)0) {        //首次插入链表时,链表是空的pnode_next->OSFlagNodePrev = pnode;       /* 非首次插入时,将原链表头上一个指向新创建的节点 */}pgrp->OSFlagWaitList = (void *)pnode;       /* 将链表头指向新节点 */y            =  OSTCBCur->OSTCBY;      /* 从优先级就绪表中将等待标志位的任务清除 */OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX;if (OSRdyTbl[y] == 0x00u) {OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;}
}

        可以用下图表示该函数做了什么:

①事件标志组(OS_FLAG_GRP)第一次被等待时,创建首个节点(OS_FLAG_NODE),并双向引用。

②该事件标志组(OS_FLAG_GRP)第二次被等待时,将新节点填好后挂载在原链表头,原来的链表元素接续在新节点后,同时双向引用不能少。

        再看解除绑定函数OS_FlagUnlink(),就是将上面的操作反过来,解除这些链接。

//os_flag.c
void  OS_FlagUnlink (OS_FLAG_NODE *pnode)
{
#if OS_TASK_DEL_EN > 0uOS_TCB       *ptcb;
#endifOS_FLAG_GRP  *pgrp;OS_FLAG_NODE *pnode_prev;OS_FLAG_NODE *pnode_next;pnode_prev = (OS_FLAG_NODE *)pnode->OSFlagNodePrev;pnode_next = (OS_FLAG_NODE *)pnode->OSFlagNodeNext;if (pnode_prev == (OS_FLAG_NODE *)0) {         /* 前一个节点为0,表明pnode为链表首 */pgrp                 = (OS_FLAG_GRP *)pnode->OSFlagNodeFlagGrp;pgrp->OSFlagWaitList = (void *)pnode_next;        /* 将该节点脱离链表 */if (pnode_next != (OS_FLAG_NODE *)0) {pnode_next->OSFlagNodePrev = (OS_FLAG_NODE *)0;     /* 下一个节点的上一个指向0 */}} else {     //前一个节点非0pnode_prev->OSFlagNodeNext = pnode_next;     /* 上一节点的下一个,指向下一个节点 */if (pnode_next != (OS_FLAG_NODE *)0) {       /* 下一节点非空 */pnode_next->OSFlagNodePrev = pnode_prev;     /* 下一节点的上一个,指向上一个节点,完成pnode的脱离 */}}
#if OS_TASK_DEL_EN > 0uptcb                = (OS_TCB *)pnode->OSFlagNodeTCB;ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0;
#endif
}

OS_FLAGS OSFlagPost(OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U opt, INT8U *perr)

        功能描述:为事件标志组设置(或清除)一些标志位。支持一些选项opt:

//ucos_ii.h
#define  OS_FLAG_CLR     0u   //清除这些标志位
#define  OS_FLAG_SET     1u   //置位这些标志位

        接下来看源码:

//os_flag.c
OS_FLAGS  OSFlagPost (OS_FLAG_GRP  *pgrp,OS_FLAGS      flags,INT8U         opt,INT8U        *perr)
{OS_FLAG_NODE *pnode;BOOLEAN       sched;OS_FLAGS      flags_cur;OS_FLAGS      flags_rdy;BOOLEAN       rdy;
#if OS_CRITICAL_METHOD == 3u      /* 初始化临界区变量 */OS_CPU_SR     cpu_sr = 0u;
#endif#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0) {OS_SAFETY_CRITICAL_EXCEPTION();}
#endif#if OS_ARG_CHK_EN > 0uif (pgrp == (OS_FLAG_GRP *)0) {      /* 事件标志组不能为空 */*perr = OS_ERR_FLAG_INVALID_PGRP;return ((OS_FLAGS)0);}
#endifif (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) {     /* 事件类型必须为“事件标志组” */*perr = OS_ERR_EVENT_TYPE;return ((OS_FLAGS)0);}OS_ENTER_CRITICAL();switch (opt) {case OS_FLAG_CLR:pgrp->OSFlagFlags &= (OS_FLAGS)~flags;     /* 清除对应的标志位 */break;case OS_FLAG_SET:pgrp->OSFlagFlags |=  flags;     /* 置位对应标志位 */break;default:OS_EXIT_CRITICAL();         /* 非法选项,标记错误,返回空标志 */*perr = OS_ERR_FLAG_INVALID_OPT;return ((OS_FLAGS)0);}sched = OS_FALSE;        /* 初始化切换上下文标志,默认不切换 */pnode = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;      //获取事件标志组的等待链表while (pnode != (OS_FLAG_NODE *)0) {       /* 遍历所有的等待节点 */switch (pnode->OSFlagNodeWaitType) {      //判断等待类型case OS_FLAG_WAIT_SET_ALL:       /* 所有标志位满足 */flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & pnode->OSFlagNodeFlags);   //将任务等待的标志位和当前已有的标志位进行按位与操作if (flags_rdy == pnode->OSFlagNodeFlags) {rdy = OS_FlagTaskRdy(pnode, flags_rdy);   /* 如果已有标志位能满足任务等待的需求,则尝试就绪该任务 */if (rdy == OS_TRUE) {   //是否成功就绪(在优先级就绪表置位)sched = OS_TRUE;       /* 将切换标志置位 */}}break;case OS_FLAG_WAIT_SET_ANY:      /* 任意标志位满足 */flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & pnode->OSFlagNodeFlags);if (flags_rdy != (OS_FLAGS)0) {     //只有不为0,说明存在标志位满足条件rdy = OS_FlagTaskRdy(pnode, flags_rdy);   /* 尝试就绪等待链表中的任务 */if (rdy == OS_TRUE) {sched = OS_TRUE;}}break;#if OS_FLAG_WAIT_CLR_EN > 0u     /* 0有效,其它和上面代码逻辑相同 */case OS_FLAG_WAIT_CLR_ALL:flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & pnode->OSFlagNodeFlags;if (flags_rdy == pnode->OSFlagNodeFlags) {rdy = OS_FlagTaskRdy(pnode, flags_rdy);if (rdy == OS_TRUE) {sched = OS_TRUE;}}break;case OS_FLAG_WAIT_CLR_ANY:flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & pnode->OSFlagNodeFlags;if (flags_rdy != (OS_FLAGS)0) {rdy = OS_FlagTaskRdy(pnode, flags_rdy);if (rdy == OS_TRUE) {sched = OS_TRUE;}}break;
#endifdefault:     //非法选项,标记错误,并返回空标志OS_EXIT_CRITICAL();*perr = OS_ERR_FLAG_WAIT_TYPE;return ((OS_FLAGS)0);}pnode = (OS_FLAG_NODE *)pnode->OSFlagNodeNext;    /* 节点指向链表中的下一个 */}OS_EXIT_CRITICAL();if (sched == OS_TRUE) {    //若切换标志位为真,则尝试上下文切换OS_Sched();}OS_ENTER_CRITICAL();flags_cur = pgrp->OSFlagFlags;OS_EXIT_CRITICAL();*perr     = OS_ERR_NONE;return (flags_cur);    //返回事件标志组当前的标志
}

        其中函数OS_FlagTaskRdy(pnode, flags_rdy)用于就绪节点指向的任务,并将该节点从事件标志组控制块的等待链表中脱离:

//os_flag.c
static  BOOLEAN  OS_FlagTaskRdy (OS_FLAG_NODE *pnode,OS_FLAGS      flags_rdy)
{OS_TCB   *ptcb;BOOLEAN   sched;ptcb                 = (OS_TCB *)pnode->OSFlagNodeTCB;    /* 取出等待事件的任务TCB */ptcb->OSTCBDly       = 0u;     //等待超时计数器设置为0(不计数)ptcb->OSTCBFlagsRdy  = flags_rdy;    //将准备好的标志位填装到TCB中ptcb->OSTCBStat     &= (INT8U)~(INT8U)OS_STAT_FLAG;    //清除等待标志位状态ptcb->OSTCBStatPend  = OS_STAT_PEND_OK;     //pend状态设置为OKif (ptcb->OSTCBStat == OS_STAT_RDY) {       /* 任务是否就绪 */OSRdyGrp               |= ptcb->OSTCBBitY;       /* 将优先级就绪表中对应优先级置位 */OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;sched                   = OS_TRUE;} else {sched                   = OS_FALSE;}OS_FlagUnlink(pnode);     //释放该节点,从标志组的等待链表中脱离return (sched);    //返回是否需要切换任务
} 

事件标志组的删除

        函数原型:OS_FLAG_GRP OSFlagDel(OS_FLAG_GRP *pgrp, INT8U opt, INT8U *perr)

        和其它事件的删除函数一样,作用是清空控制块,并就绪正在等待的所有任务,最后将控制块归还给空白控制块链表。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com