?? 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 + -