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