uC/OS-II 一些函數(shù)簡(jiǎn)介
ucos ii介紹
μC/OS-II由Micrium公司提供,是一個(gè)可移植、可固化的、可裁剪的、占先式多任務(wù)實(shí)時(shí)內(nèi)核,它適用于多種微處理器,微控制器和數(shù)字處理芯片(已經(jīng)移植到超過(guò)100種以上的微處理器應(yīng)用中)。同時(shí),該系統(tǒng)源代碼開(kāi)放、整潔、一致,注釋詳盡,適合系統(tǒng)開(kāi)發(fā)。
常用函數(shù)介紹:
OSInit()初始化函數(shù)
在uC/OS II的學(xué)習(xí)中,OSInit(OS_CORE.C )(函數(shù)原型位于);是一個(gè)重要的函數(shù),它在OS應(yīng)用中的main()函數(shù)中首先被調(diào)用,是OS運(yùn)行的第一個(gè)函數(shù),它完成各初始變量的初始化。主要工作:
OSInitHookBegin(); /* 調(diào)用用戶特定的初始化代碼(通過(guò)一個(gè)接口函數(shù)實(shí)現(xiàn)用戶要求的插件式進(jìn)入系統(tǒng)中)*/
OS_InitMisc(); /* 初始化變量*/
OS_InitRdyList(); /* 初始化就緒列表*/
OS_InitTCBList(); /* 初始化OS_TCB空閑列表*/
OS_InitEventList(); /* 初始化OS_EVENT空閑列表*/
OS_InitTaskIdle(); /創(chuàng)建空閑任務(wù)/
程序注釋詳解:
void OSInit (void)
{
#if OS_TASK_CREATE_EXT_EN > 0u
#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
INT8U err;
#endif
#endif
OSInitHookBegin(); /* 調(diào)用用戶特定的初始化代碼(通過(guò)一個(gè)接口函數(shù)實(shí)現(xiàn)用戶要求的插件式進(jìn)入系統(tǒng)中)*/
OS_InitMisc(); /* 初始化變量*/ /* Initialize miscellaneous variables */
OS_InitRdyList(); /* 初始化就緒列表*/ /* Initialize the Ready List */
OS_InitTCBList(); /* 初始化OS_TCB空閑列表*/ /* Initialize the free list of OS_TCBs */
OS_InitEventList(); /* 初始化OS_EVENT空閑列表*/ /* Initialize the free list of OS_EVENTs */
#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
OS_FlagInit(); /* 初始化事件標(biāo)志結(jié)構(gòu)*/ /* Initialize the event flag structures */
#endif
#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
OS_MemInit(); /* 初始化內(nèi)存管理器*/ /* Initialize the memory manager */
#endif
#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
OS_QInit(); /* 初始化消息隊(duì)列結(jié)構(gòu)*/ /* Initialize the message queue structures */
#endif
#if OS_TASK_CREATE_EXT_EN > 0u
#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
OS_TLS_Init(&err); /* 創(chuàng)建任務(wù)前初始化TLS*/ /* Initialize TLS, before creating tasks */
if (err != OS_ERR_NONE) {
return;
}
#endif
#endif
OS_InitTaskIdle(); /* 創(chuàng)建空閑任務(wù)(無(wú)條件)Create the Idle Task */
#if OS_TASK_STAT_EN > 0u
OS_InitTaskStat(); /* 創(chuàng)建統(tǒng)計(jì)任務(wù)*/ /* Create the Statistic Task */
#endif
#if OS_TMR_EN > 0u
OSTmr_Init(); /* 初始化時(shí)間管理器*/ /* Initialize the Timer Manager */
#endif
OSInitHookEnd(); /*調(diào)用用戶特定的初始化代碼*/
#if OS_DEBUG_EN > 0u
OSDebugInit();
#endif
}
123456789101112131415161718192021222324252627282930313233343536373839404142
任務(wù)函數(shù)相關(guān):
OSTaskCreate()任務(wù)創(chuàng)建函數(shù)
1、主要作用:建立一個(gè)新任務(wù)。任務(wù)的建立可以在多任務(wù)環(huán)境啟動(dòng)之前,也可以在正在運(yùn)行的任務(wù)中建立。中斷處理程序中不能建立任務(wù);注意,ISR中禁止建立任務(wù),一個(gè)任務(wù)必須為無(wú)限循環(huán)結(jié)構(gòu)。
2、函數(shù)原型:INT8U OSTaskCreate(void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio);
3、參數(shù)說(shuō)明:
void (*task)(void *pd):指向任務(wù)代碼首地址的指針。
void *pdata:指向一個(gè)數(shù)據(jù)結(jié)構(gòu),該結(jié)構(gòu)用來(lái)在建立任務(wù)時(shí)向任務(wù)傳遞參數(shù)。
OS_STK *ptos: 指向堆棧任務(wù)棧頂?shù)闹羔?/p>
INT8U prio:任務(wù)優(yōu)先級(jí)
4、返回值介紹:
OS_NO_ERR:函數(shù)調(diào)用成功。
OS_PRIO_EXIST:具有該優(yōu)先級(jí)的任務(wù)已經(jīng)存在。
OS_PRIO_INVALID:參數(shù)指定的優(yōu)先級(jí)大于OS_LOWEST_PRIO。
OS_NO_MORE_TCB:系統(tǒng)中沒(méi)有OS_TCB可以分配給任務(wù)了。
5、函數(shù)主體在os_task.c中
OSTaskCreateExt
1、主要作用:建立一個(gè)新任務(wù)。與OSTaskCreate()不同的是,OSTaskCreateExt()允許用戶設(shè)置更多的細(xì)節(jié)內(nèi)容。任務(wù)的建立可以在多任務(wù)環(huán)境啟動(dòng)之前,也可以在正在運(yùn)行的任務(wù)中建立,但中斷處理程序中不能建立新任務(wù)。,且不
2、函數(shù)原型:NT8U OSTaskCreateExt (void (*task)(void *pd),void *pdata, OS_STK *ptos,INT8U prio ,INT16U id, OS_STK *pbos,INT32U stk_size,void *pext,INT16U opt)
3、參數(shù)說(shuō)明:
void (*task)(void *pd):指向任務(wù)代碼首地址的指針。
void *pdata:指向一個(gè)數(shù)據(jù)結(jié)構(gòu),該結(jié)構(gòu)用來(lái)在建立任務(wù)時(shí)向任務(wù)傳遞參數(shù)。
OS_STK *ptos: 指向堆棧任務(wù)棧頂?shù)闹羔?/p>
INT8U prio:任務(wù)優(yōu)先級(jí)
INT16U id: 任務(wù)ID,2.52版本,無(wú)實(shí)際作用,保留作為擴(kuò)展用
OS_STK *pbos: 指向堆棧底部的指針,用于OSTaskStkChk()函數(shù)
INT32U stk_size:指定任務(wù)堆棧的大小,由OS_STK類型決定
void *pext:定義數(shù)據(jù)結(jié)構(gòu)的指針,作為T(mén)CB的擴(kuò)展
INT16U opt) :存放于任務(wù)操作相關(guān)的信息,詳見(jiàn)uCOS-II.H
4、返回值說(shuō)明:
OS_NO_ERR:函數(shù)調(diào)用成功。
OS_PRIO_EXIST:具有該優(yōu)先級(jí)的任務(wù)已經(jīng)存在。
OS_PRIO_INVALID:參數(shù)指定的優(yōu)先級(jí)大于OS_LOWEST_PRIO。
OS_NO_MORE_TCB:系統(tǒng)中沒(méi)有OS_TCB可以分配給任務(wù)了。
5、函數(shù)主體在os_task.c中
OSTaskSuspend()任務(wù)掛起:
1、主要作用: 無(wú)條件掛起一個(gè)任務(wù)。調(diào)用此函數(shù)的任務(wù)也可以傳遞參數(shù) OS_PRIO_SELF,掛起調(diào)用任務(wù)本身。當(dāng)前任務(wù)掛起后,只有其他任務(wù)才能喚醒被掛起的任務(wù)。任務(wù)掛起后,系統(tǒng)會(huì)重新進(jìn)行任務(wù)調(diào)度,運(yùn)行下一個(gè)優(yōu)先級(jí)最高的就緒任務(wù)。喚醒掛起任務(wù)需要調(diào)用函數(shù)OSTaskResume()。任務(wù)的掛起是可以疊加到其他操作上的。例如,任務(wù)被掛起時(shí)正在進(jìn)行延時(shí)操作,那么任務(wù)的喚醒就需要兩個(gè)條件:延時(shí)的結(jié)束以及其他任務(wù)的喚醒操作。又如,任務(wù)被掛起時(shí)正在等待信號(hào)量,當(dāng)任務(wù)從信號(hào)量的等待對(duì)列中清除后也不能立即運(yùn)行,而必須等到被喚醒后。[!--empirenews.page--]
2、函數(shù)原型:INT8U OSTaskSuspend(INT8U prio);
3、參數(shù)說(shuō)明:prio為指定要獲取掛起的任務(wù)優(yōu)先級(jí),也可以指定參數(shù) OS_PRIO_SELF,掛起任務(wù)本身。此時(shí),下一個(gè)優(yōu)先級(jí)最高的就緒任務(wù)將運(yùn)行。
4、返回值說(shuō)明:
OS_NO_ERR:函數(shù)調(diào)用成功。
OS_TASK_SUSPEND_IDLE:試圖掛起μC/OS-II中的空閑任務(wù)(Idle task)。此為非法操作。
OS_PRIO_INVALID:參數(shù)指定的優(yōu)先級(jí)大于 OS_LOWEST_PRIO 或沒(méi)有設(shè)定 OS_PRIO_SELF 的值。
OS_TASK_SUSPEND_PRIO:要掛起的任務(wù)不存在。
5、函數(shù)主體在os_task.c中
OSTaskResume()喚醒任務(wù)
1、主要作用: 喚醒一個(gè)用 OSTaskSuspend() 函數(shù)掛起的任務(wù)。OSTaskResume() 也是唯一能“解掛”掛起任務(wù)的函數(shù)。
2、函數(shù)原型:INT8U OSTaskResume(INT8U prio);
3、參數(shù)說(shuō)明:prio指定要喚醒任務(wù)的優(yōu)先級(jí)。
4、返回值說(shuō)明:
OS_NO_ERR:函數(shù)調(diào)用成功。
OS_TASK_RESUME_PRIO:要喚醒的任務(wù)不存在
OS_TASK_NOT_SUSPENDED:要喚醒的任務(wù)不在掛起狀態(tài)。
OS_PRIO_INVALID:參數(shù)指定的優(yōu)先級(jí)大于或等于OS_LOWEST_PRIO。
5、函數(shù)主體在os_task.c中
時(shí)間相關(guān)的函數(shù)
OSTimeDly()延時(shí)節(jié)拍函數(shù)
1、主要作用:調(diào)用該函數(shù)的任務(wù)將自己延時(shí)一段時(shí)間并執(zhí)行一次任務(wù)調(diào)度,一旦規(guī)定的延時(shí)時(shí)間完成或有其它的任務(wù)通過(guò)調(diào)用OSTimeDlyResume()取消了延時(shí),調(diào)用OSTimeDly()函數(shù)的任務(wù)馬上進(jìn)入就緒狀態(tài)(前提是先將任務(wù)調(diào)度后執(zhí)行的任務(wù)執(zhí)行到程序尾,且調(diào)用OSTimeDly的任務(wù)此時(shí)優(yōu)先級(jí)最高)。
2、函數(shù)原型:void OSTimeDly (INT16U ticks);
3、參數(shù)說(shuō)明:ticks為需要延時(shí)的時(shí)鐘節(jié)拍數(shù);
4、返回值:無(wú)
5、函數(shù)主體在os_time.c中
OSTimeDlyHMSM()系統(tǒng)延時(shí)函數(shù)
1、主要作用:函數(shù)是以小時(shí)(H)、分(M)、秒(S)和毫秒(m)四個(gè)參數(shù)來(lái)定義延時(shí)時(shí)間的,函數(shù)在內(nèi)部把這些參數(shù)轉(zhuǎn)換為時(shí)鐘節(jié)拍,再通過(guò)單次或多次調(diào)用OSTimeDly()進(jìn)行延時(shí)和任務(wù)調(diào)度,所以延時(shí)原理和調(diào)用延時(shí)函數(shù)OSTimeDly()是一樣的。調(diào)用 OSTimeDlyHMSM() 后,如果延時(shí)時(shí)間不為0,系統(tǒng)將立即進(jìn)行任務(wù)調(diào)度。
2、函數(shù)原型:INT8U OSTimeDlyHMSM (INT8U hours,INT8U minutes,INT8U seconds,INT16U milli);
3、參數(shù)說(shuō)明:
hours 為延時(shí)小時(shí)數(shù),范圍從0-255。
minutes 為延時(shí)分鐘數(shù),范圍從0-59
seconds 為延時(shí)秒數(shù),范圍從0-59
milli 為延時(shí)毫秒數(shù),范圍從0-999
4、返回值說(shuō)明:
OS_NO_ERR:函數(shù)調(diào)用成功。
OS_TIME_INVALID_MINUTES:參數(shù)錯(cuò)誤,分鐘數(shù)大于59。
OS_TIME_INVALID_SECONDS:參數(shù)錯(cuò)誤,秒數(shù)大于59。
OS_TIME_INVALID_MILLI:參數(shù)錯(cuò)誤,毫秒數(shù)大于999。
OS_TIME_ZERO_DLY:四個(gè)參數(shù)全為0。
5、函數(shù)主體在os_time.c中
OSTimeDlyResume()延時(shí)恢復(fù)函數(shù)
1、主要作用:任務(wù)在延時(shí)之后,進(jìn)入阻塞態(tài)。當(dāng)延時(shí)時(shí)間到了就從阻塞態(tài)恢復(fù)到就緒態(tài),可以被操作系統(tǒng)調(diào)度執(zhí)行。但是,并非回到就緒態(tài)就只有這么一種可能,因?yàn)榧幢闳蝿?wù)的延時(shí)時(shí)間沒(méi)到,還是可以通過(guò)函數(shù)OSTimeDlyResume恢復(fù)該任務(wù)到就緒態(tài)的。另外,OSTimeDlyResume也不僅僅能恢復(fù)使用OSTimeDly或OSTimeDlyHMSM而延時(shí)的任務(wù)。對(duì)于因等待事件發(fā)生而阻塞的,并且設(shè)置了超時(shí)(timeout)時(shí)間的任務(wù),也可以使用OSTimeDlyResume來(lái)恢復(fù)。對(duì)這些任務(wù)使用了OSTimeDlyResume,就好像已經(jīng)等待超時(shí)了一樣。但是,對(duì)于采用OSTaskSuspend掛起的任務(wù),是不允許采用OSTimeDlyResume來(lái)恢復(fù)的。
2、函數(shù)原型:INT8U OSTimeDlyResume (INT8U prio)
3.參數(shù)說(shuō)明:prio 被恢復(fù)任務(wù)的優(yōu)先級(jí)
4、返回值:
OS_ERR_TASK_NOT_EXIST:任務(wù)優(yōu)先級(jí)指針表中沒(méi)有此任務(wù)
OS_NO_ERR:函數(shù)調(diào)用成功。
OS_ERR_PRIO_INVALID:參數(shù)指定的優(yōu)先級(jí)大于或等于OS_LOWEST_PRIO。
OS_ERR_TIME_NOT_DLY:任務(wù)沒(méi)有被延時(shí)阻塞
5、函數(shù)主體在os_time.c中
信號(hào)量相關(guān)函數(shù):
如果我們想對(duì)一個(gè)公共資源進(jìn)行互斥訪問(wèn),例如:如果我們想讓兩個(gè)任務(wù)Task1和Task2都可以調(diào)用Fun()函數(shù),但不能同時(shí)調(diào)用,最好定義信號(hào)量:Semp = OSSemCreate(1),同理在各自的任務(wù)中都需要調(diào)用OSSemPend(Semp,0,&err)請(qǐng)求此信號(hào)量,如果可用,則調(diào)用Fun(),然后再用OSSemPost(Semp)釋放該信號(hào)量。這里就實(shí)現(xiàn)了一個(gè)資源的互斥訪問(wèn)。
(注:初始化OSSemCreate(1),那么一個(gè)任務(wù)中有OSSemPend,那么可以執(zhí)行,執(zhí)行之后cnt==0,其他任務(wù)的OSSemPend無(wú)法獲得sem,只能等待,除非任務(wù)一有OSSemPost,使其cnt++,這樣其他任務(wù)的Pend可以執(zhí)行。)
同理,如果一個(gè)任務(wù)要等待n個(gè)事件發(fā)生后才能執(zhí)行,則應(yīng)定義為Semp = OSSemCreate(n)。然后在這n個(gè)任務(wù)分別運(yùn)行時(shí)調(diào)用OSSemPost(Semp),直到這n個(gè)事件均發(fā)生后,這個(gè)任務(wù)才能運(yùn)行。
OSSemCreate(cnt)賦初始值cnt,OSSemPend一次,cnt– 一次,OSSemPost一次,cnt++一次。
下面對(duì)信號(hào)量函數(shù)做簡(jiǎn)要介紹:
OSSemCreate()建立信號(hào)量函數(shù)
1、主要作用:該函數(shù)建立并初始化一個(gè)信號(hào)量,信號(hào)量的作用如下:
允許一個(gè)任務(wù)和其他任務(wù)或者中斷同步
取得設(shè)備的使用權(quán)
標(biāo)志事件的發(fā)生
2、函數(shù)原型:OS_EVENT *OSSemCreate(INT16U value);
3、參數(shù)說(shuō)明:value 參數(shù)是所建立的信號(hào)量的初始值,可以取0到65535之間的任何值。
4、返回值:OSSemCreate() 函數(shù)返回指向分配給所建立的信號(hào)量的控制塊的指針。如果沒(méi)有可用的控制塊,OSSemCreate() 函數(shù)返回空指針。
5、函數(shù)主體在os_sem.c中
OSSemPend()取得使用權(quán)函數(shù)
1、主要作用: 該函數(shù)用于任務(wù)試圖取得設(shè)備的使用權(quán)、任務(wù)需要和其他任務(wù)或中斷同步、任務(wù)需要等待特定事件的發(fā)生的場(chǎng)合。如果任務(wù)調(diào)用OSSemPend() 函數(shù)時(shí),信號(hào)量的值大于零,OSSemPend() 函數(shù)遞減該值。如果調(diào)用時(shí)信號(hào)量值等于零,OSSemPend() 函數(shù)將任務(wù)加入該信號(hào)量的等待隊(duì)列。OSSemPend() 函數(shù)掛起當(dāng)前任務(wù)直到其他的任務(wù)或中斷設(shè)置信號(hào)量或超出等待的預(yù)期時(shí)間。如果在預(yù)期的時(shí)鐘節(jié)拍內(nèi)信號(hào)量被設(shè)置,μC/OS-Ⅱ默認(rèn)讓最高優(yōu)先級(jí)的任務(wù)取得信號(hào)量并回到就緒狀態(tài)。一個(gè)被OSTaskSuspend() 函數(shù)掛起的任務(wù)也可以接受信號(hào)量,但這個(gè)任務(wù)將一直保持掛起狀態(tài)直到通過(guò)調(diào)用OSTaskResume() 函數(shù)恢復(fù)該任務(wù)的運(yùn)行。[!--empirenews.page--]
2、函數(shù)原型:void OSSemPend ( OS_EVNNT *pevent, INT16U timeout, int8u *err );
3、參數(shù)說(shuō)明:
pevent 是指向信號(hào)量的指針。該指針的值在建立該信號(hào)量時(shí)可以得到。(參考OSSemCreate() 函數(shù))。
timeout 允許一個(gè)任務(wù)在經(jīng)過(guò)了指定數(shù)目的時(shí)鐘節(jié)拍后還沒(méi)有得到需要的信號(hào)量時(shí)恢復(fù)就緒狀態(tài)。如果該值為零表示任務(wù)將持續(xù)地等待信號(hào)量,最大的等待時(shí)間為65535個(gè)時(shí)鐘節(jié)拍。這個(gè)時(shí)間長(zhǎng)度并不是非常嚴(yán)格的,可能存在一個(gè)時(shí)鐘節(jié)拍的誤差。
err 是指向包含錯(cuò)誤碼的變量的指針,返回的錯(cuò)誤碼可能為下述幾種:
OS_NO_ERR :信號(hào)量不為零。
OS_TIMEOUT :信號(hào)量沒(méi)有在指定數(shù)目的時(shí)鐘周期內(nèi)被設(shè)置。
OS_ERR_PEND_ISR :從中斷調(diào)用該函數(shù)。雖然規(guī)定了不允許從中斷調(diào)用該函數(shù),但μC/OS-Ⅱ仍然包含了檢測(cè)這種情況的功能。
OS_ERR_EVENT_TYPE :pevent 不是指向信號(hào)量的指針。
4、返回值:無(wú)
5、函數(shù)主體在os_sem.c中
OSSemPost()使用權(quán)放棄函數(shù)
1、主要作用: 該函數(shù)用于設(shè)置指定的信號(hào)量。如果指定的信號(hào)量是零或大于零,OSSemPost() 函數(shù)遞增該信號(hào)量的值并返回。如果有任何任務(wù)在等待該信號(hào)量,則最高優(yōu)先級(jí)的任務(wù)將得到信號(hào)量并進(jìn)入就緒狀態(tài)。任務(wù)調(diào)度函數(shù)將進(jìn)行任務(wù)調(diào)度,決定當(dāng)前運(yùn)行的任務(wù)是否仍然為最高優(yōu)先級(jí)的就緒任務(wù)。
2、函數(shù)原型:INT8U OSSemPost(OS_EVENT *pevent);
3、參數(shù)說(shuō)明:pevent 是指向信號(hào)量的指針。該指針的值在建立該信號(hào)量時(shí)可以得到。(參考OSSemCreate() 函數(shù))。
4、返回值:
OS_NO_ERR :信號(hào)量被成功地設(shè)置
OS_SEM_OVF :信號(hào)量的值溢出
OS_ERR_EVENT_TYPE :pevent 不是指向信號(hào)量的指針
5、函數(shù)主體在os_sem.c中
消息隊(duì)列函數(shù)
消息隊(duì)列是µC/OS-II中另一種通訊機(jī)制,它可以使一個(gè)任務(wù)或者中斷服務(wù)子程序向另一個(gè)任務(wù)發(fā)送以指針?lè)绞蕉x的變量。因具體的應(yīng)用有所不同,每個(gè)指針指向的數(shù)據(jù)結(jié)構(gòu)變量也有所不同。為了使用µC/OS-II的消息隊(duì)列功能,需要在OS_CFG.H 文件中,將OS_Q_EN常數(shù)設(shè)置為1,并且通過(guò)常數(shù)OS_MAX_QS來(lái)決定µC/OS-II支持的最多消息隊(duì)列數(shù)。
12
OSQCreate()建立消息隊(duì)列函數(shù)
1、主要作用:該函數(shù)用于建立一個(gè)消息隊(duì)列。任務(wù)或中斷可以通過(guò)消息隊(duì)列向一個(gè)或多個(gè)任務(wù)發(fā)送消息。消息的含義是和具體的應(yīng)用密切相關(guān)的。
2、函數(shù)原型:OS_EVENT *OSQCreate (void **start, INT8U size);
3、參數(shù)說(shuō)明:start 是消息內(nèi)存區(qū)的首地址,消息內(nèi)存區(qū)是一個(gè)指針數(shù)組
size 是消息內(nèi)存區(qū)的大小。
4、返回值說(shuō)明:OSQCreate() 函數(shù)返回一個(gè)指向消息隊(duì)列控制塊的指針。如果沒(méi)有空閑的控制塊,OSQCreate() 函數(shù)返回空指針
5、函數(shù)主體在os_q.c中
OSQPend()任務(wù)等待消息函數(shù)
1、主要作用: 該函數(shù)用于任務(wù)等待消息。消息通過(guò)中斷或任務(wù)發(fā)送給需要的任務(wù)。消息是一個(gè)指針變量,在不同的應(yīng)用中消息的具體含義不同。如果調(diào)用 OSQPend() 函數(shù)時(shí)隊(duì)列中已經(jīng)存在消息,那么該消息被返回給 OSQPend() 函數(shù)的調(diào)用者,該消息同時(shí)從隊(duì)列中清除。如果調(diào)用 OSQPend() 函數(shù)時(shí)隊(duì)列中沒(méi)有消息,OSQPend() 函數(shù)掛起調(diào)用任務(wù)直到得到消息或超出定義的超時(shí)時(shí)間。如果同時(shí)有多個(gè)任務(wù)等待同一個(gè)消息,μC/OS-Ⅱ默認(rèn)最高優(yōu)先級(jí)的任務(wù)取得消息。一個(gè)由 OSTaskSuspend() 函數(shù)掛起的任務(wù)也可以接受消息,但這個(gè)任務(wù)將一直保持掛起狀態(tài)直到通過(guò)調(diào)用 OSTaskResume() 函數(shù)恢復(fù)任務(wù)的運(yùn)行。
2、函數(shù)原型:void *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err);
3、參數(shù)說(shuō)明:pevent 是指向消息隊(duì)列的指針,該指針的值在建立該隊(duì)列時(shí)可以得到。(參考 OSQCreate() 函數(shù))。 timeout 允許一個(gè)任務(wù)以指定數(shù)目的時(shí)鐘節(jié)拍等待消息。超時(shí)后如果還沒(méi)有得到消息則恢復(fù)成就緒狀態(tài)。如果該值設(shè)置成零則表示任務(wù)將持續(xù)地等待消息,最大的等待時(shí)間為65535個(gè)時(shí)鐘節(jié)拍。這個(gè)時(shí)間長(zhǎng)度并不是非常嚴(yán)格的,可能存在一個(gè)時(shí)鐘節(jié)拍的誤差。
err 是指向包含錯(cuò)誤碼的變量的指針。OSQPend() 函數(shù)返回的錯(cuò)誤碼可能為下述幾種:
* OS_NO_ERR :消息被正確地接受。
* OS_TIMEOUT :消息沒(méi)有在指定的時(shí)鐘周期數(shù)內(nèi)接收到消息。
* OS_ERR_PEND_ISR :從中斷調(diào)用該函數(shù)。雖然規(guī)定了不允許從中斷中調(diào)用該函數(shù),但μC/OS-Ⅱ仍然包含了檢測(cè)這種情況的功能。
* OS_ERR_EVENT_TYPE :pevent 不是指向消息隊(duì)列的指針。
12345678
4、返回值說(shuō)明:OSQPend() 函數(shù)返回取得的消息并將 *err 置為 OS_NO_ERR。如果沒(méi)有在指定數(shù)目的時(shí)鐘節(jié)拍內(nèi)接受到消息,OSQPend() 函數(shù)返回空指針并將 *err 設(shè)置為 OS_TIMEOUT。
5、函數(shù)主體在os_q.c中
其他的消息函數(shù)
INT8U OSQPost (OS_EVENT *pevent, void *msg)
發(fā)送一個(gè)消息到消息隊(duì)列 FIFO模式
INT8U OSQPostFront (OS_EVENT *pevent, void *msg)
發(fā)送一個(gè)消息到消息隊(duì)列 FIFO模式
void *OSQAccept (OS_EVENT *pevent)
無(wú)等待地從消息隊(duì)列中得到一個(gè)消息
INT8U OSQFlush (OS_EVENT *pevent)
清空一個(gè)消息隊(duì)列
INT8U OSQQuery (OS_EVENT *pevent, OS_Q_DATA *pdata)
查詢一個(gè)消息隊(duì)列的當(dāng)前狀態(tài)
使用消息隊(duì)列的通常步驟為:
1)定義指針: OS_EVENT *proSQ
定義指針數(shù)組: void *start[4]
2) 在主程序中建立信號(hào)列隊(duì):*proSQ = OSQCreate(start,4);
3)在任務(wù)中等待消息列隊(duì)中得到消息或者給消息列隊(duì)發(fā)送消息
12345678910111213141516
內(nèi)存管理:參考于:μC/OS-II學(xué)習(xí)筆記四(內(nèi)存管理)注:以下都為轉(zhuǎn)載;
在ANSI C中可以用malloc()和free()兩個(gè)函數(shù)動(dòng)態(tài)地分配內(nèi)存和釋放內(nèi)存。但是,在嵌入式實(shí)時(shí)操作系統(tǒng)中,多次這樣做會(huì)把原來(lái)很大的一塊連續(xù)內(nèi)存區(qū)域,逐漸地分割成許多非常小而且彼此又不相鄰的內(nèi)存區(qū)域,也就是內(nèi)存碎片。由于這些碎片的大量存在,使得程序到后來(lái)連非常小的內(nèi)存也分配不到。另外,由于內(nèi)存管理算法的原因,malloc()和free()函數(shù)執(zhí)行時(shí)間是不確定的。[!--empirenews.page--]
在μC/OS-II中,操作系統(tǒng)把連續(xù)的大塊內(nèi)存按分區(qū)來(lái)管理。每個(gè)分區(qū)中包含有整數(shù)個(gè)大小相同的內(nèi)存塊。利用這種機(jī)制,μC/OS-II 對(duì)malloc()和free()函數(shù)進(jìn)行了改進(jìn),使得它們可以分配和釋放固定大小的內(nèi)存塊。這樣一來(lái),malloc()和free()函數(shù)的執(zhí)行時(shí)間也是固定的了。
在一個(gè)系統(tǒng)中可以有多個(gè)內(nèi)存分區(qū)。這樣,用戶的應(yīng)用程序就可以從不同的內(nèi)存分區(qū)中得到不同大小的內(nèi)存塊。但是,特定的內(nèi)存塊在釋放時(shí)必須重新放回它以前所屬于的內(nèi)存分區(qū)。顯然,采用這樣的內(nèi)存管理算法,上面的內(nèi)存碎片問(wèn)題就得到了解決。
內(nèi)存控制塊
為了便于內(nèi)存的管理,在μC/OS-II中使用內(nèi)存控制塊(memory control blocks)的數(shù)據(jù)結(jié)構(gòu)來(lái)跟蹤每一個(gè)內(nèi)存分區(qū),系統(tǒng)中的每個(gè)內(nèi)存分區(qū)都有它自己的內(nèi)存控制塊。
內(nèi)存控制塊的定義如下:
typedef struct {
void *OSMemAddr; //指向內(nèi)存分區(qū)起始地址的指針
void *OSMemFreeList; //是指向下一個(gè)空閑內(nèi)存控制塊或者下一個(gè)空閑的內(nèi)存塊的指針
INT32U OSMemBlkSize; //是內(nèi)存分區(qū)中內(nèi)存塊的大小
INT32U OSMemNBlks; //內(nèi)存分區(qū)中總的內(nèi)存塊數(shù)量
INT32U OSMemNFree; //內(nèi)存分區(qū)中當(dāng)前可以得空閑內(nèi)存塊數(shù)量
} OS_MEM;
如果要在μC/OS-II中使用內(nèi)存管理,需要在OS_CFG.H文件中將開(kāi)關(guān)量OS_MEM_EN設(shè)置為1。這樣μC/OS-II 在啟動(dòng)時(shí)就會(huì)對(duì)內(nèi)存管理器進(jìn)行初始化[由OSInit()調(diào)用OSMemInit()實(shí)現(xiàn)]。常數(shù)OS_MAX_MEM_PART(見(jiàn)文件OS_CFG.H)定義了最大的內(nèi)存分區(qū)數(shù),該常數(shù)值最小應(yīng)為2。
OSMemCreate()內(nèi)存塊創(chuàng)建函數(shù)
1 主要作用: 該函數(shù)建立并初始化一個(gè)用于動(dòng)態(tài)內(nèi)存分配的區(qū)域,該內(nèi)存區(qū)域包含指定數(shù)目的、大小確定的內(nèi)存塊。應(yīng)用可以動(dòng)態(tài)申請(qǐng)這些內(nèi)存塊并在用完后將其釋放回這個(gè)內(nèi)存區(qū)域。該函數(shù)的返回值就是指向這個(gè)內(nèi)存區(qū)域控制塊的指針,并作為OSMemGet(),OSMemPut(),OSMemQuery() 等相關(guān)調(diào)用的參數(shù)。
2函數(shù)原型:OS_MEM *OSMemCreate( void *addr, INT32U nblks, INT32U blksize, INT8U *err );
3參數(shù)說(shuō)明:addr 建立的內(nèi)存區(qū)域的起始地址??梢允褂渺o態(tài)數(shù)組或在系統(tǒng)初始化時(shí)使用 malloc() 函數(shù)來(lái)分配這個(gè)區(qū)域的空間。
nblks 內(nèi)存塊的數(shù)目。每一個(gè)內(nèi)存區(qū)域最少需要定義兩個(gè)內(nèi)存塊。
blksize 每個(gè)內(nèi)存塊的大小,最小應(yīng)該能夠容納一個(gè)指針變量。
err 是指向包含錯(cuò)誤碼的變量的指針。Err可能是如下幾種情況:
OS_NO_ERR :成功建立內(nèi)存區(qū)域。
OS_MEM_INVALID_ADDR :非法地址,即地址為空指針。
OS_MEM_INVALID_PART :沒(méi)有空閑的內(nèi)存區(qū)域。
OS_MEM_INVALID_BLKS :沒(méi)有為內(nèi)存區(qū)域建立至少兩個(gè)內(nèi)存塊。
OS_MEM_INVALID_SIZE :內(nèi)存塊大小不足以容納一個(gè)指針變量。
4返回值:
OSMemCreate() 函數(shù)返回指向所創(chuàng)建的內(nèi)存區(qū)域控制塊的指針。如果創(chuàng)建失敗,函數(shù)返回空指針。
OSMemGet()函數(shù)
1 主要作用: 該函數(shù)用于從內(nèi)存區(qū)域分配一個(gè)內(nèi)存塊。用戶程序必須知道所建立的內(nèi)存塊的大小,并必須在使用完內(nèi)存塊后釋放它??梢远啻握{(diào)用 OSMemGet() 函數(shù)。它的返回值就是指向所分配內(nèi)存塊的指針,并作為 OSMemPut() 函數(shù)的參數(shù)。
2函數(shù)原型:void *OSMemGet(OS_MEM *pmem, INT8U *err);
3參數(shù)說(shuō)明:pmem 是指向內(nèi)存區(qū)域控制塊的指針,可以從 OSMemCreate() 函數(shù)的返回值中得到。
err 是指向包含錯(cuò)誤碼的變量的指針。Err可能是如下情況:
OS_NO_ERR :成功得到一個(gè)內(nèi)存塊。
OS_MEM_NO_FREE_BLKS :內(nèi)存區(qū)域中已經(jīng)沒(méi)有足夠的內(nèi)存塊。
4返回值:
OSMemGet() 函數(shù)返回指向所分配內(nèi)存塊的指針。如果沒(méi)有可分配的內(nèi)存塊,OSMemGet() 函數(shù)返回空指針。
OSMemPut()
1 主要作用:該函數(shù)用于釋放一個(gè)內(nèi)存塊,內(nèi)存塊必須釋放回它原先所在的內(nèi)存區(qū)域,否則會(huì)造成系統(tǒng)錯(cuò)誤。
2函數(shù)原型:INT8U OSMemPut (OS_MEM *pmem, void *pblk);
3參數(shù)說(shuō)明:pmem 是指向內(nèi)存區(qū)域控制塊的指針,可以從 OSMemCreate() 函數(shù)的返回值中得到。
pblk 是指向?qū)⒈会尫诺膬?nèi)存塊的指針。
4返回值:
OSMemPut() 函數(shù)的返回值為下述之一:
OS_NO_ERR :成功釋放內(nèi)存塊
OS_MEM_FULL :內(nèi)存區(qū)域已滿,不能再接受更多釋放的內(nèi)存塊。這種情況說(shuō)明用戶程序出現(xiàn)了錯(cuò)誤,釋放了多于用 OSMemGet() 函數(shù)得到的內(nèi)存塊。
OSMemQuery()
1 主要作用:該函數(shù)用于得到內(nèi)存區(qū)域的信息。
2函數(shù)原型:INT8U OSMemQuery(OS_MEM *pmem, OS_MEM_DATA *pdata);
3參數(shù)說(shuō)明:pmem 是指向內(nèi)存區(qū)域控制塊的指針,可以從 OSMemCreate() 函數(shù)的返回值中得到。
pdata 是一個(gè)指向 OS_MEM_DATA 數(shù)據(jù)結(jié)構(gòu)的指針,該數(shù)據(jù)結(jié)構(gòu)包含了以下的域:
void OSAddr; /* 指向內(nèi)存區(qū)域起始地址的指針 */
void OSFreeList; /* 指向空閑內(nèi)存塊列表起始地址的指針 */
INT32U OSBlkSize; /* 每個(gè)內(nèi)存塊的大小 */
INT32U OSNBlks; /* 該內(nèi)存區(qū)域中的內(nèi)存塊總數(shù) */
INT32U OSNFree; /* 空閑的內(nèi)存塊數(shù)目 */
INT32U OSNUsed; /* 已使用的內(nèi)存塊數(shù)目 */
參考文章:
1、 uC/OS II 函數(shù)說(shuō)明 之–OSTaskCreate()與OSTaskCreateExt()
2、uC-OS-II_中文手冊(cè)