1. 程式人生 > >OS_FLAG.C(2)

OS_FLAG.C(2)

本篇介紹OS_FLAG.C檔案中的建立事件標誌組函式*OSFlagCreate (OS_FLAGS  flags,INT8U *perr)和刪除事件標誌組函式 *OSFlagDel (OS_FLAG_GRP  *pgrp,INT8U  opt,INT8U  *perr)。

OS_FLAG_GRP  *OSFlagCreate (OS_FLAGS  flags,INT8U    *perr)建立事件標誌組:

/*$PAGE*/
/*
*********************************************************************************************************
*                                           CREATE AN EVENT FLAG
*												建立事件標誌組
* Description: This function is called to create an event flag group.
*描述:該函式是用來建立一個事件標誌組。
* Arguments  : flags         Contains the initial value to store in the event flag group.
*引數:						--flags:事件標誌組的事件標誌初值
*              perr          is a pointer to an error code which will be returned to your application:
*                               OS_ERR_NONE               if the call was successful.
*                               OS_ERR_CREATE_ISR         if you attempted to create an Event Flag from an
*                                                         ISR.
*                               OS_ERR_FLAG_GRP_DEPLETED  if there are no more event flag groups
*							--perr:指向錯誤碼的指標,該指標將會返回到你的應用程式中。
									OS_ERR_NONE:無錯誤型別,說明呼叫成功。
									OS_ERR_CREATE_ISR:從中斷中建立一個事件標誌
									OS_ERR_FLAG_GRP_DEPLETED:如果系統中沒有剩餘的空閒事件標誌組,需要更改OS_CFG.H中的事件標誌組數目配置
* Returns    : A pointer to an event flag group or a NULL pointer if no more groups are available.
*返回值:指向事件標誌組的指標,如果沒有可以返回的可用指標,返回null。
* Called from: Task ONLY
只能被任務呼叫
*********************************************************************************************************
*/

OS_FLAG_GRP  *OSFlagCreate (OS_FLAGS  flags,
                            INT8U    *perr)
{
    OS_FLAG_GRP *pgrp;						/*指向事件標誌組的指標*/
#if OS_CRITICAL_METHOD == 3u               /*中斷型別被設定為3*/
    OS_CPU_SR    cpu_sr = 0u;
#endif

#ifdef OS_SAFETY_CRITICAL					/*如果定義了安全中斷*/
    if (perr == (INT8U *)0)					/*如果錯誤碼為0*/
	{
        OS_SAFETY_CRITICAL_EXCEPTION();		/*呼叫安全中斷異常函式*/
    }
#endif

#ifdef OS_SAFETY_CRITICAL_IEC61508
    if (OSSafetyCriticalStartFlag == OS_TRUE) 
	{
        OS_SAFETY_CRITICAL_EXCEPTION();
    }
#endif

    if (OSIntNesting > 0u) /* 如果是從中斷函式呼叫 */
	{                        
        *perr = OS_ERR_CREATE_ISR;	 /* 將錯誤碼指標設定為OS_ERR_CREATE_ISR,不能從中斷函式呼叫 */
        return ((OS_FLAG_GRP *)0);	/*返回0*/
    }
    OS_ENTER_CRITICAL();			/*關中斷(進入中斷)*/
    pgrp = OSFlagFreeList;          /*pgrp指向空閒事件標誌列表,來得到一個空閒事件標誌組*/ 
    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;           /*等待任務連結表指標初始化為NULL*/
		#if OS_FLAG_NAME_EN > 0u					/*如果標誌有名字的話,將名字初始化為未命名*/
				pgrp->OSFlagName     = (INT8U *)(void *)"?";
		#endif
        OS_EXIT_CRITICAL();							/*退出中斷*/
        *perr                = OS_ERR_NONE;			/*將錯誤型別設定為OS_ERR_NONE*/
    } 
	else							/*沒有空閒的事件標誌組*/
	{
        OS_EXIT_CRITICAL();			/*退出中斷*/
        *perr                = OS_ERR_FLAG_GRP_DEPLETED;/*將錯誤碼設定為OS_ERR_FLAG_GRP_DEPLETED*/
    }
    return (pgrp);                                  /* Return pointer to event flag group              */
}

流程圖如下:


其中,上面的“進行相應處理”為:


