多优先级任务
文章目錄
- 1 多優(yōu)先級任務(wù)
- 1.1 設(shè)計(jì)目標(biāo)
- 1.2 優(yōu)先級原理
- 1.3 設(shè)計(jì)實(shí)現(xiàn)
1 多優(yōu)先級任務(wù)
1.1 設(shè)計(jì)目標(biāo)
問題引入:
- 任務(wù)數(shù)量無限,而資源有限。當(dāng)多個(gè)任務(wù)在等待同一資源/事件時(shí),如果資源/事件不能在任務(wù)間共享,應(yīng)該有哪個(gè)任務(wù)來處理?
1.2 優(yōu)先級原理
在此我們只討論CPU占用的優(yōu)先級:
- RTOS維護(hù)一個(gè)就緒表,每個(gè)表項(xiàng)對應(yīng)一個(gè)任務(wù),對應(yīng)一種優(yōu)先級。就緒表指明哪些優(yōu)先級的任務(wù)等待占用CPU運(yùn)行。
- 為便于快速找到優(yōu)先級更高的任務(wù)運(yùn)行,使用了就緒位置標(biāo)記就緒,快速查找。
1.3 設(shè)計(jì)實(shí)現(xiàn)
添加優(yōu)先級字段:
添加優(yōu)先級位圖表:
添加獲取當(dāng)前最高優(yōu)先級任務(wù)的函數(shù):
修改任務(wù)初始化函數(shù):
/********************************************************************************************************** ** Function name : tTaskInit ** Descriptions : 初始化任務(wù)結(jié)構(gòu) ** parameters : task 要初始化的任務(wù)結(jié)構(gòu) ** parameters : entry 任務(wù)的入口函數(shù) ** parameters : param 傳遞給任務(wù)的運(yùn)行參數(shù) ** Returned value : 無 ***********************************************************************************************************/ void tTaskInit (tTask * task, void (*entry)(void *), void *param, uint32_t prio, uint32_t * stack) {// 為了簡化代碼,tinyOS無論是在啟動(dòng)時(shí)切換至第一個(gè)任務(wù),還是在運(yùn)行過程中在不同間任務(wù)切換// 所執(zhí)行的操作都是先保存當(dāng)前任務(wù)的運(yùn)行環(huán)境參數(shù)(CPU寄存器值)的堆棧中(如果已經(jīng)運(yùn)行運(yùn)行起來的話),然后再// 取出從下一個(gè)任務(wù)的堆棧中取出之前的運(yùn)行環(huán)境參數(shù),然后恢復(fù)到CPU寄存器// 對于切換至之前從沒有運(yùn)行過的任務(wù),我們?yōu)樗渲靡粋€(gè)“虛假的”保存現(xiàn)場,然后使用該現(xiàn)場恢復(fù)。// 注意以下兩點(diǎn):// 1、不需要用到的寄存器,直接填了寄存器號(hào),方便在IDE調(diào)試時(shí)查看效果;// 2、順序不能變,要結(jié)合PendSV_Handler以及CPU對異常的處理流程來理解*(--stack) = (unsigned long)(1<<24); // XPSR, 設(shè)置了Thumb模式,恢復(fù)到Thumb狀態(tài)而非ARM狀態(tài)運(yùn)行*(--stack) = (unsigned long)entry; // 程序的入口地址*(--stack) = (unsigned long)0x14; // R14(LR), 任務(wù)不會(huì)通過return xxx結(jié)束自己,所以未用*(--stack) = (unsigned long)0x12; // R12, 未用*(--stack) = (unsigned long)0x3; // R3, 未用*(--stack) = (unsigned long)0x2; // R2, 未用*(--stack) = (unsigned long)0x1; // R1, 未用*(--stack) = (unsigned long)param; // R0 = param, 傳給任務(wù)的入口函數(shù)*(--stack) = (unsigned long)0x11; // R11, 未用*(--stack) = (unsigned long)0x10; // R10, 未用*(--stack) = (unsigned long)0x9; // R9, 未用*(--stack) = (unsigned long)0x8; // R8, 未用*(--stack) = (unsigned long)0x7; // R7, 未用*(--stack) = (unsigned long)0x6; // R6, 未用*(--stack) = (unsigned long)0x5; // R5, 未用*(--stack) = (unsigned long)0x4; // R4, 未用task->stack = stack; // 保存最終的值task->delayTicks = 0;task->prio = prio; // 設(shè)置任務(wù)的優(yōu)先級taskTable[prio] = task; // 填入任務(wù)優(yōu)先級表tBitmapSet(&taskPrioBitmap, prio); // 標(biāo)記優(yōu)先級位置中的相應(yīng)位 }修改tTaskDelay函數(shù):
/********************************************************************************************************** ** Function name : tTaskDelay ** Descriptions : 使當(dāng)前任務(wù)進(jìn)入延時(shí)狀態(tài)。 ** parameters : delay 延時(shí)多少個(gè)ticks ** Returned value : 無 ***********************************************************************************************************/ void tTaskDelay (uint32_t delay) {// 配置好當(dāng)前要延時(shí)的ticks數(shù)uint32_t status = tTaskEnterCritical();currentTask->delayTicks = delay;tBitmapClear(&taskPrioBitmap, currentTask->prio);tTaskExitCritical(status);// 然后進(jìn)行任務(wù)切換,切換至另一個(gè)任務(wù),或者空閑任務(wù)// delayTikcs會(huì)在時(shí)鐘中斷中自動(dòng)減1.當(dāng)減至0時(shí),會(huì)切換回來繼續(xù)運(yùn)行。tTaskSched(); }修改tTaskSystemTickHandler函數(shù):
/********************************************************************************************************** ** Function name : tTaskSystemTickHandler ** Descriptions : 系統(tǒng)時(shí)鐘節(jié)拍處理。 ** parameters : 無 ** Returned value : 無 ***********************************************************************************************************/ void tTaskSystemTickHandler () {// 檢查所有任務(wù)的delayTicks數(shù),如果不0的話,減1。int i; uint32_t status = tTaskEnterCritical();for (i = 0; i < TINYOS_PRO_COUNT; i++) {if (taskTable[i]->delayTicks > 0){taskTable[i]->delayTicks--;}else {tBitmapSet(&taskPrioBitmap, i);}}tTaskExitCritical(status);// 這個(gè)過程中可能有任務(wù)延時(shí)完畢(delayTicks = 0),進(jìn)行一次調(diào)度。tTaskSched(); }修改調(diào)度算法:
/********************************************************************************************************** ** Function name : tTaskSched ** Descriptions : 任務(wù)調(diào)度接口。tinyOS通過它來選擇下一個(gè)具體的任務(wù),然后切換至該任務(wù)運(yùn)行。 ** parameters : 無 ** Returned value : 無 ***********************************************************************************************************/ void tTaskSched (void) { tTask * tempTask;// 進(jìn)入臨界區(qū),以保護(hù)在整個(gè)任務(wù)調(diào)度與切換期間,不會(huì)因?yàn)榘l(fā)生中斷導(dǎo)致currentTask和nextTask可能更改uint32_t status = tTaskEnterCritical();// 如何調(diào)度器已經(jīng)被上鎖,則不進(jìn)行調(diào)度,直接退bmif (schedLockCount > 0) {tTaskExitCritical(status);return;}// 找到優(yōu)先級最高的任務(wù),如果其優(yōu)先級比當(dāng)前任務(wù)的還高,那么就切換到這個(gè)任務(wù)tempTask = tTaskHighestReady();if (tempTask != currentTask) {nextTask = tempTask;tTaskSwitch(); }// 退出臨界區(qū)tTaskExitCritical(status); }參考資料:
總結(jié)
- 上一篇: 一加哈苏合作 建立四大影像研发中心
- 下一篇: 人脸识别收集不只是脸 有些企业后台会看见