1. 程式人生 > >uCOSII學習筆記,不斷更新

uCOSII學習筆記,不斷更新

1、任務管理
任務的一般格式
void MyTask (void *pdata)
{
任務準備工作…
While(1)//死迴圈
{
任務MyTask實體程式碼;
OSTimeDlyHMSM(x,x,x,x);//呼叫任務延時函式,釋放cpu控制權,
}
}
任務優先順序
ucos中,每個任務都有唯一的一個優先順序。優先順序是任務的唯一標識。在UCOSII中,使用CPU的時候,優先順序高(數值小)的任務比優先順序低的任務具有優先使用權,即任務就緒表中總是優先順序最高的任務獲得CPU使用權,只有高優先順序的任務讓出CPU使用權(比如延時)時,低優先順序的任務才能獲得CPU使用權。UCOSII不支援多個任務優先順序相同,也就是每個任務的優先順序必須不一樣。l在建立任務的時候可以賦予優先順序,也可以更改。
INT8U OSTaskCreate (void (*task)(void *p_arg),void *p_arg,OS_STK *ptos,INT8U prio);
INT8U OSTaskChangePrio(INT8U oldprio,INT8U newprio);
這個函式之所以不需要指定修改哪個任務,是因為優先順序是任務的唯一標識,優先順序是多少就決定是了哪個任務。
任務就緒表
簡而言之就是用來記錄系統中所有處於就緒狀態的任務。它是一個位圖,系統中每個任務都在這個點陣圖中佔據一個進位制位,該位置的狀態(1或者0)就表示任務是否處於就緒狀態。
任務排程
作用一是在任務就緒表中查詢優先順序最高的就緒任務,二是實現任務的切換。比如說,當一個任務釋放cpu控制權後,進行一次任務排程,這個時候任務排程器首先要去任務就緒表查詢優先順序最高的就緒任務,查到之後,進行一次任務切換,轉而去執行下一個任務。
任務狀態
l睡眠狀態,任務在沒有被配備任務控制塊或被剝奪了任務控制塊時的狀態。
l就緒狀態,系統為任務配備了任務控制塊且在任務就緒表中進行了就緒登記,任務已經準備好了,但由於該任務的優先順序比正在執行的任務的優先順序低, 還暫時不能執行,這時任務的狀態叫做就緒狀態。
l執行狀態,該任務獲得CPU使用權,並正在執行中,此時的任務狀態叫做執行狀態。
l等待狀態,正在執行的任務,需要等待一段時間或需要等待一個事件發生再執行時,該任務就會把CPU的使用權讓給別的任務而使任務進入等待狀態。
l中斷服務狀態,一個正在執行的任務一旦響應中斷申請就會中止執行而去執行中斷服務程式,這時任務的狀態叫做中斷服務狀態。
UCOSII初始化:
OSInit();
對UCOSII自身執行環境初始化,包括所有全域性變數和資料結構初始化以及建立空閒任務。
UCOSII啟動
OSStart();
UCOSII呼叫此函式開始啟動任務管理。前提條件是呼叫 之前必須建立至少一個使用者任務。
任務延時函式OSTimeDly();
void OSTimeDly (INT32U ticks) ;
使當前任務執行延時(暫停)一段時間,並進行一次任務排程,以讓出cpu使用權。
取消任務延時函式OSTimeDlyResume();
INT8U OSTimeDlyResume (INT8U prio);
延時函式可通過在其他任務中呼叫此函式取消延時,從而進入就緒狀態。如果任務比正在執行的任務優先順序高,則引發一次排程。
INT8U OSTimeDlyHMSM(INT8U hours,
INT8U minutes,
INT8U seconds,
INT16U ms);
建立任務函式
如果想讓UCOSII管理使用者的任務,必須先建立任務。UCOSII提供了我們2個建立任務的函式:OSTaskCreat和OSTaskCreateExt,我們一般用OSTaskCreat函式來建立任務,該函式原型為:
OSTaskCreate(void(*task)(void*pd),void*pdata,OS_STK*ptos,INTU prio)。
該函式包括4個引數:
task:是指向任務程式碼的指標;
pdata:是任務開始執行時,傳遞給任務的引數的指標;
ptos:是分配給任務的堆疊的棧頂指標;
prio是分配給任務的優先順序。
每個任務都有自己的堆疊,堆疊必須申明為OS_STK型別,並且由連續的記憶體空間組成。可以靜態分配堆疊空間,也可以動態分配堆疊空間。
任務刪除函式
任務刪除,並不是把任務程式碼給刪除,而是把該任務控制塊從任務控制塊連結串列中刪除,並歸還給空任務控制塊連結串列,並且修改任務就緒表中狀態為0。刪除的任務不能再被排程器呼叫。也就是身份被吊銷了。
UCOSII提供的任務刪除函式原型為:
INT8U OSTaskDel(INT8U prio);
其中引數prio就是我們要刪除的任務的優先順序,可見該函式是通過任務優先順序來實現任務刪除的。
特別注意:任務不能隨便刪除,必須在確保被刪除任務的資源被釋放的前提下才能刪除!
請求任務刪除函式
前面提到,必須確保被刪除任務的資源被釋放的前提下才能將其刪除,所以我們通過向被刪除任務傳送刪除請求,來實現任務釋放自身佔用資源後再刪除。UCOSII提供的請求刪除任務函式原型為:
INT8U OSTaskDelReq(INT8U prio);
同樣還是通過優先順序來確定被請求刪除任務
發出刪除任務請求的任務和打算被時刪除的任務都必須呼叫 OSTaskDelReq() 函式
舉個例子:請求刪除其他任務的任務,設為 Task-1。
要被刪除的任務,設為 Task-2。其實就是 Task-1刪除Task-2.
Task-1 確定要刪除 Task-2,那麼Tak-1 發出刪除請求:OSTaskDelReq( TASK_TO_DEL_PRIO),其中 TASK_TO_DEL_PRIO 是 Task-2 的優先順序號,假設優先順序號在正常範圍內,Task-2 確實已經建立。
那麼,這樣一來,OS_TASK_DEL_REQ 標誌就會被存往 Task-2 的 TCB 中,程式碼見 OSTaskDelReq() 中的:
if (ptcb != (OS_TCB *)0)
{
ptcb->OSTCBDelReq = OS_TASK_DEL_REQ; /* 存刪除請求標誌*/
err = OS_NO_ERR;
}
當 OSTaskDelReq() 返回時,帶回的返回值是 OS_NO_ERR。(這與上面的假設成為因果)
表明請求已經被接受,但 TASK-2 還沒被刪除,所以 TASK-1 選擇等待。在我的試驗裡,Task1是個具體的任務,他的優先順序高,而task2的優先順序低,於是優先順序高的任務執行時,可以刪除task2.
當輪到 TASK-2 開始執行時,它也會呼叫 OSTaskDelReq( OS_PRIO_SELF ) 檢查自身。 這時,在OSTaskDelReq() 的 if( prio == OS_PRIO_SELF ) 程式塊中,從自己的 TCB中得到了之前所存的標誌:OS_TASK_DEL_REQ。這樣,TASK-2 已經確認了自己要被別的任務刪除了,所以接下來它就釋放所佔用的資源還有釋放所有的動態記憶體。完後,呼叫 OSTaskDel( OS_PRIO_SELF )刪除自身。
至此,假設 TASK-2 在刪除自身後,並沒有更高的優先順序任務出現,依然是 TASK-1 在執行。記得 TASK-1在傳送刪除請求時,是在一直迴圈等待著的,它等待的是一個叫做 OS_TASK_NOT_EXIT的標誌。所以,當再一次呼叫OSTaskDelReq() 時,由於OSTaskDelReq() 中的 if( ptcb != (OS_TCB*)0) 不成立( ptcb == (OS_TCB *)0 ),則理所當然的得到 OS_TASK_NOT_EXIT這個標誌。至此,TASK-1 成功完成了刪除 TASK-2 的任務。
要刪除別人的是這麼寫的:
If()
{
While(OSTaskDelReq(被刪的優先順序號)!=OS_TASK_NOT_Exist)
{
OSTimeDly(1);//這個有點就行
}
}
被刪的任務是這樣寫的:
If(OSTaskDelReq(OS_PRIO_SELF)==OS_TASK_DEL_REQ)
{
釋放所佔用的資源;//這裡才是重點
釋放動態記憶體;
OSTaskDel(OS_PRO_SELF);
}Else
{
其他程式碼!
}
//明白了吧,原來,這個函式是要用它的引數的,其實他並不去主動的釋放那些東西的。

