生活随笔
收集整理的這篇文章主要介紹了
任务延时队列
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 1 任務延時隊列
- 1.1 現有問題
- 1.2 延時隊列設計
- 1.3 設計實現
1 任務延時隊列
1.1 現有問題
現有問題:
- 每次時鐘節拍中斷都需要掃描所有任務,比較耗時。
- 不易支持多個任務具有相同優先級。
我們需要更加快速、簡單的結構,我們可以設計一個延時隊列。將所有需要延時的任務單獨放置在一個隊列中,每次發生系統時鐘節拍時,只需要掃描該隊列??梢杂袃煞N實現方式:
方式一:獨立保存延時時間。
方式二:遞增的延時隊列。
1.2 延時隊列設計
對于上述兩種延時隊列的設計方式,比較如下:
- 方式一插入延遲任務比較簡單,快速;掃描整個隊列教簡單,但較慢。
- 方式二插入延時任務比較復雜,較慢;掃描整個隊列較復雜,但較快。
我們采用方式一進行設計。
1.3 設計實現
添加延時隊列:
延時隊列的插入:
延時隊列的刪除:
時鐘節拍掃描延時隊列:
實現代碼如下:
#include "tinyOS.h"
#include "ARMCM3.h"
tTask
* currentTask
;
tTask
* nextTask
;
tTask
* idleTask
;
tBitmap taskPrioBitmap
;
tTask
* taskTable
[TINYOS_PRO_COUNT
];
uint8_t schedLockCount
;
tList tTaskDelayedList
;
void tTaskInit
(tTask
* task
, void (*entry
)(void *), void *param
, uint32_t prio
, uint32_t
* stack
)
{*(--stack
) = (unsigned long)(1<<24); *(--stack
) = (unsigned long)entry
; *(--stack
) = (unsigned long)0x14; *(--stack
) = (unsigned long)0x12; *(--stack
) = (unsigned long)0x3; *(--stack
) = (unsigned long)0x2; *(--stack
) = (unsigned long)0x1; *(--stack
) = (unsigned long)param
; *(--stack
) = (unsigned long)0x11; *(--stack
) = (unsigned long)0x10; *(--stack
) = (unsigned long)0x9; *(--stack
) = (unsigned long)0x8; *(--stack
) = (unsigned long)0x7; *(--stack
) = (unsigned long)0x6; *(--stack
) = (unsigned long)0x5; *(--stack
) = (unsigned long)0x4; task
->stack
= stack
; task
->delayTicks
= 0;task
->prio
= prio
; task
->state
= TINYOS_TASK_STATE_RDY
; tNodeInit(&(task
->delayNode
)); taskTable
[prio
] = task
; tBitmapSet(&taskPrioBitmap
, prio
);
}
tTask
* tTaskHighestReady
(void)
{uint32_t highestPrio
= tBitmapGetFirstSet(&taskPrioBitmap
);return taskTable
[highestPrio
];
}
void tTaskSchedInit
(void)
{schedLockCount
= 0;
}
void tTaskSchedDisable
(void)
{uint32_t status
= tTaskEnterCritical();if (schedLockCount
< 255) {schedLockCount
++;}tTaskExitCritical(status
);
}
void tTaskSchedEnable
(void)
{uint32_t status
= tTaskEnterCritical();if (schedLockCount
> 0) {if (--schedLockCount
== 0) {tTaskSched(); }}tTaskExitCritical(status
);
}
void tTaskSchedRdy
(tTask
* task
)
{taskTable
[task
->prio
] = task
;tBitmapSet(&taskPrioBitmap
, task
->prio
);
}
void tTaskSchedUnRdy
(tTask
* task
)
{taskTable
[task
->prio
] = (tTask
*)0;tBitmapClear(&taskPrioBitmap
, task
->prio
);
}
void tTaskSched
(void)
{ tTask
* tempTask
;uint32_t status
= tTaskEnterCritical();if (schedLockCount
> 0) {tTaskExitCritical(status
);return;}tempTask
= tTaskHighestReady();if (tempTask
!= currentTask
) {nextTask
= tempTask
;tTaskSwitch(); }tTaskExitCritical(status
);
}
void tTaskDelayedInit
(void)
{tListInit(&tTaskDelayedList
);
}
void tTimeTaskWait
(tTask
* task
, uint32_t ticks
)
{task
->delayTicks
= ticks
;tListAddLast(&tTaskDelayedList
, &(task
->delayNode
)); task
->state
|= TINYOS_TASK_STATE_DELAYED
;
}
void tTimeTaskWakeUp
(tTask
* task
)
{tListRemove(&tTaskDelayedList
, &(task
->delayNode
));task
->state
&= ~TINYOS_TASK_STATE_DELAYED
;
}
void tTaskSystemTickHandler
()
{tNode
* node
;uint32_t status
= tTaskEnterCritical();for (node
= tTaskDelayedList
.headNode
.nextNode
; node
!= &(tTaskDelayedList
.headNode
); node
= node
->nextNode
){tTask
* task
= tNodeParent(node
, tTask
, delayNode
);if (--task
->delayTicks
== 0) {tTimeTaskWakeUp(task
);tTaskSchedRdy(task
); }}tTaskExitCritical(status
); tTaskSched();
}
void tTaskDelay
(uint32_t delay
) {uint32_t status
= tTaskEnterCritical();tTimeTaskWait(currentTask
, delay
);tTaskSchedUnRdy(currentTask
);tTaskSched();tTaskExitCritical(status
);
}
void tSetSysTickPeriod(uint32_t ms
)
{SysTick
->LOAD
= ms
* SystemCoreClock
/ 1000 - 1; NVIC_SetPriority
(SysTick_IRQn
, (1<<__NVIC_PRIO_BITS
) - 1);SysTick
->VAL
= 0; SysTick
->CTRL
= SysTick_CTRL_CLKSOURCE_Msk
|SysTick_CTRL_TICKINT_Msk
|SysTick_CTRL_ENABLE_Msk
;
}
void SysTick_Handler
()
{tTaskSystemTickHandler();
}
int task1Flag
;
void task1Entry
(void * param
)
{tSetSysTickPeriod(10);for (;;) {task1Flag
= 1;tTaskDelay(1);task1Flag
= 0;tTaskDelay(1);}
}int task2Flag
;
void task2Entry
(void * param
)
{for (;;) {task2Flag
= 1;tTaskDelay(1);task2Flag
= 0;tTaskDelay(1);}
}
tTask tTask1
;
tTask tTask2
;
tTaskStack task1Env
[1024];
tTaskStack task2Env
[1024];
tTask tTaskIdle
;
tTaskStack idleTaskEnv
[1024];void idleTaskEntry
(void * param
) {for (;;){}
}int main
()
{tTaskSchedInit();tTaskDelayedInit();tTaskInit(&tTask1
, task1Entry
, (void *)0x11111111, 0, &task1Env
[1024]);tTaskInit(&tTask2
, task2Entry
, (void *)0x22222222, 1, &task2Env
[1024]);tTaskInit(&tTaskIdle
, idleTaskEntry
, (void *)0, TINYOS_PRO_COUNT
- 1, &idleTaskEnv
[1024]);nextTask
= tTaskHighestReady();tTaskRunFirst();return 0;
}
參考資料:
【李述銅】從0到1自己動手寫嵌入式操作系統
總結
以上是生活随笔為你收集整理的任务延时队列的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。