官术网_书友最值得收藏!

5.2 實現(xiàn)阻塞延時

阻塞延時的阻塞是指任務(wù)調(diào)用該延時函數(shù)后,會被剝奪CPU使用權(quán),然后進(jìn)入阻塞狀態(tài),直到延時結(jié)束,任務(wù)重新獲取CPU使用權(quán)才可以繼續(xù)運行。在任務(wù)阻塞的這段時間,CPU可以執(zhí)行其他任務(wù),如果其他任務(wù)也處于延時狀態(tài),那么CPU就將運行空閑任務(wù)。阻塞延時函數(shù)在os_time.c中定義,具體代碼實現(xiàn)參見代碼清單5-9。

代碼清單5-9 阻塞延時

1 /* 阻塞延時 */
 2 void  OSTimeDly(OS_TICK dly)
 3 {
 4     /* 設(shè)置延時時間 */
 5     OSTCBCurPtr->TaskDelayTicks = dly;(1)
 6 
 7     /* 進(jìn)行任務(wù)調(diào)度 */
 8     OSSched();(2)
 9 }

代碼清單5-9(1):TaskDelayTicks是任務(wù)控制塊的一個成員,用于記錄任務(wù)需要延時的時間,單位為SysTick的中斷周期。比如我們設(shè)置的SysTick的中斷周期為10ms,調(diào)用OSTimeDly(2)則完成2*10ms的延時。TaskDelayTicks的定義具體參見代碼清單5-10。

代碼清單5-10 TaskDelayTicks定義

1 struct os_tcb {
 2     CPU_STK         *StkPtr;
 3     CPU_STK_SIZE    StkSize;
 4 
 5     /* 任務(wù)延時周期個數(shù) */
 6     OS_TICK         TaskDelayTicks;
7 };

代碼清單5-9(2):任務(wù)調(diào)度。這時的任務(wù)調(diào)度與第4章的不一樣,具體參見代碼清單5-11,其中加粗部分為第4章的代碼,現(xiàn)已用條件編譯屏蔽掉。

代碼清單5-11 任務(wù)調(diào)度

1 void OSSched(void)
 2 {
 3 #if 0/* 非常簡單的任務(wù)調(diào)度:兩個任務(wù)輪流執(zhí)行 */
 4     if ( OSTCBCurPtr == OSRdyList[0].HeadPtr ) {
 5         OSTCBHighRdyPtr = OSRdyList[1].HeadPtr;
 6     } else {
 7         OSTCBHighRdyPtr = OSRdyList[0].HeadPtr;
 8     }
 9 #endif
10 
11     /* 如果當(dāng)前任務(wù)是空閑任務(wù),那么嘗試執(zhí)行任務(wù)1或者任務(wù)2,
12      *看看其延時時間是否結(jié)束,如果任務(wù)的延時時間均沒有到期,
13      *就返回繼續(xù)執(zhí)行空閑任務(wù) */
14     if ( OSTCBCurPtr == &OSIdleTaskTCB ) {(1)
15         if (OSRdyList[0].HeadPtr->TaskDelayTicks == 0) {
16             OSTCBHighRdyPtr = OSRdyList[0].HeadPtr;
17         } else if (OSRdyList[1].HeadPtr->TaskDelayTicks == 0) {
18             OSTCBHighRdyPtr = OSRdyList[1].HeadPtr;
19         } else {
20             /* 任務(wù)延時均沒有到期則返回,繼續(xù)執(zhí)行空閑任務(wù) */
21             return;
22         }
23     } else {(2)
24     /*如果是task1或者task2,則檢查另外一個任務(wù),
25      *如果另外的任務(wù)不在延時中,則切換到該任務(wù)
26      *否則,判斷當(dāng)前任務(wù)是否應(yīng)該進(jìn)入延時狀態(tài),
27      *如果是,則切換到空閑任務(wù),否則就不進(jìn)行任何切換 */
28     if (OSTCBCurPtr == OSRdyList[0].HeadPtr) {
29         if (OSRdyList[1].HeadPtr->TaskDelayTicks == 0) {
30                 OSTCBHighRdyPtr = OSRdyList[1].HeadPtr;
31             } else if (OSTCBCurPtr->TaskDelayTicks != 0) {
32                 OSTCBHighRdyPtr = &OSIdleTaskTCB;
33             } else {
34                 /* 返回,不進(jìn)行切換,因為兩個任務(wù)都處于延時狀態(tài) */
35                 return;
36             }
37         } else if (OSTCBCurPtr == OSRdyList[1].HeadPtr) {
38             if (OSRdyList[0].HeadPtr->TaskDelayTicks == 0) {
39                 OSTCBHighRdyPtr = OSRdyList[0].HeadPtr;
40             } else if (OSTCBCurPtr->TaskDelayTicks != 0) {
41                 OSTCBHighRdyPtr = &OSIdleTaskTCB;
42             } else {
43                 /* 返回,不進(jìn)行切換,因為兩個任務(wù)都處于延時中 */
44                 return;
45             }
46         }
47     }
48 
49     /* 任務(wù)切換 */
50     OS_TASK_SW();(3)
51 }

代碼清單5-11(1):如果當(dāng)前任務(wù)是空閑任務(wù),則嘗試執(zhí)行任務(wù)1或者任務(wù)2,看看其延時時間是否結(jié)束,如果任務(wù)的延時時間均沒有到期,就返回繼續(xù)執(zhí)行空閑任務(wù)。

代碼清單5-11(2):如果當(dāng)前任務(wù)不是空閑任務(wù),則會執(zhí)行到此,那就看看當(dāng)前任務(wù)是哪個任務(wù)。無論是哪個任務(wù),都要檢查另外一個任務(wù)是否處于延時狀態(tài),如果沒有延時,就切換到該任務(wù),如果處于延時狀態(tài),則判斷當(dāng)前任務(wù)是否應(yīng)該進(jìn)入延時狀態(tài),如果是,則切換到空閑任務(wù),否則不進(jìn)行任務(wù)切換。

代碼清單5-11(3):任務(wù)切換,實際就是觸發(fā)PendSV異常。

主站蜘蛛池模板: 常山县| 文山县| 惠东县| 安阳县| 大荔县| 朝阳区| 江西省| 那曲县| 文水县| 东兰县| 静宁县| 清苑县| 泊头市| 怀仁县| 溧水县| 陇川县| 彩票| 嘉善县| 平原县| 青岛市| 建湖县| 石景山区| 瑞金市| 东明县| 栖霞市| 遂昌县| 出国| 鄄城县| 垫江县| 江西省| 渭南市| 临朐县| 类乌齐县| 茂名市| 南丰县| 凉山| 贵州省| 萝北县| 广平县| 石城县| 贵阳市|