這四個步驟對應程式碼為:

 OSFlagFreeList       = (OS_FLAG_GRP *)OSFlagFreeList->OSFlagWaitList; /*分配後,調整系統空閒事件標誌組連結串列指標*/
        pgrp->OSFlagType     = OS_EVENT_TYPE_FLAG;  /* 將標誌型別設定為事件標誌型別*/
        pgrp->OSFlagFlags    = flags;               /* 事件標誌初始化*/
        pgrp->OSFlagWaitList = (void *)0;           /*等待任務連結表指標初始化為NULL*/

刪除事件標誌組函式:   *OSFlagDel (OS_FLAG_GRP  *pgrp,INT8U  opt,INT8U  *perr)

/*$PAGE*/
/*
*********************************************************************************************************
*                                     DELETE AN EVENT FLAG GROUP
*										刪除事件標誌組
* Description: This function deletes an event flag group and readies all tasks pending on the event flag
*              group.
*描述:該功能刪除事件標誌組並且將事件標誌組中所有掛起的任務設為就緒
* Arguments  : pgrp          is a pointer to the desired event flag group.
*引數:						--pgrp:指向事件標誌組的指標
*              opt           determines delete options as follows:
*                            opt == OS_DEL_NO_PEND   Deletes the event flag group ONLY if no task pending
*                            opt == OS_DEL_ALWAYS    Deletes the event flag group even if tasks are
*                                                    waiting.  In this case, all the tasks pending will be
*                                                    readied.
*							--opt:刪除的方式可以有以下幾種選擇:
								   OS_DEL_NO_PEND:只有當沒有任務掛起時才能刪除事件標誌組
								   OS_DEL_ALWAYS:即使任務處於等待狀態,也要刪除事件標誌組。這種情況下所有掛起的任務將會處於就緒態。
*              perr          is a pointer to an error code that can contain one of the following values:
*                            OS_ERR_NONE               The call was successful and the event flag group was deleted
*                            OS_ERR_DEL_ISR            If you attempted to delete the event flag group from an ISR
*                            OS_ERR_FLAG_INVALID_PGRP  If 'pgrp' is a NULL pointer.
*                            OS_ERR_EVENT_TYPE         If you didn't pass a pointer to an event flag group
*                            OS_ERR_INVALID_OPT        An invalid option was specified
*                            OS_ERR_TASK_WAITING       One or more tasks were waiting on the event flag
*                                                      group.
*							--perr:指向錯誤碼的指標,該指標可以設定為以下值:
									OS_ERR_NONE:呼叫成功,事件標誌組被刪除
									OS_ERR_DEL_ISR:嘗試從中斷中呼叫刪除函式
									OS_ERR_FLAG_INVALID_PGRP:如果pgrp為空指標
									OS_ERR_EVENT_TYPE:pgrp不是指向事件標誌組的指標;
									OS_ERR_INVALID_OPT:opt引數不是指定的值;
									OS_ERR_TASK_WAITING:如果opt引數為OS_DEL_NO_PEND,那麼此時有任務等待事件標誌組
* Returns    : pgrp          upon error
*              (OS_EVENT *)0 if the event flag group was successfully deleted.
*返回值:如果事件標誌組被刪除,組則返回空指標;
		如果沒有刪除,則仍然返回指向該事件標誌組的指標。
		後一種情況需要檢查出錯程式碼,找出事件標誌的失敗的原因。
* Note(s)    : 1) This function must be used with care.  Tasks that would normally expect the presence of
*                 the event flag group MUST check the return code of OSFlagAccept() and OSFlagPend().
*              2) This call can potentially disable interrupts for a long time.  The interrupt disable
*                 time is directly proportional to the number of tasks waiting on the event flag group.
	註釋:1)該功能需要小心使用,期望事件標誌組的任務一定要檢測OSFlagAccept()和OSFlagPend()兩個函式的返回碼。
		  2)該函式有可能長時間關閉中斷,其時間長短決定於標誌組的任務個數。
*********************************************************************************************************
*/

