📄 os_flag.c
字号:
OS_EXIT_CRITICAL();
*err = OS_ERR_TASK_WAITING;
return (pgrp);
}
case OS_DEL_ALWAYS: /* 即使有等待的任务,也要删除 */
pnode = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;
while (pnode != (OS_FLAG_NODE *)0)
{ /* 就绪所有等待标志的任务 */
OS_FlagTaskRdy(pnode, (OS_FLAGS)0);
pnode = (OS_FLAG_NODE *)pnode->OSFlagNodeNext;
}
pgrp->OSFlagType = OS_EVENT_TYPE_UNUSED;
pgrp->OSFlagWaitList = (void *)OSFlagFreeList;/* 返回事件标志组到空余链表上 */
OSFlagFreeList = pgrp;
OS_EXIT_CRITICAL();
if (tasks_waiting == TRUE)
{ /* 如果在此之前任务等待,则调度 */
OS_Sched(); /* 寻找最高优先级就绪运行 */
}
*err = OS_NO_ERR;
return ((OS_FLAG_GRP *)0); /* 事件标志组被删除 */
default:
OS_EXIT_CRITICAL();
*err = OS_ERR_INVALID_OPT;
return (pgrp);
}
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* 等待一个事件标志组的事件标志位
*
* 函数描述: 该函数用于等待事件标志组中设定的组合位。应用程序可以等待任一位或所有位。
*
* 输入参数 : pgrp 指向期望的事件标志组的指针
*
* flags 显示希望等待的位模式。在'flags'中通过设定对应位来指定期望的位。例如,应用程序
* 期望等待位0和位1,那么,'flags'将包含0X03。
*
* wait_type 指定期望等待的任一位或者所有位。
* 指定下列参数:
*
* OS_FLAG_WAIT_CLR_ALL 等待'mask'中所有位清零 (0)
* OS_FLAG_WAIT_SET_ALL 等待'mask'中所有位设置 (1)
* OS_FLAG_WAIT_CLR_ANY 等待'mask'中任一位清零 (0)
* OS_FLAG_WAIT_SET_ANY 等待'mask'中任一位设置 (1)
*
* 注释: 如果期望事件标志组通过调用清除则添加OS_FLAG_CONSUME 例如,等待事件标志组
* 中的任一标志置位后,清除位标志。设定 'wait_type' 为:
*
* OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME
*
* timeout 等待位组合的任务的延时选择项。如果设为 0 ,任务将一直等到事件标志的到来。
*
* err 指向出错代码的指针:
* OS_NO_ERR 在延时时间内期望的位被设定。
* OS_ERR_PEND_ISR 从ISR中等待
* OS_FLAG_INVALID_PGRP 'pgrp' 是一个空指针。
* OS_ERR_EVENT_TYPE 没有指向事件标志组
* OS_TIMEOUT 在延时时间内期望的位没有被设定
* OS_FLAG_ERR_WAIT_TYPE 指定 'wait_type' 出错
*
* 返回值 : 当任务重新运行时,在事件标志组中为新的标志状态,或如果延时或出错发生,则返回 0。
*
* 只有任务调用
*********************************************************************************************************
*/
OS_FLAGS OSFlagPend (OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U wait_type, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
OS_FLAG_NODE node;
OS_FLAGS flags_cur;
OS_FLAGS flags_rdy;
BOOLEAN consume;
if (OSIntNesting > 0)
{ /* 如果调用来自 ISR ... ... */
*err = OS_ERR_PEND_ISR; /* ... 从ISR中不能等待 */
return ((OS_FLAGS)0);
}
#if OS_ARG_CHK_EN > 0
if (pgrp == (OS_FLAG_GRP *)0)
{ /* 无效的 'pgrp' */
*err = OS_FLAG_INVALID_PGRP;
return ((OS_FLAGS)0);
}
if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG)
{ /* 无效的事件标志组 */
*err = OS_ERR_EVENT_TYPE;
return ((OS_FLAGS)0);
}
#endif
if (wait_type & OS_FLAG_CONSUME)
{ /* 看是否需要清事件标志 */
wait_type &= ~OS_FLAG_CONSUME;
consume = TRUE;
}
else
{
consume = FALSE;
}
/*$PAGE*/
OS_ENTER_CRITICAL();
switch (wait_type)
{
case OS_FLAG_WAIT_SET_ALL: /* 看所有需要的标志位是否置1 */
flags_rdy = pgrp->OSFlagFlags & flags; /* 仅提取期望的标志位 */
if (flags_rdy == flags)
{ /* 必须匹配期望的所有标志位 */
if (consume == TRUE) /* 看是否需要清零标志位 */
{
pgrp->OSFlagFlags &= ~flags_rdy; /* 仅清除期望的标志位 */
}
flags_cur = pgrp->OSFlagFlags; /* 返回到标志组状态 */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return (flags_cur);
}
else
{ /* 任务等待,直到事件发生或延时时间到 */
OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);
OS_EXIT_CRITICAL();
}
break;
case OS_FLAG_WAIT_SET_ANY:
flags_rdy = pgrp->OSFlagFlags & flags; /* 仅提取期望的标志位 */
if (flags_rdy != (OS_FLAGS)0)
{ /* 看是否有标志置位? */
if (consume == TRUE)
{ /* 看是否需要清除标志? */
pgrp->OSFlagFlags &= ~flags_rdy; /* 只清除得到的标志位 */
}
flags_cur = pgrp->OSFlagFlags; /* 返回事件组状态 */
OS_EXIT_CRITICAL(); /* 条件满足返回调用函数 */
*err = OS_NO_ERR;
return (flags_cur);
}
else
{ /* 任务等待,直到事件发生或延时时间到 */
OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);
OS_EXIT_CRITICAL();
}
break;
#if OS_FLAG_WAIT_CLR_EN > 0
case OS_FLAG_WAIT_CLR_ALL: /* 看所有需要的标志位是否清零 */
flags_rdy = ~pgrp->OSFlagFlags & flags; /* 仅提取期望的标志位 */
if (flags_rdy == flags)
{ /* 必须满足期望的所有位 */
if (consume == TRUE)
{ /* 看是否需要清除标志? */
pgrp->OSFlagFlags |= flags_rdy; /* 设定期望的位 */
}
flags_cur = pgrp->OSFlagFlags; /* 返回事件组状态 */
OS_EXIT_CRITICAL(); /* 条件满足返回调用函数 */
*err = OS_NO_ERR;
return (flags_cur);
}
else
{ /* 任务等待,直到事件发生或延时时间到 */
OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);
OS_EXIT_CRITICAL();
}
break;
case OS_FLAG_WAIT_CLR_ANY:
flags_rdy = ~pgrp->OSFlagFlags & flags; /* 仅提取期望的标志位 */
if (flags_rdy != (OS_FLAGS)0)
{ /* 看是否有其中一位清零? */
if (consume == TRUE)
{ /* 看是否需要清除标志? */
pgrp->OSFlagFlags |= flags_rdy; /* 设定期望的位 */
}
flags_cur = pgrp->OSFlagFlags; /* 返回事件组状态 */
OS_EXIT_CRITICAL(); /* 条件满足返回调用函数 */
*err = OS_NO_ERR;
return (flags_cur);
}
else
{ /* 任务等待,直到事件发生或延时时间到 */
OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);
OS_EXIT_CRITICAL();
}
break;
#endif
default:
OS_EXIT_CRITICAL();
flags_cur = (OS_FLAGS)0;
*err = OS_FLAG_ERR_WAIT_TYPE;
return (flags_cur);
}
OS_Sched(); /* 寻找下一个 HPT 就绪运行 */
OS_ENTER_CRITICAL();
if (OSTCBCur->OSTCBStat & OS_STAT_FLAG) /* 有延时吗? */
{
OS_FlagUnlink(&node);
OSTCBCur->OSTCBStat = OS_STAT_RDY; /* 是的 */
OS_EXIT_CRITICAL();
flags_cur = (OS_FLAGS)0;
*err = OS_TIMEOUT; /* 显示延时等待 */
}
else
{
if (consume == TRUE)
{ /* 看是否需要清除标志? */
switch (wait_type)
{
case OS_FLAG_WAIT_SET_ALL:
case OS_FLAG_WAIT_SET_ANY: /* 仅清除得到的位 */
pgrp->OSFlagFlags &= ~OSTCBCur->OSTCBFlagsRdy;
break;
#if OS_FLAG_WAIT_CLR_EN > 0
case OS_FLAG_WAIT_CLR_ALL:
case OS_FLAG_WAIT_CLR_ANY: /* 仅设定得到的位 */
pgrp->OSFlagFlags |= OSTCBCur->OSTCBFlagsRdy;
break;
#endif
}
}
flags_cur = pgrp->OSFlagFlags;
OS_EXIT_CRITICAL();
*err = OS_NO_ERR; /* 事件发生 */
}
return (flags_cur);
}
/*$PAGE*/
/*
*********************************************************************************************************
* 发送事件标志位
*
* 函数描述: 该函数用于置位或清除事件标志组中的一些位。这些位由'位掩码'指定设置或清除。
*
* 输入参数 : pgrp 指向期望的事件标志组的指针
*
* flags 如果'opt'为OS_FLAG_SET,则在'flags'中设定的每一位在事件标志组中将设定对应的位。
* 例如,置高 0, 4和 5位,则设定'flags' 为:
*
* 0x31 (注意, 0位是等级最低位)
*
* 如果'opt'为OS_FLAG_CLR,则在'flags'中设定的每一位在事件标志组中将设定对应的位。
* 例如,置低 0, 4和 5位,则设定'flags' 为:
*
* 0x31 (注意, 0位是等级最低位)
*
* opt 标志选项:
* 置高 (OS_FLAG_SET)
* 置低 (OS_FLAG_CLR)
*
* err 指向出错代码:
* OS_NO_ERR 调用成功
* OS_FLAG_INVALID_PGRP 传递一个空指针
* OS_ERR_EVENT_TYPE 指向的类型不是事件标志组
* OS_FLAG_INVALID_OPT 无效选项
*
* 返回值 : 事件标志组设置的新值。
*
* 从任务或ISR中调用
*
* 警告 : 1) 该函数的执行时间取决于等待事件标志组任务的数量。
* 2) The amount of time interrupts are DISABLED depends on the number of tasks waiting on
* the event flag group.
*********************************************************************************************************
*/
OS_FLAGS OSFlagPost (OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U opt, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
OS_FLAG_NODE *pnode;
BOOLEAN sched;
OS_FLAGS flags_cur;
OS_FLAGS flags_rdy;
#if OS_ARG_CHK_EN > 0
if (pgrp == (OS_FLAG_GRP *)0)
{ /* 无效的 'pgrp' */
*err = OS_FLAG_INVALID_PGRP;
return ((OS_FLAGS)0);
}
if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG)
{ /* 是否指向事件标志组? */
*err = OS_ERR_EVENT_TYPE;
return ((OS_FLAGS)0);
}
#endif
/*$PAGE*/
OS_ENTER_CRITICAL();
switch (opt)
{
case OS_FLAG_CLR:
pgrp->OSFlagFlags &= ~flags; /* 在标志组中清除指定标志 */
break;
case OS_FLAG_SET:
pgrp->OSFlagFlags |= flags; /* 在标志组中置高指定标志 */
break;
default:
OS_EXIT_CRITICAL(); /* 无效选项 */
*err = OS_FLAG_INVALID_OPT;
return ((OS_FLAGS)0);
}
sched = FALSE; /* 不需要重调度 */
pnode = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;
while (pnode != (OS_FLAG_NODE *)0) /* 遍历等待事件标志组的所有任务 */
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -