OS_FLAG.C(1)
本篇介紹OS_FLAG.C中的檢測事件標誌組的標誌狀態函式
OS_FLAGS OSFlagAccept (OS_FLAG_GRP *pgrp,OS_FLAGS flags,INT8U wait_type,INT8U *perr)檢測事件標誌組的標誌狀態函式:
- 介紹一下wait_type:
在最後的程式碼中也有相關介紹,為了更好理解,下面具體解釋一下:
wait_type specifies whether you want ALL bits to be set/cleared or ANY of the bitsto be set/cleared.
* You can specify the following argument:
* OS_FLAG_WAIT_CLR_ALL You will check ALL bits in 'flags' to be clear (0)
* OS_FLAG_WAIT_CLR_ANY You will check ANY bit in 'flags' to be clear (0)
* OS_FLAG_WAIT_SET_ALL You will check ALL bits in 'flags' to be set (1)
* OS_FLAG_WAIT_SET_ANY You will check ANY bit in 'flags' to be set (1)
*--wait_type:定義等待事件標誌位的方式.有以下四種引數選擇:
OS_FLAG_WAIT_CLR_ALL:所有指定事件標誌位清 (0);
OS_FLAG_WAIT_CLR_ANY:任意指定事件標誌位清 (0);
OS_FLAG_WAIT_SET_ALL:所有指定事件標誌位置 (1);
OS_FLAG_WAIT_SET_ANY:任意指定事件標誌位置 (1)。
將該引數加上一個常量OS_FLAG_CONSUME。例如,如果等待事件標誌組中任意指定事件標誌位置位,
並且在任意事件標誌位置位後清除該位,則把引數wait_type設定為:OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME。
所謂的消耗與否,就是事件組滿足條件後(獲得事件標誌組後),事件標誌組控制塊的對應事件標誌是否清除,如果清除,就稱為消耗掉,如果不清除,就成為不消耗。
程式碼中具體體現為:
result = (INT8U)(wait_type & OS_FLAG_CONSUME); /*將wiat_type與OS_FLAG_COUNSUME進行與,結果存放在result中*/ if (result != (INT8U)0) /*判斷我們是否需要清除標誌。*/ { wait_type &= ~OS_FLAG_CONSUME; /*不為0,消耗型,需要清除,wait_type儲存其取反之後的值*/ consume = OS_TRUE; /*"清除"事件標誌位置1,需要對這個標誌清0*/ } else /*result為0,非消耗型。不需要清除*/ { consume = OS_FALSE; /*"清除"事件標誌位為0*/ }
將wiat_type與OS_FLAG_COUNSUME進行邏輯與運算,結果存放在result中。若是rusult為0,則說明wait_type是沒有加上OS_FLAG_CONSUME的,也就是非消耗型別的,否則就是消耗型別的。
- 該函式中第二個需要解釋的點:
case OS_FLAG_WAIT_SET_ALL: /*等待選擇的所有位都置1,即所有指定事件標誌位清 (0)*/
flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); /*提取我們需要的位*/
if (flags_rdy == flags) /*必須匹配到我們需要的所有的位*/
{
if (consume == OS_TRUE) /*如果是消耗型的*/
{
pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /*將請求事件組中對應請求標誌位的位清零,消耗了事件*/
}
}
以這個小片段為例,裡面有一個與運算:
flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); /*提取我們需要的位*/
解釋一下我們是如何提取我們需要的位呢?這行語句為什麼進行與運算?
0 | 1 | 0 | 1 | 1 | 1 | 0 | 0 |
1 | 1 | 0 | 1 | 1 | 0 | 0 | 0 |
OSFlagFlags和flags都是8位。假定各自8位分別如上圖設定。當我們提取位的時候,就一一對應,進行邏輯與操作,並賦給flags_rdy:
0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 |
if (flags_rdy == flags) /*必須匹配到我們需要的所有的位*/
上述例子可以看到二者是不一樣的。所以這個等式不成立,就沒有匹配到我們需要的所有的位,就執行相應的操作。如果是OS_FLAG_WAIT_SET_ANY等待型別,進行完與操作之後,
if (flags_rdy != (OS_FLAGS)0) /*看是否有任何設定為1的標誌*/
是將flags_rdy與0進行比較。然後執行相關操作。
- 第三個需要提醒的點:
if (consume == OS_TRUE) /*如果是消耗型的*/
{
pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /*將請求事件組中對應請求標誌位的位清零,消耗了事件*/
}
如果是消耗型的,在清除的時候,我們只清除了之前用到的位,並不是所有位都清除了。這點需要注意一下。
下面是該函式的原始碼:
/*$PAGE*/
/*
*********************************************************************************************************
* CHECK THE STATUS OF FLAGS IN AN EVENT FLAG GROUP
* 檢測事件標誌組的標誌狀態
* Description: This function is called to check the status of a combination of bits to be set or cleared
* in an event flag group. Your application can check for ANY bit to be set/cleared or ALL
* bits to be set/cleared.
This call does not block if the desired flags are not present.
*描述:這個功能用來檢查位的組合狀態,來確定事件標誌組中的事件標誌位是置位還是清0。
你的應用程式可以檢查任意一位是置位還是清0,也可以檢查所有位是置位還是清0。
* 這個呼叫不會被阻塞如果需要的事件標誌沒有產生。這點與於OSFlagPend()不同。
* Arguments : pgrp is a pointer to the desired event flag group.
*引數: --pgrp:指向事件標誌組的指標
* flags Is a bit pattern indicating which bit(s) (i.e. flags) you wish to check.
* The bits you want are specified by setting the corresponding bits in
* 'flags'. e.g. if your application wants to wait for bits 0 and 1 then
* 'flags' would contain 0x03.
* --flags:指定需要檢查的事件標誌位。為1則檢查對應位;為0則忽若對應位。
flags是事件組合的標誌,是位掩碼,表示事件要等待哪些位。
如果應用程式等待任務組中事件標誌中的0和2,掩碼為0x05。
* wait_type specifies whether you want ALL bits to be set/cleared or ANY of the bits
* to be set/cleared.
* You can specify the following argument:
* OS_FLAG_WAIT_CLR_ALL You will check ALL bits in 'flags' to be clear (0)
* OS_FLAG_WAIT_CLR_ANY You will check ANY bit in 'flags' to be clear (0)
* OS_FLAG_WAIT_SET_ALL You will check ALL bits in 'flags' to be set (1)
* OS_FLAG_WAIT_SET_ANY You will check ANY bit in 'flags' to be set (1)
* --wait_type:定義等待事件標誌位的方式.有以下四種引數選擇:
OS_FLAG_WAIT_CLR_ALL:所有指定事件標誌位清 (0);
OS_FLAG_WAIT_CLR_ANY:任意指定事件標誌位清 (0);
OS_FLAG_WAIT_SET_ALL:所有指定事件標誌位置 (1);
OS_FLAG_WAIT_SET_ANY:任意指定事件標誌位置 (1)。
* NOTE: Add OS_FLAG_CONSUME if you want the event flag to be 'consumed' by
* the call. Example, to wait for any flag in a group AND then clear
* the flags that are present, set 'wait_type' to:
* OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME
* 註釋:如果需要在得到期望的事件標誌後,清除該事件標誌,則可以在呼叫函式時,
將該引數加上一個常量OS_FLAG_CONSUME。例如,如果等待事件標誌組中任意指定事件標誌位置位,
並且在任意事件標誌位置位後清除該位,則把引數wait_type設定為:OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME
所謂的消耗與否,就是事件組滿足條件後,獲得事件標誌組後。事件標誌組控制塊的對應事件標誌清除,即消耗掉。
* perr is a pointer to an error code and can be:
* OS_ERR_NONE No error
* OS_ERR_EVENT_TYPE You are not pointing to an event flag group
* OS_ERR_FLAG_WAIT_TYPE You didn't specify a proper 'wait_type' argument.
* OS_ERR_FLAG_INVALID_PGRP You passed a NULL pointer instead of the event flag
* group handle.
* OS_ERR_FLAG_NOT_RDY The desired flags you are waiting for are not
* available.
* --perr:是一個指向錯誤碼的指標,可以是一下幾種:
OS_ERR_NONE:無錯誤
OS_ERR_EVENT_TYPE:指標未指向事件標誌組錯
OS_ERR_FLAG_WAIT_TYPE:引數wait_type不是指定的四個方式之一。
OS_ERR_FLAG_INVALID_PGRP:pgrp為空指標
OS_ERR_FLAG_NOT_RDY:指定的事件標誌沒有發生。
* Returns : The flags in the event flag group that made the task ready or, 0 if a timeout or an error
* occurred.
*返回值:返回事件標誌組的事件標誌。如果是超時或者有錯誤發生,返回0
* Called from: Task or ISR
*呼叫:從任務或者中斷呼叫
* Note(s) : 1) IMPORTANT, the behavior of this function has changed from PREVIOUS versions. The
* function NOW returns the flags that were ready INSTEAD of the current state of the
* event flags.
註釋:1)重點:該功能和之前版本的不同,現在版本的該功能返回的是就緒的標誌,而不是當前事件的狀態
*********************************************************************************************************
*/
#if OS_FLAG_ACCEPT_EN > 0u
OS_FLAGS OSFlagAccept (OS_FLAG_GRP *pgrp,
OS_FLAGS flags,
INT8U wait_type,
INT8U *perr)
{
OS_FLAGS flags_rdy; /*定義一個"準備完畢"含量值*/
INT8U result; /*結果*/
BOOLEAN consume; /*定義一個"清除"事件標誌位(儲存值)*/
#if OS_CRITICAL_METHOD == 3u /*中斷被設定為型別3*/
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL /*如果定義了安全性中斷*/
if (perr == (INT8U *)0) /*如果錯誤碼指標為空,呼叫安全中斷異常函式*/
{
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u /*進行引數檢查*//*有效化pgrp指標*/
if (pgrp == (OS_FLAG_GRP *)0) /*如果pgrp指標為空*/
{
*perr = OS_ERR_FLAG_INVALID_PGRP; /*將錯誤碼指標設定為OS_ERR_FLAG_INVALID_PGRP*/
return ((OS_FLAGS)0); /*返回0*/
}
#endif
if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) /*有效化事件控制塊型別 如果不是事件型別標誌*/
{
*perr = OS_ERR_EVENT_TYPE; /*將錯誤碼指標設定為OS_ERR_EVENT_TYPE*/
return ((OS_FLAGS)0); /*返回0*/
}
result = (INT8U)(wait_type & OS_FLAG_CONSUME); /*將wiat_type與OS_FLAG_COUNSUME進行與,結果存放在result中*/
if (result != (INT8U)0) /*判斷我們是否需要清除標誌。*/
{
wait_type &= ~OS_FLAG_CONSUME; /*不為0,需要清除,wait_type儲存其取反之後的值*/
consume = OS_TRUE; /*"清除"事件標誌位置1,需要對這個標誌清0*/
}
else /*result為0,不需要清除*/
{
consume = OS_FALSE; /*"清除"事件標誌位為0*/
}
/*$PAGE*/
*perr = OS_ERR_NONE; /*先將錯誤碼指標設定為無錯誤形式*/
OS_ENTER_CRITICAL(); /*關中斷(進入中斷)*/
switch (wait_type) /*判斷等待型別,根據型別不同,處理相應的程式碼*/
{
case OS_FLAG_WAIT_SET_ALL: /*等待選擇的所有位都置1,即所有指定事件標誌位清 (1)*/
flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); /*提取我們需要的位*/
if (flags_rdy == flags) /*必須匹配到我們需要的所有的位*/
{
if (consume == OS_TRUE) /*如果是消耗型的*/
{
pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /*將請求事件組中對應請求標誌位的位清零,消耗了事件*/
}
}
else /*沒有匹配到我們需要的所有的位,阻塞,等待事件標誌組完成或者是超時*/
{
*perr = OS_ERR_FLAG_NOT_RDY;/*將錯誤碼設定為標誌位位準備好型別*/
}
OS_EXIT_CRITICAL(); /*開中斷*/
break;
case OS_FLAG_WAIT_SET_ANY: /*如果等待型別為任意指定事件標誌位清(1)*/
flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags);
if (flags_rdy != (OS_FLAGS)0) /*看是否有任何設定為1的標誌*/
{
if (consume == OS_TRUE) /*如果是消耗型別*/
{
pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /*只清除我們需要的位*/
}
}
else
{
*perr = OS_ERR_FLAG_NOT_RDY; /*將錯誤型別設定為OS_ERR_FLAG_NOT_RDY*/
}
OS_EXIT_CRITICAL(); /*開中斷*/
break;
#if OS_FLAG_WAIT_CLR_EN > 0u /*允許生成 Wait on Clear 事件標誌程式碼*/
case OS_FLAG_WAIT_CLR_ALL: /* 等待型別為所有指定事件標誌位清 (0); */
flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags; /*只提取我們需要的位 */
if (flags_rdy == flags) {
if (consume == OS_TRUE)
{
pgrp->OSFlagFlags |= flags_rdy;
}
}
else
{
*perr = OS_ERR_FLAG_NOT_RDY;
}
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 */
}
} else {
*perr = OS_ERR_FLAG_NOT_RDY;
}
OS_EXIT_CRITICAL();
break;
#endif
default: /*預設情況下*/
OS_EXIT_CRITICAL();/*開中斷(退出中斷)*/
flags_rdy = (OS_FLAGS)0;/*將flags_rdy設定為0*/
*perr = OS_ERR_FLAG_WAIT_TYPE;/*錯誤碼設定為OS_ERR_FLAG_WAIT_TYPE*/
break;
}
return (flags_rdy);/*返回flags_rdy*/
}
#endif
大概流程圖為:
END
不足之處還望提醒,謝過~
相關推薦
OS_FLAG.C(1)
本篇介紹OS_FLAG.C中的檢測事件標誌組的標誌狀態函式OS_FLAGS OSFlagAccept (OS_FLAG_GRP *pgrp,OS_FLAGS flags,INT8U wait_type,INT8U *perr)檢測事件標誌組的標誌狀態函式:介紹一下wait
標準C++(1)
esp 數組 nbsp 重載 ostream names ++ 釋放內存 操作 一、引用 引用就是某一變量(目標)的一個別名,對引用的操作與對變量直接操作完全一樣。 引用的聲明方法:類型標識符 &引用名=目標變量名; 例: int& num; 引用類似
C++(1)——布林型別,名稱空間,變數宣告
適合有學習過C語言的基礎的小白來學習C++:C++比C語言多了bool型別,且C++在宣告變數的時候不需要像C語言那樣一定放在前面,變數隨用隨定義即可。C++輸出八進位制,十進位制,十六進位制和布林值分
OS_FLAG.C(2)
本篇介紹OS_FLAG.C檔案中的建立事件標誌組函式*OSFlagCreate (OS_FLAGS flags,INT8U *perr)和刪除事件標誌組函式 *OSFlagDel (OS_FLAG_GRP *pgrp,INT8U opt,INT8U *perr)。OS
OS_FLAG.C(3)
上篇我們介紹了建立和刪除事件標誌組函式,後來在接著看原始碼的時候,發現倒著來更有助於理解。所以後面幾篇我會選擇較為合適的方式來不定期更博,方便大家理解。1.介紹刪除節點函式OS_FlagUnlink (OS_FLAG_NODE *pnode):/*$PAGE*/ /*2018
C++(1):檔案和流
#include <fstream> #include <iostream> #include <string> using namespace std;
你好,C++(1)C++是什麼?C++的“前世今生”
The world is built on C++. ——Herb Sutter the chairman of the ISO C++ standards committee and chief native languages architect at Mic
《深入理解C指針》學習筆記(1)--- 指針之外
結構 def form 學習 編程 stdlib.h struct 一個 char C語言從誕生之初就非常善於和硬件打交道,經過這麽多年的發展之後,其靈活性和超強的特征是受到幾乎所有程序員的肯定。C語言的這種靈活性很大一部分程度來源與C指針,指針為C語言動態操控內存提供
C++代碼之坦克大戰(1)
過程 核心 形狀 正方 遍歷 public 開始 www 保存 對坦克大戰情有獨鐘是因為大學時候第一次參加程序設計比賽就做的這個遊戲。當時用的語言是Java,那個比賽讓我悟出了面向對象的強大之處,我也是從那時開始接觸設計模式的。對我而言,坦克大戰有著非同尋常的意義,所以
Cmake新手使用日記(1)【C++11下的初體驗】
pen 如何 其他 err ++ targe 使用 可執行文件 使用教程 第一次使用Cmake,搜索了很多使用教程,包括《Cmake實踐》、《Cmake手冊》等,但是在針對最新的C++11條件下編程還是會存在一點點問題,需要實驗很多次錯誤並搜索大量文章才能解決問題。這裏
c++ 數組的聲明(1)
引用 是個 spa [] ++ blog ptr ack 靜態數組 今天討論靜態數組的聲明。 首先給出四個聲明: int *ptrs[10]; int *refs[10] = / ? /; int (*Parray)[10] = &arr; int (&
c++ 函數(1)
row 引用傳參 修飾 尋址 概念 pan 但是 clu 過去 函數中,數組如何傳參? 整個數組傳過去是不可以的。自然聯想到指針和引用。 因為數組指針本質上就是多重指針,所以以下三種傳參方式都是可以的: void print(const int*); v
c++ 類(1)
blog mac main png urn std 操作 ring 對象 C++用類來描述對象,類是對現實世界中相似事物的抽象,同是“雙輪車”的摩托車和自行車,有共同點,也有許多不同點。“車”類是對摩托車、自行車、汽車等相同點的提取與抽象,如所示。 類的定義分為兩個部分:數
C++語言筆記系列之十八——虛函數(1)
自己 語言 數據類型 說明 出現 adium 重定義 angle rac 1.C++中的多態 (1)多態性:同一個函數的調用能夠進行不同的操作,函數重載是實現多態的一種手段。 (2)聯編:在編譯階段進行聯接。即是在編譯階段將一個函數的調用點和函數
C++學習(1):最大子段和(多種解法)
多少 問題: code namespace 數據 組成 amp using () 問題:給定由n個數(可能為負數)組成的序列a1,a2,a3,...,an,求該序列子段和的最大值。 第一種解法:(最容易考慮的方法,將所有的子段一一相加,然後比較) 1 #include&
C#類和結構(1)
mar 安全 類型安全 readline 參數 部分 public 方法的參數 play 1、結構功能特性? 實現代碼? 結構用struct關鍵字定義的,與類類似,但有本質區別。結構實質是一個值類型,它不需要對分配的。 結構的特性: (1)、結構作為參數傳遞時,是值傳遞。
C# 《一》基本知識 (1)
png 經歷 知識 通用 代碼 可執行 處理 環境 安全性 一、 .net Framework 編寫應用程序的過程 1、使用 .NET Framework 編寫應用程序,就是使用 .NET代碼庫編寫代碼(使用支持Framework的任何一種語言)。 2、為執
C# 《二》基本語法 (1)
數據 ogr 內容 -1 程序代碼 collect thread 部分 及其 1、C#程序結構 程序結構圖如下: 代碼中各個部分的意義 1、引用命名空間; 2、項目名或命名空間名; 3、Program 類: 4、Main函數;
C# 《四》表達式和運算符(1)
center key 操作 mes string src ring mage ons 1、表達式 1、將變量和字面值(在使用運算符時,它們都稱作操作數)與運算符組合起來就得到了表達式,它是計算的基本構件。 2、簡單的操作包括所有的基本數學操作,如加減乘除;還有專門用於處理布
C# 《五》流程控制(1)
generic ram div 執行 進行 運行 align strong c# 1、分支語句之 if 語句 1、流程控制語句是程序的核心部分,對任何一門編程語言來說都至關重要,是控制程序執行流向的基本語句。如果一門語言缺少了流程控制,就會缺少對程序流向的控制,就不能稱之為