#if OS_FLAG_DEL_EN > 0u
OS_FLAG_GRP  *OSFlagDel (OS_FLAG_GRP  *pgrp,
                         INT8U         opt,
                         INT8U        *perr)
{
    BOOLEAN       tasks_waiting;		/*有等待任務標誌*/
    OS_FLAG_NODE *pnode;				/*標誌節點*/
    OS_FLAG_GRP  *pgrp_return;			/*返回指標*/
#if OS_CRITICAL_METHOD == 3u          
    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					/*檢查引數*/
    if (pgrp == (OS_FLAG_GRP *)0)		/*有效化pgrp*/
	{                       
        *perr = OS_ERR_FLAG_INVALID_PGRP;
        return (pgrp);
    }
#endif
    if (OSIntNesting > 0u)		/*看是否從中斷中呼叫的*/
	{                               
        *perr = OS_ERR_DEL_ISR;     
        return (pgrp);
    }
    if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) /*有效化事件組型別*/
	{       
        *perr = OS_ERR_EVENT_TYPE;
        return (pgrp);
    }
    OS_ENTER_CRITICAL();		/*進入中斷*/
    if (pgrp->OSFlagWaitList != (void *)0) /*看任務正在等待事件標誌是否為空*/
	{  
        tasks_waiting = OS_TRUE;          /*有*/
    }
	else
	{
        tasks_waiting = OS_FALSE;	     /*無*/
    }
    switch (opt)			/*選擇刪除的方式*/
	{
        case OS_DEL_NO_PEND:          /*無任務掛起才刪除*/
             if (tasks_waiting == OS_FALSE)			/*沒有任務正在等待*/
			 {
				#if OS_FLAG_NAME_EN > 0u
								 pgrp->OSFlagName     = (INT8U *)(void *)"?";/*名稱初始化*/
				#endif
                 pgrp->OSFlagType     = OS_EVENT_TYPE_UNUSED;/*標誌型別設定為未被使用*/
                 pgrp->OSFlagWaitList = (void *)OSFlagFreeList; /*將該事件標誌組加入到事件標誌組空閒連結串列中*/
                 pgrp->OSFlagFlags    = (OS_FLAGS)0;			/*將標誌位設為0*/
                 OSFlagFreeList       = pgrp;					/*空閒列表指標指向新的(進行過刪除事件標誌組函式)連結串列*/
                 OS_EXIT_CRITICAL();							/*退出中斷*/
                 *perr                = OS_ERR_NONE;			/*錯誤型別設定為無錯誤型別*/
                 pgrp_return          = (OS_FLAG_GRP *)0;  /*事件標誌組已經被刪除,因而返回為0*/
             } 
			 else					/*有任務正在等待*/
			 {
                 OS_EXIT_CRITICAL();/*退出中斷*/
                 *perr                = OS_ERR_TASK_WAITING;/*將錯誤型別設定為OS_ERR_TASK_WAITING*/
                 pgrp_return          = pgrp;				/*將pgrp賦給pgrp_return*/
             }
             break;

        case OS_DEL_ALWAYS:        /*如果為無論有沒有掛起,都刪除*/
             pnode = (OS_FLAG_NODE *)pgrp->OSFlagWaitList; /*指向等待事件組的節點連結串列*/
             while (pnode != (OS_FLAG_NODE *)0)			   /*遍歷該連結串列*/
			 {          
                 (void)OS_FlagTaskRdy(pnode, (OS_FLAGS)0);	/*將該連結串列中的節點指向的任務轉為就緒狀態*/
                 pnode = (OS_FLAG_NODE *)pnode->OSFlagNodeNext;
             }
			#if OS_FLAG_NAME_EN > 0u							/*如果有名字,將名字初始化*/
						 pgrp->OSFlagName     = (INT8U *)(void *)"?";
			#endif
             pgrp->OSFlagType     = OS_EVENT_TYPE_UNUSED;	/*將標誌型別設定為未使用型別*/
             pgrp->OSFlagWaitList = (void *)OSFlagFreeList;/* 將該組返回到空閒列表中*/
             pgrp->OSFlagFlags    = (OS_FLAGS)0;
             OSFlagFreeList       = pgrp;
             OS_EXIT_CRITICAL();							/*退出中斷*/
             if (tasks_waiting == OS_TRUE) {               /*如果之前是有任務在等待事件標誌組*/
                 OS_Sched();                               /*進行排程(執行最高優先順序的任務)*/
             }
             *perr = OS_ERR_NONE;							/*將錯誤型別設定為無錯誤型別*/
             pgrp_return          = (OS_FLAG_GRP *)0;      /* 事件標誌組已經被刪除,返回空*/
             break;

        default:											/*其他情況下*/
             OS_EXIT_CRITICAL();							/*退出中斷*/
             *perr                = OS_ERR_INVALID_OPT;		/*將錯誤碼設定為OS_ERR_INVALID_OPT*/
             pgrp_return          = pgrp;					/*將pgrp賦值給pgrp_return*/
             break;
    }
    return (pgrp_return);	/*返回pgrp_return*/							
}
#endif