他只是去做那些過程中事情。說白了,他就是i一個電話。
另外,如果沒有任何任務發出請求要刪除 TASK-2,而 TASK-2 只是在檢查自身是否要被刪除時,它得不到 OS_TASK_DEL_REQ 這個標誌,那麼就只能繼續執行自己的程式碼。

改變任務的優先順序函式
UCOSII在建立任務時,會分配給任務一個優先順序,但是這個優先順序並不是一成不變的,而是可以通過呼叫UCOSII提供的函式修改。UCOSII提供的任務優先順序修改函式原型為:
INT8U OSTaskChangePrio(INT8U oldprio,INT8U newprio);
任務掛起函式
任務掛起和任務刪除有點類似,但是又有區別,任務掛起只是將被掛起任務的就緒標誌刪除,並做任務掛起記錄,並沒有將任務控制塊任務控制塊連結串列裡面刪除,也不需要釋放其資源,而任務刪除則必須先釋放被刪除任務的資源,並將被刪除任務的任務控制塊也給刪了。被掛起的任務,在恢復(解掛)後可以繼續執行。UCOSII提供的任務掛起函式原型為:
INT8U OSTaskSuspend(INT8U prio);
任務恢復函式
有任務掛起函式,就有任務恢復函式,通過該函式將被掛起的任務恢復,讓排程器能夠重新排程該函式。UCOSII提供的任務恢復函式原型為:
INT8U OSTaskResume(INT8U prio);
任務資訊查詢
在應用程式中我們經常要了解任務資訊,查詢任務資訊函式原型為:
INT8U OSTaskQuery(INT8U prio,OS_TCB *pdata);
這個函式獲得的是對應任務的OS_TCB中內容的拷貝。
2、時間管理
時間管理的各個函式可以通過OS_CFG.H檔案中的幾個常量配置是否使用,常量如下:
任務中使用延時函式會交出CPU的使用權。
void OSTimeDly (INT32U ticks); //延時的長短根據指定的滴答個數來實現
INT8U OSTimeDlyHMSM (INT8U hours,//函式按照時分秒毫秒的時間格式實現延時
INT8U minutes,
INT8U seconds,
INT16U ms) //OS_TIME_DLY_HMSM_EN
INT8U OSTimeDlyResume (INT8U prio) //OS_TIME_DLY_RESUME_EN//函式可以恢復取消任務的延時,使其處於就緒狀態
INT32U OSTimeGet (void) //OS_TIME_GET_SET_EN//獲取滴答計數器值
void OSTimeSet (INT32U ticks) //OS_TIME_GET_SET_EN//修改滴答計數器值
注意:訪問OSTime時中斷是關掉的。
3、事件控制塊
任務或中斷服務子程式可以通過時間控制塊(ECB)向另外的任務發訊號,這裡“訊號”被看成是事件,所以用於中斷服務程式和任務之間通訊的資料結構叫做事件控制塊。
typedef struct os_event {
INT8U OSEventType; /* 事件型別*/
void OSEventPtr; /

等待任務所在的組*/
INT16U OSEventCnt; /計數器(當事件是訊號量時)/
OS_PRIO OSEventGrp; /指向訊息或者訊息佇列的指標/
OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /等待任務列表/
} OS_EVENT;
事件控制塊ECB是用於實現一下功能函式的基本資料結構,如:訊號量管理、互斥訊號量管理、訊息郵箱管理、訊息佇列管理等。
4、訊號量管理
要想使用訊號量,肯定需要先建立一個訊號量,我們使用函式 OSSemCreate()來建立訊號量,
函式原型如下:
void OSSemCreate ( OS_SEM *p_sem,CPU_CHAR *p_name,OS_SEM_CTR cnt,OS_ERR *p_err); //建立訊號量
p_sem: 指向訊號量控制塊,我們需要按照如下所示方式定義一個全域性訊號量,並將
這個訊號量的指標傳遞給函式 OSSemCreate()。
OS_SEM TestSem;
p_name: 指向訊號量的名字。
cnt: 設定訊號量的初始值,如果此值為 1,代表此訊號量為二進位制訊號量,如果大於 1
的話就代表此訊號量為計數型訊號量。
p_err: 儲存呼叫此函式後的返回的錯誤碼。

