📄 os_flag.c
字号:
/*
*********************************************************************************************************
* uC/OS-II 实时内核
* 事件标志管理
*
* (c) 版权 1992-2002, 所有版权归Jean J. Labrosse, Weston, FL 所有
*
*
* 文件名称 : OS_FLAG.C
* 程序作者 : Jean J. Labrosse
*********************************************************************************************************
*/
#ifndef OS_MASTER_FILE
#include "INCLUDES.H"
#endif
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
/*
*********************************************************************************************************
* 局部 函数
*********************************************************************************************************
*/
static void OS_FlagBlock(OS_FLAG_GRP *pgrp, OS_FLAG_NODE *pnode, OS_FLAGS flags, INT8U wait_type, INT16U timeout);
static BOOLEAN OS_FlagTaskRdy(OS_FLAG_NODE *pnode, OS_FLAGS flags_rdy);
/*$PAGE*/
/*
*********************************************************************************************************
* 在一个事件标志组中检验事件标志状态
*
* 函数描述: 该函数检查在事件标志组中清零或置位组合位状态。应用程序能检查所有位或每一位的置位/清零。
*
* This call does not block if the desired flags are not present.
*
* 输入参数 : 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
*
* err 指向出错代码的指针:
* OS_NO_ERR 没有错误
* OS_FLAG_INVALID_PGRP 'pgrp' 是一个空指针。
* OS_ERR_EVENT_TYPE 没有指向事件标志组
* OS_FLAG_ERR_WAIT_TYPE 指定 适当的'wait_type' 参数
* OS_FLAG_ERR_NOT_RDY 等待的标志无效
* 返回值 : 在事件标志组中的标志状态。
*
* 任务和ISR 调用
*********************************************************************************************************
*/
#if OS_FLAG_ACCEPT_EN > 0
OS_FLAGS OSFlagAccept (OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U wait_type, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
OS_FLAGS flags_cur;
OS_FLAGS flags_rdy;
BOOLEAN consume;
#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*/
*err = OS_NO_ERR; /* 假设无错误 */
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; /* 仅清除期望的标志位 */
}
}
else
{
*err = OS_FLAG_ERR_NOT_RDY;
}
flags_cur = pgrp->OSFlagFlags; /* 返回到标志组状态 */
OS_EXIT_CRITICAL();
break;
case OS_FLAG_WAIT_SET_ANY:
flags_rdy = pgrp->OSFlagFlags & flags; /* 仅提取期望的标志位 */
if (flags_rdy != (OS_FLAGS)0)
{ /* 看一些标志位是否置1 */
if (consume == TRUE)
{ /* 看是否需要清零标志位 */
pgrp->OSFlagFlags &= ~flags_rdy; /* 仅清除期望的标志位 */
}
}
else
{
*err = OS_FLAG_ERR_NOT_RDY;
}
flags_cur = pgrp->OSFlagFlags; /* 返回到标志组状态 */
OS_EXIT_CRITICAL();
break;
#if OS_FLAG_WAIT_CLR_EN > 0
case OS_FLAG_WAIT_CLR_ALL: /* 看所有需要的标志位是否置1 */
flags_rdy = ~pgrp->OSFlagFlags & flags; /* 仅提取期望的标志位 */
if (flags_rdy == flags)
{ /* 必须匹配期望的所有标志位 */
if (consume == TRUE)
{ /* 看是否需要清零标志位 */
pgrp->OSFlagFlags |= flags_rdy; /* 仅置高期望的标志位 */
}
}
else
{
*err = OS_FLAG_ERR_NOT_RDY;
}
flags_cur = pgrp->OSFlagFlags; /* 返回到标志组状态 */
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; /* 仅置高期望的标志位 */
}
}
else
{
*err = OS_FLAG_ERR_NOT_RDY;
}
flags_cur = pgrp->OSFlagFlags; /* 返回到标志组状态 */
OS_EXIT_CRITICAL();
break;
#endif
default:
OS_EXIT_CRITICAL();
flags_cur = (OS_FLAGS)0;
*err = OS_FLAG_ERR_WAIT_TYPE;
break;
}
return (flags_cur);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* 创建一个事件标志
*
* 函数描述: 该函数用于创建一个事件标志组
*
* 输入参数 : flags 包含存在事件标志组中初始值
*
* err 指向包含下列值之一的出错代码的指针: err 指向返回到应用程序的出错代码的指针:
* OS_NO_ERR 调用成功
* OS_ERR_CREATE_ISR 从ISR中建立一个事件标志。
* OS_FLAG_GRP_DEPLETED 没有了事件标志组
*
* 返回值 : 指向一个事件标志组指针或如果没有分配的事件标志组则返回一个空指针。
*
* 仅从任务中调用
*********************************************************************************************************
*/
OS_FLAG_GRP *OSFlagCreate (OS_FLAGS flags, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
OS_FLAG_GRP *pgrp;
if (OSIntNesting > 0) /* 如果调用来自 ISR ... */
{
*err = OS_ERR_CREATE_ISR; /* ... 从 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; /* 任务等待列表清零 */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
}
else
{
OS_EXIT_CRITICAL();
*err = OS_FLAG_GRP_DEPLETED;
}
return (pgrp); /* 返回指向事件标志组的指针 */
}
/*$PAGE*/
/*
*********************************************************************************************************
* 删除一个事件标志组
*
* 函数描述: 该函数删除一个事件标志组并且就绪所有等待事件标志组的任务。
*
* 输入参数 : pgrp 指向期望的事件标志组的指针
*
* opt 决定删除的选项:
* opt == OS_DEL_NO_PEND 只在没有任务等待时删除事件标志组
* opt == OS_DEL_ALWAYS 即使任务等待也要删除事件标志组。该情形下,所有等待的
* 任务将就绪。
*
*
* err 指向包含下列值之一的出错代码的指针:
* OS_NO_ERR 调用成功以及事件标志组被删。
* OS_ERR_DEL_ISR 从ISR中删除事件标志组
* OS_FLAG_INVALID_PGRP 'pgrp'是一个空指针
* OS_ERR_EVENT_TYPE 传递的不是一个事件标志组
* OS_ERR_INVALID_OPT 指定的为无效选项
* OS_ERR_TASK_WAITING 一个或更多的任务在等待事件标志组
*
* 返回值 : pevent upon error
* (OS_EVENT *)0 信号量成功被删
*
* 注释 : 1) 该函数需谨慎使用。期望事件标志组的任务一定要检查OSFlagAccept()和OSFlagPend()的返回值.
* 2) 这种调用潜在的关闭中断很长时间。中断关闭时间直接正比于等待事件标志组的任务的数量。
*********************************************************************************************************
*/
#if OS_FLAG_DEL_EN > 0
OS_FLAG_GRP *OSFlagDel (OS_FLAG_GRP *pgrp, INT8U opt, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
BOOLEAN tasks_waiting;
OS_FLAG_NODE *pnode;
if (OSIntNesting > 0)
{ /* 如果调用来自 ISR ... */
*err = OS_ERR_DEL_ISR; /* ... 从ISR中不能删除 */
return (pgrp);
}
#if OS_ARG_CHK_EN > 0
if (pgrp == (OS_FLAG_GRP *)0)
{ /* 无效的 'pgrp' */
*err = OS_FLAG_INVALID_PGRP;
return (pgrp);
}
if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG)
{ /* 无效的事件标志组 */
*err = OS_ERR_EVENT_TYPE;
return (pgrp);
}
#endif
OS_ENTER_CRITICAL();
if (pgrp->OSFlagWaitList != (void *)0)
{ /* 看是否有任务在等待事件标志组 */
tasks_waiting = TRUE; /* 是 */
}
else
{
tasks_waiting = FALSE; /* 没有 */
}
switch (opt)
{
case OS_DEL_NO_PEND: /* 若没有任务等待删除事件标志组 */
if (tasks_waiting == FALSE)
{
pgrp->OSFlagType = OS_EVENT_TYPE_UNUSED;
pgrp->OSFlagWaitList = (void *)OSFlagFreeList; /* 返回事件标志组到空余链表上 */
OSFlagFreeList = pgrp;
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return ((OS_FLAG_GRP *)0); /* 事件标志组被删除 */
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -