新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > μC/OS-II的任務之間的通訊與同步

        μC/OS-II的任務之間的通訊與同步

        作者: 時間:2016-10-08 來源:網絡 收藏

        值得注意的是,在μC/OS-II中,信號量一旦建立就不能刪除了,因此也就不可能將一個已分配的任務控制塊再放回到空閑ECB鏈表中。如果有任務正在等待某個信號量,或者某任務的運行依賴于某信號量的出現時,刪除該任務是很危險的。

        程序清單L6.9建立一個信號量

        OS_EVENT*OSSemCreate(INT16Ucnt)

        {

        OS_EVENT*pevent;

        OS_ENTER_CRITICAL();

        pevent=OSEventFreeList;(1)

        if(OSEventFreeList!=(OS_EVENT*)0){(2)

        OSEventFreeList=(OS_EVENT*)OSEventFreeList->OSEventPtr;

        }

        OS_EXIT_CRITICAL();

        if(pevent!=(OS_EVENT*)0){(3)

        pevent->OSEventType=OS_EVENT_TYPE_SEM;(4)

        pevent->OSEventCnt=cnt;(5)

        OSEventWaitListInit(pevent);(6)

        }

        return(pevent);(7)

        }

        6.6.2 等待一個信號量,OSSemPend()

        程序清單L6.10是OSSemPend()函數的源代碼。它首先檢查指針pevent所指的任務控制塊是否是由OSSemCreate()建立的[L6.10(1)]。如果信號量當前是可用的(信號量的計數值大于0)[L6.10(2)],將信號量的計數值減1[L6.10(3)],然后函數將“無錯”錯誤代碼返回給它的調用函數。顯然,如果正在等待信號量,這時的輸出正是我們所希望的,也是運行OSSemPend()函數最快的路徑。

        如果此時信號量無效(計數器的值是0),OSSemPend()函數要進一步檢查它的調用函數是不是中斷服務子程序[L6.10(4)]。在正常情況下,中斷服務子程序是不會調用OSSemPend()函數的。這里加入這些代碼,只是為了以防萬一。當然,在信號量有效的情況下,即使是中斷服務

        子程序調用的OSSemPend(),函數也會成功返回,不會出任何錯誤。

        如果信號量的計數值為0,而OSSemPend()函數又不是由中斷服務子程序調用的,則調

        用OSSemPend()函數的任務要進入睡眠狀態,等待另一個任務(或者中斷服務子程序)發出該信

        號量(見下節)。OSSemPend()允許用戶定義一個最長等待時間作為它的參數,這樣可以避免該

        任務無休止地等待下去。如果該參數值是一個大于0的值,那么該任務將一直等到信號有效或

        者等待超時。如果該參數值為0,該任務將一直等待下去。OSSemPend()函數通過將任務控制塊

        中的狀態標志.OSTCBStat置1,把任務置于睡眠狀態[L6.10(5)],等待時間也同時置入任務控

        制塊中[L6.10(6)],該值在OSTimeTick()函數中被逐次遞減。注意,OSTimeTick()函數對每個

        任務的任務控制塊的.OSTCBDly域做遞減操作(只要該域不為0)[見3.10節,時鐘節拍]。真

        正將任務置入睡眠狀態的操作在OSEventTaskWait()函數中執行[見6.03節,讓一個任務等待

        某個事件,OSEventTaskWait()][L6.10(7)]。

        因為當前任務已經不是就緒態了,所以任務調度函數將下一個最高優先級的任務調入,準備運行[L6.10(8)]。當信號量有效或者等待時間到后,調用OSSemPend()函數的任務將再一次成為最高優先級任務。這時OSSched()函數返回。這之后,OSSemPend()要檢查任務控制塊中的狀態標志,看該任務是否仍處于等待信號量的狀態[L6.10(9)]。如果是,說明該任務還沒有被OSSemPost()函數發出的信號量喚醒。事實上,該任務是因為等待超時而由TimeTick()函數把它置為就緒狀態的。這種情況下,OSSemPend()函數調用 OSEventTO()函數將任務從等待任務列表中刪除[L6.10(10)],并返回給它的調用任務一個“超時”的錯誤代碼。如果任務的任務控制塊中的OS_STAT_SEM標志位沒有置位,就認為調用 OSSemPend()的任務已經得到了該信號量,將指向信號量ECB的指針從該任務的任務控制塊中刪除,并返回給調用函數一個“無錯”的錯誤代碼[L6.10(11)]。

        程序清單L6.10等待一個信號量

        voidOSSemPend(OS_EVENT*pevent,INT16Utimeout,INT8U*err)

        {

        OS_ENTER_CRITICAL();

        if(pevent->OSEventType!=OS_EVENT_TYPE_SEM){(1)

        OS_EXIT_CRITICAL();

        *err=OS_ERR_EVENT_TYPE;

        }

        if(pevent->OSEventCnt>0){(2)

        pevent->OSEventCnt--;(3)

        OS_EXIT_CRITICAL();

        *err=OS_NO_ERR;

        }elseif(OSIntNesting>0){(4)

        OS_EXIT_CRITICAL();

        *err=OS_ERR_PEND_ISR;

        }else{

        OSTCBCur->OSTCBStat|=OS_STAT_SEM;(5)

        OSTCBCur->OSTCBDly=timeout;(6)

        OSEventTaskWait(pevent);(7)

        OS_EXIT_CRITICAL();

        OSSched();(8)

        OS_ENTER_CRITICAL();

        if(OSTCBCur->OSTCBStatOS_STAT_SEM){(9)

        OSEventTO(pevent);(10)

        OS_EXIT_CRITICAL();

        *err=OS_TIMEOUT;

        }else{

        OSTCBCur->OSTCBEventPtr=(OS_EVENT*)0;(11)

        OS_EXIT_CRITICAL();

        *err=OS_NO_ERR;

        }

        }

        }

        6.6.3 發送一個信號量,OSSemPost()

        程序清單L6.11是OSSemPost()函數的源代碼。它首先檢查參數指針pevent指向的任務控制塊是否是OSSemCreate()函數建立的[L6.11(1)],接著檢查是否有任務在等待該信號量[L6.11(2)]。如果該任務控制塊中的.OSEventGrp域不是0,說明有任務正在等待該信號量。這時,就要調用函數OSEventTaskRdy()[見6.02節,使一個任務進入就緒狀態,OSEventTaskRdy()],把其中的最高優先級任務從等待任務列表中刪除[L6.11(3)]并使它進入就緒狀態。然后,調用OSSched()任務調度函數檢查該任務是否是系統中的最高優先級的就緒任務[L6.11(4)]。如果是,這時就要進行任務切換[當OSSemPost()函數是在任務中調用的],準備執行該就緒任務。如果不是,OSSched()直接返回,調用 OSSemPost()的任務得以繼續執行。如果這時沒有任務在等待該信號量,該信號量的計數值就簡單地加1[L6.11(5)]。

        上面是由任務調用OSSemPost()時的情況。當中斷服務子程序調用該函數時,不會發生上面的任務切換。如果需要,任務切換要等到中斷嵌套的最外層中斷服務子程序調用OSIntExit()函數后才能進行(見3.09節,μC/OS-II中的中斷)。



        關鍵詞:

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 呼玛县| 铜山县| 娄底市| 阿坝| 凤山市| 宜阳县| 乌审旗| 潜江市| 鹤山市| 泸溪县| 垣曲县| 缙云县| 顺昌县| 江陵县| 钦州市| 揭阳市| 宁国市| 常州市| 阳曲县| 平安县| 揭东县| 芮城县| 民乐县| 增城市| 于都县| 孟连| 安丘市| 游戏| 兴山县| 白朗县| 海盐县| 大方县| 时尚| 上杭县| 遵义县| 武安市| 抚宁县| 平定县| 化德县| 南汇区| 宜兴市|