當一個任務需要獨佔式的訪問某個特定的系統資源時,需要與其他任務或中斷服務程式同
步,或者需要等待某個事件的發生,應該呼叫函式 OSSemPend(),函式原型如下:
OS_SEM_CTR OSSemPend ( OS_SEM *p_sem, OS_TICK timeout,OS_OPT opt, CPU_TS *p_ts, OS_ERR *p_err); //請求/等待一個訊號量
p_sem: 指向一個訊號量的指標。
timeout: 指定等待訊號量的超時時間(時鐘節拍數),如果在指定時間內沒有等到訊號量則
允許任務恢復執行。如果指定時間為 0 的話任務就會一直等待下去,直到等到訊號量。
opt: 用於設定是否使用阻塞模式,有下面兩個選項。
OS_OPT_PEND_BLOCKING 指定訊號量無效時,任務掛起以等待訊號量。
OS_OPT_PEND_NON_BLOCKING 訊號量無效時,任務直接返回。
p_ts: 指向一個時間戳,用來記錄接收到訊號量的時刻,如果給這個引數賦值 NULL,
則說明使用者沒有要求時間戳。
p_err: 儲存呼叫本函式後返回的錯誤碼。

任務獲得訊號量以後就可以訪問共享資源了,在任務訪問完共享資源以後必須釋放訊號量,
釋放訊號量也叫傳送訊號量,使用函式 OSSemPost()傳送訊號量。如果沒有任務在等待該訊號
量的話則 OSSemPost()函式只是簡單的將訊號量加 1,然後返回到呼叫該函式的任務中繼續執行。
如果有一個或者多個任務在等待這個訊號量,則優先順序最高的任務將獲得這個訊號量,然後由
排程器來判定剛獲得訊號量的任務是否為系統中優先順序最高的就緒任務,如果是,則系統將進
行任務切換,執行這個就緒任務,OSSemPost()函式原型如下:
OS_SEM_CTR OSSemPost ( OS_SEM *p_sem,OS_OPT opt,OS_ERR *p_err) //傳送一個訊號量、釋放訊號量
p_sem: 指向一個訊號量的指標
opt: 用來選擇訊號量傳送的方式。
OS_OPT_POST_1 僅向等待該訊號量的優先順序最高的任務傳送訊號量。
OS_OPT_POST_ALL 向等待該訊號量的所有任務傳送訊號量。
OS_OPT_POST_NO_SCHED 該選項禁止在本函式內執行任務排程操作。即使
該函式使得更高優先順序的任務結束掛起進入就緒狀態,也不會執行任務排程,而是會
在其他後續函式中完成任務排程。
p_err: 用來儲存呼叫此函式後返回的錯誤碼
INT16U OSSemAccept (OS_EVENT *pevent) //無等待的請求一個訊號量,當訊號量暫時無效時,任務簡單的返回而不是進入休眠等待狀態。
INT8U OSSemQuery (OS_EVENT *pevent, //查詢一個訊號量的狀態
OS_SEM_DATA *p_sem_data)
OS_EVENT *OSSemDel (OS_EVENT *pevent, //刪除一個訊號量
INT8U opt,
INT8U *perr)
注意:OSSemAccept() 、OSSemQuery() 、OSSemPost()函式可以由任務或者中斷服務子程式呼叫,而OSSemDel()、OSSemPend()只能由任務程式呼叫。

