新聞中心

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

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

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

        另外,消息隊列一旦建立就不能再刪除了。試想,如果有任務正在等待某個消息隊列中的消息,而此時又刪除該消息隊列,將是很危險的。

        程序清單L6.21建立一個消息隊列

        OS_EVENT*OSQCreate(void**start,INT16Usize)

        {

        OS_EVENT*pevent;

        OS_Q*pq;

        OS_ENTER_CRITICAL();

        pevent=OSEventFreeList;(1)

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

        OSEventFreeList=(OS_EVENT*)OSEventFreeList->OSEventPtr;(2)

        }

        OS_EXIT_CRITICAL();

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

        OS_ENTER_CRITICAL();

        pq=OSQFreeList;(3)

        if(OSQFreeList!=(OS_Q*)0){

        OSQFreeList=OSQFreeList->OSQPtr;

        }

        OS_EXIT_CRITICAL();

        if(pq!=(OS_Q*)0){

        pq->OSQStart=start;(4)

        pq->OSQEnd=start[size];

        pq->OSQIn=start;

        pq->OSQOut=start;

        pq->OSQSize=size;

        pq->OSQEntries=0;

        pevent->OSEventType=OS_EVENT_TYPE_Q;(5)

        pevent->OSEventPtr=pq;(6)

        OSEventWaitListInit(pevent);(7)

        }else{

        OS_ENTER_CRITICAL();

        pevent->OSEventPtr=(void*)OSEventFreeList;(8)

        OSEventFreeList=pevent;

        OS_EXIT_CRITICAL();

        pevent=(OS_EVENT*)0;

        }

        }

        return(pevent);(9)

        }

        6.8.2 等待一個消息隊列中的消息,OSQPend()

        程序清單L6.22是OSQPend()函數的源代碼。OSQPend()函數首先檢查事件控制塊是否是由OSQCreate()函數建立的[L6.22(1)],接著,該函數檢查消息隊列中是否有消息可用(即.OSQEntries是否大于0) [L6.22(2)]。 如果有, OSQPend()函數將指向消息的指針復制到msg變量中, 并讓.OSQOut指針指向隊列中的下一個單元[L6.22(3)],然后將隊列中的有效消息數減1[L6.22(4)]。因為消息隊列是一個循環的緩沖區,OSQPend()函數需要檢查.OSQOut是否超過了

        隊列中的最后一個單元[L6.22(5)]。當發生這種越界時,就要將.OSQOut重新調整到指向隊列的起始單元[L6.22(6)]。這是我們調用OSQPend()函數時所期望的,也是執行OSQPend()函數最快的路徑。

        程序清單L6.22在一個消息隊列中等待一條消息

        void*OSQPend(OS_EVENT*pevent,INT16Utimeout,INT8U*err)

        {

        void*msg;

        OS_Q*pq;

        OS_ENTER_CRITICAL();

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

        OS_EXIT_CRITICAL();

        *err=OS_ERR_EVENT_TYPE;

        return((void*)0);

        }

        pq=pevent->OSEventPtr;

        if(pq->OSQEntries!=0){(2)

        msg=*pq->OSQOut++;(3)

        pq->OSQEntries--;(4)

        if(pq->OSQOut==pq->OSQEnd){(5)

        pq->OSQOut=pq->OSQStart;(6)

        }

        OS_EXIT_CRITICAL();

        *err=OS_NO_ERR;

        }elseif(OSIntNesting>0){(7)

        OS_EXIT_CRITICAL();

        *err=OS_ERR_PEND_ISR;

        }else{

        OSTCBCur->OSTCBStat|=OS_STAT_Q;(8)

        OSTCBCur->OSTCBDly=timeout;

        OSEventTaskWait(pevent);

        OS_EXIT_CRITICAL();

        OSSched();(9)

        OS_ENTER_CRITICAL();

        if((msg=OSTCBCur->OSTCBMsg)!=(void*)0){(10)

        OSTCBCur->OSTCBMsg=(void*)0;

        OSTCBCur->OSTCBStat=OS_STAT_RDY;

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

        OS_EXIT_CRITICAL();

        *err=OS_NO_ERR;

        }elseif(OSTCBCur->OSTCBStatOS_STAT_Q){(12)

        OSEventTO(pevent);(13)

        OS_EXIT_CRITICAL();

        msg=(void*)0;(14)

        *err=OS_TIMEOUT;

        }else{

        msg=*pq->OSQOut++;(15)

        pq->OSQEntries--;

        if(pq->OSQOut==pq->OSQEnd){

        pq->OSQOut=pq->OSQStart;

        }

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

        OS_EXIT_CRITICAL();

        *err=OS_NO_ERR;

        }

        }

        return(msg);(17)

        }

        如果這時消息隊列中沒有消息(.OSEventEntries是0),OSQPend()函數檢查它的調用者是否是中斷服務子程序[L6.22(7)]。象OSSemPend()和OSMboxPend()函數一樣,不能在中斷服務子程序中調用OSQPend(), 因為中斷服務子程序是不能等待的。 但是, 如果消息隊列中有消息,即使從中斷服務子程序中調用OSQPend()函數,也一樣是成功的。

        如果消息隊列中沒有消息,調用OSQPend()函數的任務被掛起[L6.22(8)]。當有其它的任

        務向該消息隊列發送了消息或者等待時間超時,并且該任務成為最高優先級任務時,OSSched()

        返回[L6.22(9)]。這時,OSQPend()要檢查是否有消息被放到該任務的任務控制塊中[L6.22(10)]。如果有,那么該次函數調用成功,把任務的任務控制塊中指向消息隊列的指針刪除[L6.22(17)],并將對應的消息被返回到調用函數[L6.22(17)]。

        在OSQPend()函數中,通過檢查任務的任務控制塊中的.OSTCBStat域,可以知道是否等到時間超時。如果其對應的OS_STAT_Q位被置1,說明任務等待已經超時[L6.22(12)]。這時,通過調用函數OSEventTo()可以將任務從消息隊列的等待任務列表中刪除[L6.22(13)]。這時,因為消息隊列中沒有消息,所以返回的指針是NULL[L6.22(14)]。

        如果任務控制塊標志位中的OS_STAT_Q位沒有被置1,說明有任務發出了一條消息。

        OSQPend()函數從隊列中取出該消息[L6.22(15)]。然后,將任務的任務控制中指向事件控制塊的指針刪除[L6.22(16)]。

        6.8.3 向消息隊列發送一個消息(FIFO),OSQPost()

        程序清單L6.23是OSQPost()函數的源代碼。在確認事件控制塊是消息隊列后

        [L6.23(1)],OSQPost()函數檢查是否有任務在等待該消息隊列中的消息[L6.23(2)]。當事件控



        關鍵詞:

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 恩平市| 大荔县| 泰来县| 龙游县| 通辽市| 抚州市| 五家渠市| 靖州| 昌黎县| 廉江市| 邵武市| 阿勒泰市| 柘荣县| 丰县| 甘洛县| 门源| 诸暨市| 德化县| 屯昌县| 新竹市| 锡林浩特市| 江西省| 河源市| 措勤县| 天等县| 宜丰县| 壶关县| 象山县| 万山特区| 长白| 公主岭市| 新泰市| 邵阳市| 浦北县| 漳州市| 繁峙县| 吴旗县| 宿迁市| 武威市| 鹿邑县| 湟源县|