1. 程式人生 > >UCOS系統學習記錄1 OSSemCreate(INT16U cnt)函式使用方法

UCOS系統學習記錄1 OSSemCreate(INT16U cnt)函式使用方法

 

ucos-II中,為了實現任務之間的同步,用到的同步機制有:訊號量,郵箱和訊息佇列。其中這裡我主要說下對訊號量的使用經驗。

訊號量在建立時,呼叫OSSemCreate(INT16U cnt)函式。

cnt為訊號量的初始值。對cnt賦予不同的值,所起到的作用不同。如果Semp = OSSemCreate(0), 該訊號量表示等待一個事件或者多個事件的發生。

如果我們想對一個公共資源進行互斥訪問,例如:

如果我們想讓兩個任務Task1和Task2都可以呼叫Fun()函式,但不能同時呼叫,最好定義Semp = OSSemCreate(1),同理在各自的任務中都需要呼叫OSSemPend(Semp,0,&err)請求此訊號量

,如果可用,則呼叫Fun(),然後再呼叫OSSemPost(Semp)釋放該訊號量。這裡就實現了一個資源的互斥訪問。(注:初始化OSSemCreate(1),那麼一個任務中有OSSemPend,那麼可以執行,執行之後cnt==0,其他任務的OSSemPend無法獲得sem,只能等待,除非任務一有OSSemPost,使其cnt++,這樣其他任務的Pend可以執行。)

同理,如果一個任務要等待n個事件發生後才能執行,則應定義為Semp = OSSemCreate(n)。然後在這n個任務分別執行時呼叫OSSemPost(Semp),直到這n個事件均發生後,這個任務才能執行。
OSSemCreate(cnt)賦初始值cnt,OSSemPend一次,cnt-- 一次,OSSemPost一次,cnt++一次。


1、OSSemCreate (0);
......
OS_EVENT *Fun_Semp;
......
Fun_Semp = OSSemCreate (0);
......
void  MyTask (void *pdata)
{
.....
    for (;;) 
    {                                           
        OSSemPend(Fun_Semp,0,&err); //請求訊號量
   PC_DispStr(0,++y,  s1,  DISP_BGND_BLACK+DISP_FGND_WHITE );
        OSTimeDlyHMSM(0, 0, 1, 0);    //等待1秒
    }
}
......
void  YouTask (void *pdata)
{
......
    for (;;) 
    {           
     PC_DispStr(0,++y,  s2,  DISP_BGND_BLACK+DISP_FGND_WHITE );
     if(YouTaskRun==5)
           OSSemPost(Fun_Semp);  //傳送訊號量
     YouTaskRun++;            
       OSTimeDlyHMSM(0, 0, 2, 0);    //等待2秒
    }
}
在上例中,MyTask 一直在等待訊號量,在訊號量沒有到來之前無法執行。只有在YouTask 運行了5次,YouTaskRun==5之後,OSSemPost(Fun_Semp);  //傳送訊號量,MyTask 才得以執行。

如果按上例所示,MyTask 只能執行一次,因為YouTask 以後再也不可能使得YouTaskRun==5了。MyTask 也就因為無法得到訊號量而不能執行。


2、OSSemCreate (1);
.....
OS_EVENT *Fun_Semp;
.....
Fun_Semp = OSSemCreate (1);
.....
void  MyTask (void *pdata)
{
..... 
    for (;;) 
    {                                           
        OSSemPend(Fun_Semp,0,&err); //請求訊號量
   PC_DispStr(0,++y,  s1,  DISP_BGND_BLACK+DISP_FGND_WHITE );
   OSSemPost(Fun_Semp);  //傳送訊號量
        OSTimeDlyHMSM(0, 0, 1, 0);    //等待1秒
    }
}
void  YouTask (void *pdata)
{
    for (;;) 
    {                                           
        OSSemPend(Fun_Semp,0,&err); //請求訊號量
   PC_DispStr(0,++y,  s2,  DISP_BGND_BLACK+DISP_FGND_WHITE );
   OSSemPost(Fun_Semp);  //傳送訊號量            
        OSTimeDlyHMSM(0, 0, 2, 0);    //等待2秒
    }
}
在上例中,MyTask、YouTask 都在 等待訊號量,由於MyTask優先順序高,首先得到訊號量開始執行。此時YouTask 還在等待訊號量。MyTask 執行完畢,OSSemPost(Fun_Semp);  //傳送訊號量。YouTask 得到訊號量執行後傳送訊號量,如此反覆。