為了解決優先順序反轉的問題,系統引入了特殊訊號量“互斥訊號量”,互斥型訊號量只能用於任務,確保相關函式不能被中斷服務程式呼叫。
建立互斥訊號量使用函式 OSMutexCreate(),函式原型如下:
void OSMutexCreate (OS_MUTEX *p_mutex,CPU_CHAR *p_name,OS_ERR *p_err) //建立互斥訊號量,不允許中斷函式呼叫
p_mutex:指向互斥型訊號量控制塊。互斥型訊號量必須有使用者應用程式進行實際分配,可以使用如下所示程式碼。
OS_MUTEX MyMutex;
p_name: 互斥訊號量的名字
p_err: 呼叫此函式後返回的錯誤碼。
當一個任務需要對資源進行獨佔式訪問的時候就可以使用函式 OSMutexPend(),如果該互
斥訊號量正在被其他的任務使用,那麼 UCOSIII 就會將請求這個互斥訊號量的任務放置在這個
互斥訊號量的等待表中。任務會一直等待,直到這個互斥訊號量被釋放掉,或者設定的超時時
間到達為止。如果在設定的超時時間到達之前訊號量被釋放,UCOSIII 將會恢復所有等待這個
訊號量的任務中優先順序最高的任務。
注意!如果佔用該互斥訊號量的任務比當前申請該互斥訊號量的任務優先順序低的話,
OSMutexPend()函式會將佔用該互斥訊號量的任務的優先順序提升到和當前申請任務的優先順序一
樣。當佔用該互斥訊號量的任務釋放掉該互斥訊號量以後,恢復到之前的優先順序。OSMutexPend()
函式原型如下:
void OSMutexPend (OS_MUTEX *p_mutex,OS_TICK timeout,OS_OPT opt, CPU_TS *p_ts,OS_ERR *p_err) //掛起任務,請求/等待一個互斥訊號量,不允許在中斷程式中呼叫
p_mutex:指向互斥訊號量。
timeout:指定等待互斥訊號量的超時時間(時鐘節拍數),如果在指定的時間內互斥訊號量沒有釋放,則允許任務恢復執行。該值設定為 0 的話,表示任務將會一直等待下去,直到訊號量被釋放掉。
opt:用於選擇是否使用阻塞模式。
OS_OPT_PEND_BLOCKING 指定互斥訊號量被佔用時,任務掛起等待該互斥訊號量。
OS_OPT_PEND_NON_BLOCKING 指定當互斥訊號量被佔用時,直接返回任務。
注意!當設定為 OS_OPT_PEND_NON_BLOCKING,是 timeout 引數就沒有意義了,應該設定為 0。
p_ts:指向一個時間戳,記錄傳送、終止或刪除互斥訊號量的時刻。
p_err:用於儲存呼叫此函式後返回的錯誤碼。
我們可以通過呼叫函式 OSMutexPost()來釋放互斥型訊號量,只有之前呼叫過函式
OSMutexPend()獲取互斥訊號量,才需要呼叫 OSMutexPost()函式來釋放這個互斥訊號量,函式原型如下:
void OSMutexPost(OS_MUTEX *p_mutex,OS_OPT opt,OS_ERR *p_err) //傳送互斥訊號量、釋放互斥訊號量,不可被中斷服務程式呼叫
p_mutex: 指向互斥訊號量。
opt: 用來指定是否進行任務排程操作
OS_OPT_POST_NONE 不指定特定的選項
OS_OPT_POST_NO_SCHED 禁止在本函式內執行任務排程操作。
p_err: 用來儲存呼叫此函式返回的錯誤碼。
BOOLEAN OSMutexAccept (OS_EVENT *pevent, //無等待請求,當訊號量暫時無效時直接返回,不會進入休眠狀態等待訊號量(任務不掛起)
INT8U *perr)
OS_EVENT *OSMutexDel (OS_EVENT *pevent, //刪除一個互斥型訊號量,不允許中斷函式呼叫
INT8U opt,
INT8U *perr)
INT8U OSMutexQuery (OS_EVENT *pevent,
OS_MUTEX_DATA *p_mutex_data) //獲取互斥訊號量的當前狀態
訊號量主要用於訪問共享資源(手冊125),實現任務的同步以及任務和 ISR 間的同步(手冊129)。
5、事件標誌組管理
事件標誌組包括兩個部分:一是用來儲存當前事件組中各個事件狀態的一些標誌位,二是等待這些標誌位職位或清除的任務列表。
對於flag–”事件組”的使用,可以用一個簡單的例子做說明: 比如,我現在用迅雷下載一部10集的連續劇,我打算10集全部下載完成之後,才開始正式看,現在3~10集因為種子原因,先早下完了,現在第1集下到了82%,第2集下到了97%,因為我的計劃是10集全部下完才開始看,而第1集和第2集由於網路,種子等等各種原因,遲遲不能下載完成,進而導致我的計劃被懸停,不能進行,已下載的8集,也因為前2集沒能下完,而白白等待—這就等同於flag事件組,1~10集,每一集都是一個事件,因為我內定,10個事件全部完成之後,才進入下一事件–”觀看”所以及早完成自己事件的第3~10集,將主動把自己通過flag事件組函式OSFlagPost()登記到事件組上,他們不關心,其他友鄰事件完成否,只專注自己的事件是否完成,自己的事件一旦完成就登記到事件組上,最後3~10集,都把自己登記上去了,只剩下第1集和第2集,一旦某天的某個時刻,第2集下完了,那麼第2集也把自己登記到事件組上,這樣整個事件距離完成還剩下一個事件,就是第1集是否下載完成,只要第1集下載完成,那麼我內定的”觀看”計劃開始啟動,過了3分鐘,由於網速提高,竟以300k的速度開始下載第1集,1分鐘之後,第1集也下載完成了,第1集立即呼叫OSFlagPost事件組函式,將自己登記到事件組上,ok,OSFlagPost()檢測到所有事件已經完成,OSFlagPost()將是”我”自動進入下一事件—”觀看”還有一點就是關於flag事件組和Sem,Mbox,Queue的區別之處,flag事件組不使用事件控制矩陣來管理被阻塞在事件上的task程序,flag事件組使用pgrp的雙向連結串列來掛接起所有task,在OSFlagPost()中將遍歷這個連結串列,查詢符合當前flag事件的task,將該task從雙向連結串列中摘下然後放入就緒控制矩陣中,之所以這樣,是因為flag事件組不像Sem,Mbox,Queue那樣具有二值性,即Sem,Mbox,Queue,要麼有,要麼沒有,flag事件組,還要進一步判斷,有的話,是什麼程度的有。