刪除函式流程圖為:


其中,刪除操作為(針對OS_DEL_NO_PEND刪除型別):


如果刪除型別是OS_DEL_ALWAYS:則在上述操作步驟之前加一個:將等待事件組的節點連結串列中的節點指向的任務轉為就緒狀態。

對應的程式碼段為:

#if OS_FLAG_NAME_EN > 0u
	pgrp->OSFlagName     = (INT8U *)(void *)"?";/*名稱初始化*/
#endif
pgrp->OSFlagType     = OS_EVENT_TYPE_UNUSED;/*標誌型別設定為未被使用*/
pgrp->OSFlagWaitList = (void *)OSFlagFreeList; /*將該事件標誌組加入到事件標誌組空閒連結串列中*//*下圖<1>*/
pgrp->OSFlagFlags    = (OS_FLAGS)0;			/*將標誌位設為0*/
OSFlagFreeList       = pgrp;			/*空閒列表指標指向新的(進行過刪除事件標誌組函式)連結串列*//*下圖2*/

可能直接理解有點困難,我們圖解一下:


上圖即從原始狀態經過程式之後的轉化狀態。<1><2>對應的程式碼上面註釋也寫清楚了。

相關推薦

OS_FLAG.C2

本篇介紹OS_FLAG.C檔案中的建立事件標誌組函式*OSFlagCreate (OS_FLAGS  flags,INT8U *perr)和刪除事件標誌組函式 *OSFlagDel (OS_FLAG_GRP  *pgrp,INT8U  opt,INT8U  *perr)。OS

Python呼叫採用Boost Python封裝的c++2

     上次我寫了利用Python提供的API封裝c函式,並呼叫。但是由於利用API的方式過於原始,對於類或者結構極度麻煩。因此,我選擇了Boost的Python的來封裝類,類似的工具還有SWIG等,

OS_FLAG.C1

本篇介紹OS_FLAG.C中的檢測事件標誌組的標誌狀態函式OS_FLAGS  OSFlagAccept (OS_FLAG_GRP  *pgrp,OS_FLAGS flags,INT8U wait_type,INT8U *perr)檢測事件標誌組的標誌狀態函式:介紹一下wait

OS_FLAG.C3

