時(shí)間管理服務(wù)函數(shù)是以系統(tǒng)節(jié)拍為處理單位的,實(shí)際的時(shí)間與希望的時(shí)間是有誤差的,最壞的情況下誤差接近一個(gè)系統(tǒng)節(jié)拍。因此時(shí)間管理服務(wù)函數(shù)只能用在對(duì)時(shí)間精度要求不高的場(chǎng)合,或者時(shí)間間隔較長(zhǎng)的場(chǎng)合。
1. void OSSchedLock(void);
void OSSchedLock (void)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
if (OSRunning == OS_TRUE) { /* Make sure multitasking is running */
OS_ENTER_CRITICAL();
if (OSIntNesting == 0) { /* Can't call from an ISR */
if (OSLockNesting < 255u) { /* Prevent OSLockNesting from wrapping back to 0 */
OSLockNesting++; /* Increment lock nesting level */
}
}
OS_EXIT_CRITICAL();
}
}
這個(gè)函數(shù)又叫上鎖函數(shù),如果在一個(gè)任務(wù)里面調(diào)用了上鎖函數(shù),那么OSSched()這個(gè)任務(wù)切換函數(shù)就不會(huì)執(zhí)行也就是說不會(huì)進(jìn)任務(wù)調(diào)度。
調(diào)用OSSchedLock()以后,用戶的應(yīng)用程序不得使用任何能將現(xiàn)行任務(wù)掛起的系統(tǒng)調(diào)用。也就是說,用戶程序不得調(diào)用OSMboxPend()、OSQPend()、OSSemPend()、OSTaskSuspend(OS_PR1O_SELF)、OSTimeDly()或OSTimeDlyHMSM(),直到OSLockNesting回零為止。因?yàn)檎{(diào)度器上了鎖,用戶就鎖住了系統(tǒng),任何其它任務(wù)都不能運(yùn)行。
但是上鎖了任務(wù)是可以中斷,若任務(wù)遇到中斷,則中斷函數(shù)的執(zhí)行會(huì)為OSIntNesting變量加1,當(dāng)中斷返回時(shí)又要判斷OSLockNesting是否為0,如果不為0說明系統(tǒng)仍被鎖,直接退出中斷。如果OSLockNesting為0說明系統(tǒng)未被鎖,CPU進(jìn)入任務(wù)就緒表查找優(yōu)先級(jí)最高的任務(wù)。所以上鎖函數(shù)執(zhí)行后,CPU一直處于當(dāng)前任務(wù)與中斷服務(wù)函數(shù)之間的運(yùn)行,直到解鎖函數(shù)將OSLockNesting和OSIntNesting的值減到0時(shí),方可解除系統(tǒng)鎖定。
OSSchedUnlock() 取消函數(shù)上鎖。
2.void
OSTimeDly (INT16U ticks);
void
OSTimeDly (INT16U ticks)
{
INT8U y;
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
if (OSIntNesting > 0) { /* See if trying to call from an ISR */
return;
}
if (ticks > 0) { /* 0 means no delay! */
OS_ENTER_CRITICAL();
y = OSTCBCur->OSTCBY; /* Delay current task */
OSRdyTbl[y] &= ~OSTCBCur->OSTCBBitX;
if (OSRdyTbl[y] == 0) {
OSRdyGrp &= ~OSTCBCur->OSTCBBitY; /*取消當(dāng)前任務(wù)的就緒狀態(tài)
}
OSTCBCur->OSTCBDly = ticks; /* 延時(shí)節(jié)拍數(shù)存入任務(wù)控制塊TCB */
OS_EXIT_CRITICAL();
OS_Sched(); /* 調(diào)度函數(shù) */
}
}
將一個(gè)任務(wù)延時(shí)若干個(gè)時(shí)鐘節(jié)拍。如果延時(shí)時(shí)間大于0,系統(tǒng)將立即進(jìn)行任務(wù)調(diào)度。延時(shí)時(shí)間的長(zhǎng)度可從0到65535個(gè)時(shí)鐘節(jié)拍。延時(shí)時(shí)間0表示不進(jìn)行延時(shí),函數(shù)將立即返回調(diào)用者。延時(shí)的具體時(shí)間依賴于系統(tǒng)每秒鐘有多少時(shí)鐘節(jié)拍(由文件OS_CFG.H中的常量OS_TICKS_PER_SEC設(shè)定):
#define OS_TICKS_PER_SEC 1000
調(diào)用該函數(shù)會(huì)使uCOS-II進(jìn)行一次任務(wù)調(diào)度,并且執(zhí)行下一個(gè)優(yōu)先級(jí)最高的就緒態(tài)任務(wù)。任務(wù)調(diào)用OSTimeDly()后,一旦規(guī)定的時(shí)間期滿或者有其它的任務(wù)通過調(diào)用OSTimeDlyResume()取消了延時(shí),它就會(huì)馬上進(jìn)入就緒狀態(tài)。注意,只有當(dāng)該任務(wù)在所有就緒任務(wù)中具有最高的優(yōu)先級(jí)時(shí),它才會(huì)立即運(yùn)行。
3.INT8U
OSTimeDlyHMSM (INT8U hours, INT8U minutes, INT8U seconds, INT16U ms);
這個(gè)函數(shù)是以小時(shí)(H)、分(M)、秒(S)和毫秒(m)四個(gè)參數(shù)來定義延時(shí)時(shí)間的,函數(shù)在內(nèi)部把這些參數(shù)轉(zhuǎn)換為時(shí)鐘節(jié)拍,再通過單次或多次調(diào)用OSTimeDly()進(jìn)行延時(shí)和任務(wù)調(diào)度,所以延時(shí)原理和調(diào)用延時(shí)函數(shù)OSTimeDly()是一樣的。
4.INT8U
OS_TCBInit(INT8U
prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt);
任務(wù)控制塊初始化
描述:這個(gè)函數(shù)是uCOS-II內(nèi)部函數(shù),在建立任務(wù)時(shí)調(diào)用的初始化任務(wù)控制塊OS_TCB函數(shù),含7個(gè)參數(shù),查看OSTaskCreate()和OSTaskCreateExt()
初始化任務(wù)控制塊TCB(優(yōu)先級(jí)指針,堆棧指針,棧底指針,任務(wù)標(biāo)志符,堆棧容量,擴(kuò)展指針,選擇項(xiàng))
INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)
{
#if OS_CRITICAL_METHOD == 3 //中斷函數(shù)被設(shè)定為模式3
OS_CPU_SR cpu_sr;
-
#endif
-
OS_TCB *ptcb; //定義一個(gè)PCB變量
-
-
-
OS_ENTER_CRITICAL(); //關(guān)閉中斷
-
ptcb = OSTCBFreeList; //分配一個(gè)空任務(wù)控制塊給ptcb
-
if (ptcb != (OS_TCB *)0) { //如果緩沖池有空余TCB,這個(gè)TCB被初始化
-
OSTCBFreeList = ptcb->OSTCBNext; //指向TCB的雙向鏈接的后鏈接
-
OS_EXIT_CRITICAL(); //打開中斷
-
ptcb->OSTCBStkPtr = ptos; //指向當(dāng)前TCB的棧頂指針(輸入的數(shù)據(jù))
-
ptcb->OSTCBPrio = (INT8U)prio; //保存當(dāng)前TCB的優(yōu)先級(jí)別(輸入的數(shù)據(jù))
-
ptcb->OSTCBStat = OS_STAT_RDY; //設(shè)定當(dāng)前TCB的狀態(tài)字(內(nèi)容為(準(zhǔn)備完畢))
-
ptcb->OSTCBDly = 0; //允許任務(wù)等待的最大字節(jié)節(jié)拍為0
-
-
#if OS_TASK_CREATE_EXT_EN > 0 //允許生成OSTaskCreateExt()函數(shù)
-
ptcb->OSTCBExtPtr = pext; //指向用戶定義的任務(wù)控制塊(擴(kuò)展指針)
-
ptcb->OSTCBStkSize = stk_size; //設(shè)定堆棧的容量
-
ptcb->OSTCBStkBottom = pbos; //指向堆棧棧底的指針
-
ptcb->OSTCBOpt = opt; //保存OS_TCB的選擇項(xiàng)
-
ptcb->OSTCBId = id; //保存任務(wù)標(biāo)志符
-
#else //否則使用舊的參數(shù)
-
pext = pext; //擴(kuò)展指針
-
stk_size = stk_size; //堆棧的容量
-
pbos = pbos; //棧底的指針
-
opt = opt; //選擇項(xiàng)
-
id = id; //任務(wù)標(biāo)志符
-
#endif
-
-
#if OS_TASK_DEL_EN > 0 //允許生成OSTaskDel()函數(shù)代碼函數(shù)
-
ptcb->OSTCBDelReq = OS_NO_ERR; //如果可以刪除任務(wù)本身,可以從每個(gè)OS_TCB中節(jié)省出一個(gè)布爾量
-
#endif
-
-
ptcb->OSTCBY = prio >> 3; //對(duì)一些參數(shù)提前運(yùn)算,為了節(jié)省CPU的操作事件
-
ptcb->OSTCBBitY = OSMapTbl[ptcb->OSTCBY];
-
ptcb->OSTCBX = prio & 0x07;
-
ptcb->OSTCBBitX = OSMapTbl[ptcb->OSTCBX];
-
-
#if OS_EVENT_EN > 0 //如果不打算在應(yīng)用程序中使用各類事件
-
ptcb->OSTCBEventPtr = (OS_EVENT *)0; //OS_TCB中OSTCBEventPtr就不會(huì)出現(xiàn)
-
#endif
-
-
//針對(duì)的事件為信號(hào)量,互斥型信號(hào)量,消息郵箱,消息隊(duì)列,當(dāng)滿足版本大于2.51且事件標(biāo)志允許且有最大事件標(biāo)志及允許刪除任務(wù)
-
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0)
-
ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; //則向事件標(biāo)志節(jié)點(diǎn)的指針被初始化為空指針
-
#endif
-
-
#if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0))
-
ptcb->OSTCBMsg = (void *)0; //滿足以上條件,指向傳遞給任務(wù)的消息指針為0空指針
-
#endif
-
-
#if OS_VERSION >= 204 //如果版本大于2.04
-
OSTCBInitHook(ptcb); //允許使用OSTCBInitHook(ptcb)函數(shù),可對(duì)其加代碼
-
#endif //主要增加OS_TCB擴(kuò)展,浮點(diǎn)運(yùn)算,MMU寄存器,與任務(wù)相關(guān)內(nèi)容,調(diào)用此程序時(shí)中斷開著的
-
-
OSTaskCreateHook(ptcb); //調(diào)用戶建立任務(wù)鉤子程序
-
-
OS_ENTER_CRITICAL();
-
OSTCBPrioTbl[prio] = ptcb;
-
ptcb->OSTCBNext = OSTCBList; //鏈接到任務(wù)控制塊鏈接串
-
ptcb->OSTCBPrev = (OS_TCB *)0;
-
if (OSTCBList != (OS_TCB *)0) {
-
OSTCBList->OSTCBPrev = ptcb;
-
}
-
OSTCBList = ptcb; //讓該任務(wù)進(jìn)入就緒表
-
OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */
-
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
-
OS_EXIT_CRITICAL(); //打開中斷
-
return (OS_NO_ERR); //調(diào)用成功,最后讓此函數(shù)返回到調(diào)用函數(shù)[OSTaskCreate()或OSTaskCreateExt()函數(shù)],
-
//返回值表示分配到任務(wù)控塊,并初始化了
-
}
-
OS_EXIT_CRITICAL(); //打開中斷
-
return (OS_NO_MORE_TCB); //沒有更多的任務(wù)控制塊被分配,將無法創(chuàng)建新的任務(wù)
-
}
5.INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio);
-
//建立一個(gè)新任務(wù)
-
#if OS_TASK_CREATE_EN > 0 //允許生成OSTaskCreate()函數(shù)
-
INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio)
-
{
-
#if OS_CRITICAL_METHOD == 3 //中斷函數(shù)被設(shè)定為模式3
-
OS_CPU_SR cpu_sr;
-
#endif
-
OS_STK *psp; //初始化任務(wù)堆棧指針變量,返回新的棧頂指針
-
INT8U err; //定義(獲得并定義初始化任務(wù)控制塊)是否成功
-
-
-
#if OS_ARG_CHK_EN > 0 //所有參數(shù)必須在指定的參數(shù)內(nèi)
-
if (prio > OS_LOWEST_PRIO) { //檢查任務(wù)優(yōu)先級(jí)是否合法
-
return (OS_PRIO_INVALID); //參數(shù)指定的優(yōu)先級(jí)大于OS_LOWEST_PRIO
-
}
-
#endif
-
OS_ENTER_CRITICAL(); //關(guān)閉中斷
-
if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { //確認(rèn)優(yōu)先級(jí)未被使用,即就緒態(tài)為0
-
OSTCBPrioTbl[prio] = (OS_TCB *)1; //保留這個(gè)優(yōu)先級(jí),將就緒態(tài)設(shè)為1
-
-
OS_EXIT_CRITICAL(); //打開中斷
-
psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, 0); //初始化任務(wù)堆棧
-
err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0); //獲得并初始化任務(wù)控制塊
-
if (err == OS_NO_ERR) { //任務(wù)控制初始化成功
-
OS_ENTER_CRITICAL(); //關(guān)閉中斷
-
OSTaskCtr++; //任務(wù)計(jì)數(shù)器加1
-
OS_EXIT_CRITICAL(); //打開中斷
-
if (OSRunning == TRUE) { //檢查是否有(某個(gè))任務(wù)在運(yùn)行
-
OS_Sched(); //任務(wù)調(diào)度,最高任務(wù)優(yōu)先級(jí)運(yùn)行
-
}
-
} else { //否則,任務(wù)初始化失敗
-
OS_ENTER_CRITICAL(); //關(guān)閉中斷
-
OSTCBPrioTbl[prio] = (OS_TCB *)0; //放棄任務(wù),設(shè)此任務(wù)就緒態(tài)為0
-
OS_EXIT_CRITICAL(); //打開中斷
-
}
-
return (err); //返回(獲得并定義初始化任務(wù)控制塊是否成功)
-
}
-
OS_EXIT_CRITICAL(); //打開中斷
-
return (OS_PRIO_EXIST); //返回(具有該優(yōu)先級(jí)的任務(wù)已經(jīng)存在)
-
}
-
#endif
6.static void OS_InitTaskStat (void)
;
-
//創(chuàng)建統(tǒng)計(jì)任務(wù)
-
#if OS_TASK_STAT_EN > 0
-
static void OS_InitTaskStat (void)
-
{
-
#if OS_TASK_CREATE_EXT_EN > 0 //允許生成OSTaskCreateExt()函數(shù)
-
#if OS_STK_GROWTH == 1 //堆棧生長(zhǎng)方向向下
-
(void)OSTaskCreateExt(OS_TaskStat, //建立擴(kuò)展任務(wù);產(chǎn)生一個(gè)統(tǒng)計(jì)任務(wù)
-
(void *)0, //沒有(傳遞參數(shù)指針)
-
&OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1], //分配任務(wù)堆棧棧頂指針
-
OS_STAT_PRIO, //分配任務(wù)優(yōu)先級(jí)
-
OS_TASK_STAT_ID, //(未來的)優(yōu)先級(jí)標(biāo)識(shí)(與優(yōu)先級(jí)相同)
-
&OSTaskStatStk[0], //分配任務(wù)堆棧棧底指針
-
OS_TASK_STAT_STK_SIZE, //指定堆棧的容量(檢驗(yàn)用)
-
(void *)0, //沒有(指向用戶附加的數(shù)據(jù)域的指針)
-
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear */
-
#else //建立擴(kuò)展任務(wù);堆棧生長(zhǎng)方向向上
-
(void)OSTaskCreateExt(OS_TaskStat, //產(chǎn)生一個(gè)統(tǒng)計(jì)任務(wù)
-
(void *)0, //沒有(傳遞參數(shù)指針)
-
&OSTaskStatStk[0], //分配任務(wù)堆棧棧底指針
-
OS_STAT_PRIO, //分配任務(wù)優(yōu)先級(jí)
-
OS_TASK_STAT_ID, //(未來的)優(yōu)先級(jí)標(biāo)識(shí)(與優(yōu)先級(jí)相同)
-
&OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1], //分配任務(wù)堆棧棧頂指針
-
OS_TASK_STAT_STK_SIZE, //指定堆棧的容量(檢驗(yàn)用)
-
(void *)0, //沒有(指向用戶附加的數(shù)據(jù)域的指針)
-
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear */
-
#endif
-
#else //否則只能生成OSTaskCreate()函數(shù)
-
#if OS_STK_GROWTH == 1 //堆棧生長(zhǎng)方向向下
-
(void)OSTaskCreate(OS_TaskStat, //產(chǎn)生一個(gè)統(tǒng)計(jì)任務(wù)
-
(void *)0, //沒有(傳遞參數(shù)指針)
-
&OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1], //分配任務(wù)堆棧棧頂指針
-
OS_STAT_PRIO); //分配任務(wù)優(yōu)先級(jí)
-
#else //否則堆棧生長(zhǎng)方向向上
-
(void)OSTaskCreate(OS_TaskStat, //產(chǎn)生一個(gè)統(tǒng)計(jì)任務(wù)
-
(void *)0, //沒有(傳遞參數(shù)指針)
-
&OSTaskStatStk[0], //分配任務(wù)堆棧棧底指針
-
OS_STAT_PRIO); //分配任務(wù)優(yōu)先級(jí)
-
#endif
-
#endif
-
}
-
#endif
7.static void OS_InitTCBList (void);
-
//初始化空閑TCB鏈表
-
static void OS_InitTCBList (void)
-
{
-
INT8U i;
-
OS_TCB *ptcb1;
-
OS_TCB *ptcb2;
-
-
-
OSTCBList = (OS_TCB *)0; //任務(wù)控制塊鏈接表的指針清0
-
for (i = 0; i < (OS_LOWEST_PRIO + 1); i++) {
-
OSTCBPrioTbl[i] = (OS_TCB *)0; //清除所有的優(yōu)先級(jí)控制塊優(yōu)先級(jí)列表
-
}
-
ptcb1 = &OSTCBTbl[0]; //查找任務(wù)控制塊列表(0)的對(duì)應(yīng)地址
-
ptcb2 = &OSTCBTbl[1]; //查找任務(wù)控制塊列表(1)的對(duì)應(yīng)地址
-
for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) {
-
ptcb1->OSTCBNext = ptcb2;//釋放所有的任務(wù)控制塊列表
-
ptcb1++;
-
ptcb2++;
-
}
-
ptcb1->OSTCBNext = (OS_TCB *)0; //將最后的任務(wù)塊雙向鏈接表的后鏈接為0
-
OSTCBFreeList = &OSTCBTbl[0]; //空任務(wù)控制塊地址為當(dāng)前任務(wù)控制塊列表的首地址
-
}