OS_FLAG_GRP *OSFlagCreate (OS_FLAGS flags, //建立一個事件標誌組,不允許在中斷中呼叫此函式,呼叫會返回錯誤。
INT8U *perr)
OS_FLAG_GRP *OSFlagDel (OS_FLAG_GRP *pgrp, //刪除一個事件標誌組,不允許在中斷函式中呼叫,呼叫會返回錯誤。
INT8U opt,
INT8U *perr)
OS_FLAGS OSFlagPend (OS_FLAG_GRP *pgrp, //請求/等待事件標誌組的事件標誌位
OS_FLAGS flags,
INT8U wait_type,
INT32U timeout,
INT8U *perr)
static void OS_FlagBlock (OS_FLAG_GRP *pgrp, //新增一個任務到事件標誌組的等待任務連結串列中
OS_FLAG_NODE *pnode,
OS_FLAGS flags,
INT8U wait_type,
INT32U timeout)
OS_FLAGS OSFlagPost (OS_FLAG_GRP *pgrp, //職位或清零事件標誌組中的事件標誌位
OS_FLAGS flags,
INT8U opt,
INT8U *perr)
static BOOLEAN OS_FlagTaskRdy (OS_FLAG_NODE *pnode, //等待事件標誌的任務進入就緒狀態
OS_FLAGS flags_rdy)
void OS_FlagUnlink (OS_FLAG_NODE *pnode) //從等待連結串列中刪除OS_FLAG_NODE
OS_FLAGS OSFlagAccept (OS_FLAG_GRP *pgrp, //無等待的獲取事件標誌組中的事件標誌位
OS_FLAGS flags,
INT8U wait_type,
INT8U *perr)
OS_FLAGS OSFlagQuery (OS_FLAG_GRP *pgrp, //查詢事件標誌組的狀態
INT8U *perr)
6、訊息郵箱管理
使一個任務或中斷服務子程式向另一個任務傳送一個指標型的變數,通常該指標指向一個包含了“訊息”的特定資料結構。
應用程式可以使用任意多個郵箱,其最大數目由OS_CFG.H檔案中的配置常數OS_MAX_EVENTS設定。
OS_EVENT *OSMboxCreate (void *pmsg) //建立一個郵箱,中斷服務子程式不能呼叫。
OS_EVENT *OSMboxDel (OS_EVENT *pevent, //刪除一個郵箱,函式不能被中斷服務程式呼叫。
INT8U opt,
INT8U *perr)
注意:當郵箱被刪除時可能有一個或多個任務試圖操作已刪除的郵箱,所以在刪除郵箱之前必須先刪除可能操作郵箱的任務。
void *OSMboxPend (OS_EVENT *pevent, //等待/請求郵箱中的訊息,中斷服務程式不能等待,所以不可呼叫。
INT32U timeout,
INT8U *perr)
INT8U OSMboxPost (OS_EVENT *pevent, //向郵箱傳送一則訊息,
void *pmsg)
INT8U OSMboxPostOpt (OS_EVENT *pevent, //向郵箱傳送一則訊息,另外可以向所有郵箱傳送訊息(廣播)。
void *pmsg,
INT8U opt)
void *OSMboxAccept (OS_EVENT *pevent) //無等待的從郵箱獲取一則訊息,當郵箱為空時任務直接返回,不會進入等待。
INT8U OSMboxQuery (OS_EVENT *pevent, //查詢郵箱的狀態
OS_MBOX_DATA *p_mbox_data)
注:用郵箱作為二值訊號量(243頁)、用郵箱實現延時(244頁);
7、訊息佇列管理
使一個任務或中斷服務子程式向另一個任務傳送一個指標型的變數或任務,實際可以將訊息佇列看成多個郵箱組成的陣列,只是他們公用一個等待任務列表。
訊息佇列容納的最大訊息數為65535.
OS_EVENT *OSQCreate (void **start, //建立一個訊息佇列
INT16U size)
OS_EVENT *OSQDel (OS_EVENT *pevent, //刪除一個訊息佇列
INT8U opt,
INT8U *perr)
void *OSQPend (OS_EVENT *pevent, //等待訊息佇列中的訊息
INT32U timeout,
INT8U *perr)
INT8U OSQPost (OS_EVENT *pevent, //向訊息佇列傳送一則訊息,使用.OSQIn插入新訊息
void *pmsg)
INT8U OSQPostFront (OS_EVENT *pevent, //向訊息佇列傳送一則訊息,使用.OSQOut插入新訊息
void *pmsg)
INT8U OSQPostOpt (OS_EVENT *pevent, //向訊息佇列傳送一則訊息,支援向所有訊息佇列中等待訊息的任務傳送訊息(廣播形式)
void *pmsg,
INT8U opt)
void *OSQAccept (OS_EVENT *pevent, //無等待的從訊息佇列中獲取一則訊息,當訊息無效時直接返回而不是等待。
INT8U *perr)
INT8U OSQFlush (OS_EVENT *pevent) // 清空訊息佇列
INT8U OSQQuery (OS_EVENT *pevent, //獲取訊息佇列的狀態
OS_Q_DATA *p_q_data)
使用訊息佇列讀取模擬量的值(267),訊息佇列用做計數型訊號量(268)。
8、軟體定時器
自V1.8.3以後版本引入軟體定時器。
OS_TMR *OSTmrCreate (INT32U dly, //建立一個軟體定時器
INT32U period,
INT8U opt,
OS_TMR_CALLBACK callback,
void *callback_arg,
INT8U *pname,
INT8U *perr)
BOOLEAN OSTmrDel (OS_TMR *ptmr, //刪除一個軟體定時器
INT8U *perr)
INT8U OSTmrNameGet (OS_TMR *ptmr, //獲取定時器的名字
INT8U **pdest,
INT8U *perr)
INT32U OSTmrRemainGet (OS_TMR *ptmr, //獲取定時器還有多久會超時,剩餘多少時間會超時。
INT8U *perr)
INT8U OSTmrStateGet (OS_TMR *ptmr, //獲取定時器的狀態
INT8U *perr)
BOOLEAN OSTmrStart (OS_TMR *ptmr, //啟動一個定時器
INT8U *perr)
BOOLEAN OSTmrStop (OS_TMR *ptmr, //停止一個定時器
INT8U opt,
void *callback_arg,
INT8U *perr)
8、記憶體管理
為了解決記憶體碎片的問題,系統中使用記憶體控制卡的資料結構跟蹤每一個記憶體分割槽,系統中的每個記憶體分割槽都有自己的記憶體控制塊。
void *OSMemGet (OS_MEM *pmem, //分配一個記憶體塊
INT8U *perr)
INT8U OSMemPut (OS_MEM *pmem, //釋放一個記憶體塊
void *pblk)
INT8U OSMemQuery (OS_MEM *pmem, //查詢一個記憶體分割槽的狀態,可查詢到特定記憶體分割槽中記憶體塊的大小、可用記憶體塊數目及使用了的記憶體塊數目等資訊。
OS_MEM_DATA *p_mem_data)