上篇我們介紹了建立和刪除事件標誌組函式,後來在接著看原始碼的時候,發現倒著來更有助於理解。所以後面幾篇我會選擇較為合適的方式來不定期更博,方便大家理解。1.介紹刪除節點函式OS_FlagUnlink (OS_FLAG_NODE *pnode):/*$PAGE*/ /*2018

C語言代碼訓練營2

周末 int main 基本 之前 lin 例題 鏈接 params 上一篇的評論中,大家反饋評論中貼代碼無法排版。我們改一下規則,大家可以把自己實現的代碼發布在自己的簡書博文中,之後把鏈接貼在評論中。這樣也方便大家日後追溯。 當然,也可以直接發郵件給我。希望大家堅持打卡,

c++的const小總結2

通過 con 其他 綁定 strong col 指針和引用 兩個 tle c++的const小總結(1) http://www.cnblogs.com/MyNameIsPc/p/7091631.html 頂層const和底層cnost 先憑經驗區分一下兩者的區別?

C++14系列2:C/C++的時間函數

復習 -a 執行時間 htm 結果 down pro addclass data- C++筆記開始 為了好好研究下C++14。順便復習下曾經的C++知識。搞了個git(不斷完好中): https://github.com/rododo/cpp14ex

C# 《四》表達式和運算符2

技術分享 -a 按位運算 表達式 其他 img 數學 tro .cn 1、位運算符 1、位(bit):在計算中存儲所有數據都采用二進制,那麽二進制的位,便是我們所說的 bit。 1)1Byte = 8bit 1字節 = 8位 2)1k =10

c#基礎知識2

alt 實現 height over 聯系 c# 覆蓋 tro strong 一,繼承與派生 原來的類——基類或父類 新定義的類——派生類 引入原因:擴展原有類的功能 派生類的成員: (1)會吸收基類的所有成員(包括私有成

樹莓派進階之路 (032) -字符問題2 - 用c語言怎樣得到一個漢字的GB2312編碼(轉)

十六進制 字符串 c++ gb2 十進制 轉換 tails 表示 blog C/C++支持的是ASCII,不過漢字編碼中,GB2312與ASCII是兼容的,所以可以在C中獲得漢字的GB2312編碼 GB2312是兩個字節的,第一字節是高八位,第二字節是低八位,比如下面的程序

C# webApi----H5_app後臺制作2--參數的傳輸(對於懶得安分webApi參數傳輸不行的補充)

word func 2.0 object function log tty out 接收 (2)問題二:傳參的方式; http://www.cnblogs.com/landeanfen/p/5337072.html對於這篇文章的補充 測試一如下: 1)後端代碼如下, 註意

在STM32上實現NTFS之5:GPT分區表的C語言實現2GPT實現以及統一方式讀取磁盤分區

tfs 下載 數據 特殊 dpt 屬性列表 handle 系統分區 成了   上一節實現了主GPT頭的信息提取,這一節繼續提取整個的GPT數據,並且將GPT分區表和MBR分區表兩種格式融合成一個模塊,使主調函數(也可以說是使用者)不需要關心磁盤的分區表類型:它太底層了,確實

Halcon學習筆記2 VS2010 + Halcon12 C#鏈接相機

operator debug ets generic code locate != 目錄 empty 1.打開Halcon, 使用圖像采集助手獲取相機實時圖像:      1.1 獲取實時圖像:          1.2 插入采集實時圖像的Halcon代碼,並導出:    

C語言程序設計第六次作業——循環結構2.

是什麽 絕對值 方法 程序設計 輸入一個數 系列 發生 自己 很好 (一)改錯題 序列求和:輸入一個正實數eps,計算序列部分和 1 - 1/4 + 1/7 - 1/10 + ... ,精確到最後一項的絕對值小於eps(保留6位小數)。   輸入輸出樣例:   Input

C語言程序設計第六次作業——循環結構2

但是 n-1 輸入輸出 printf 控制 運行 進行 定義 small (一)改錯題 序列求和:輸入一個正實數eps,計算序列部分和 1 - 1/4 + 1/7 - 1/10 + ... ,精確到最後一項的絕對值小於eps(保留6位小數)。   輸入輸出樣例:   Inp

3.1、C#基礎 - C# 的 Hello World2

大小寫 我們 解釋 pre blog 分享 ref sharp 圖片 在上篇文章中,你跟著我寫了一個HelloWorld,本篇中,我們來談談一些C#程序中的小概念 1、C# 程序結構 一個 C# 程序主要包括以下部分: 命名空間聲明(Namespace declarati

C++中調用DLL中的函數2

釋放 工作 img .html 一個 log ++ 原型 獲取 轉自:http://blog.sina.com.cn/s/blog_53004b4901009h3b.html 應用程序使用DLL可以采用兩種方式: 一種是隱式鏈接,另一種是顯式鏈接。在使用DLL之前首先要

基於qml創建最簡單的圖像處理程序2-使用c++&qml進行圖像處理

.cn turn isnull 按鈕 編寫 可能 finish height 通過 《基於qml創建最簡單的圖像處理程序》系列課程及配套代碼基於qml創建最簡單的圖像處理程序(1)-基於qml創建界面http://www.cnblogs.com/jsxyhelu/p/83

c++ 日誌輸出庫 spdlog 簡介2

def 頻率 car ges invalid 輸出日誌 輸出結果 syn else 繼續上一篇,example.cpp解析。1、set_pattern 自定義日誌格式官方參考:https://github.com/gabime/spdlog/wiki/3.-Custom-f

C程序設計導引2

類型 使用 結果 邏輯或 滿足 default 邏輯與 及其 != 第3章 3.1 關系運算符和邏輯運算符 關系運算符 <、<=、>、>= 左端小於、小於等於、大於、大於等於右端時返回值為1,否則為0 ==、!= 左端等於、不等於右端