vTaskUntil(上次Task開始時間,延遲時間)從上次Task開始時間計時
Task2(void *ptr) {
.//假設中間程式碼需50Ticks
.
vTaskDelay(100);
}
Task1(void *ptr) {
取得執行開始時間
.
.//假設中間程式碼需50Ticks
vTaskUntil(開始執行時間,100);
}
時序圖如下:
工作排程之方式(Scheduling)
主要有三種:
- Preemptive強佔式:以高優先權為主,只要高優先權之工作在就緒狀態,則高優先權工作將先執行,直到其進入阻斷或擱置狀態為止(作業系統多以此為主,其反應較快,有饑餓現象)
- Selecting選擇式:單調速率排程(Rate Montonic Sechedule)(反應速度中)高優先權工作具有高CPU執行頻率,低優先權工作具有低CPU執行頻率,例:O.S.每秒執行100次工作切換,優先權分別為1,2,3,之工作分配到的工作次數分別為17,33,50
- Co-operative合作式:沒有優先權,輪流執行,工作執行後,進入就緒狀態。(較安全的作業系統,不易當機,反應較慢)
第二、三、四節------------------------------------------------------------------------------------------------------------
FreeRTOS使用強佔式排程法
Delete A Task 刪除工作
API: vTaskDelete(工作處理指標)
範例:
主迴圈執行工作1
工作1產生工作2
工作2執行後,結束工作。
時序圖如下:
xTaskHandle hTask2;//宣告hTask2為全域變數,代表位址
void Task1(void *ptr) {
char *str=(char *)ptr;
while(1) {
printf(str);
xTaskCreate(Task2,"Task2",256,NULL,2,&hTask2);//Task2的位址在hTask2,256堆疊指標大小取決Task2函式內是否有push/pop,或呼叫副程式
vTaskDelay(10);
}
}
void Task2(void *ptr) {
printf("Task2\n");
vTaskDelete(hTask2);
}
int main(void) {
char *str="Task1\n";
xTaskCreate(Task1,"Task1",256,(void *)str1,1,NULL);
vTaskStartScheduler();
while(1);
return 0;
}
Queue(佇列/排隊)
queue基本上為FIFO(first in first out)資料緩衝區
以上圖為列
資料由左邊進入後將會存放在最右邊第一個有空之格位,資料提取時,將提取最右邊之格住,最右邊格住資料被提取後,其他資料儲存格住需往右移一格。
Task1與Task2資料傳遞如圖:
Tassk之間透過Queue溝通資料
建立Queue
Queue處理指標之資料型態
xQueueHandle
建立Queue之API
使用xQueueCreate(unsigned portBASE_TYPE uxQueueLength,unsigned portBASE_TYPE uxItemSize)//uxQueueLength長度取決於頻率速度與存取速度,當進入速率快於讀取速率,則需把長度提高
上述API呼叫後會回傳Queue之處理指標,例:
寫資料到Queue
主要有
xQueueSendToBack(Queue指標,(const void *)資料指標,等待之tick數)//資料指標需小於uxItemSize(每格容量)
xQueueSendToFront(Queue指標,(const void *)資料指標,等待之tick數)//插隊放置最右邊
正常資料寫入Queue之尾部,故需使用xQueueSendToBack(或xQueueSend)
當有一筆特殊資料需被優先處理可以使用xQueueSendToFront將資料寫入Queue之最右邊格位
當要寫入之Queue滿格,無法寫入時,Task會進入阻斷狀態,直到等待之ticks數之滴答數為止,重新進入就緒狀態
例:
void Task(void *ptr) {
.
.
char data[256];
.
.
xQueueSendToBack(hQueue1,(const void *)data,50);
}
由Queue讀取資料有
xQueueReceive(Queue指標,(const void *)資料指標,等待tick數)//讀取完後資料會清除
xQueuePeak(Queue指標,(const void *)資料指標,等待tick數)//讀取完後資料不會清除
xQueueReceive提取Queue最右邊(頭部)資料後,會將頭部資料刪除,Queue其他儲存格會往前移一格
但xQueuePeak只會讀取Queue頭部資料,但不會刪除
當讀取資料時,若Queue為空時,Task會進入阻斷狀態,直到等待tick數會再進入就緒狀態
xQueueMessageWating(Queue之指標)此API可以讀取Queue中有資料之格位數
範例:
Task1產生資料寫入Queue
Task2從Queue讀取資料
xQueueHandle xQueue;
void vSendTask(void *ptr) {
long valueToSend;
portBASE_TYPE status;
valueToSend=*((long *)ptr);
while(1) {
status=xQueueSendToBack(xQueue,&valueToSend,0);//0表示不等待
if(status!=pdPASS) {
printf("Queue is full\n");
}
taskYIELD();//讓出工作權
}
}
xQueueHandle xQueue;
void vReceiveTask(void *ptr) {
long ReceivedValue;
portBASE_TYPE status;
if(xQueueMessageWaiting(xQueue)!=0) {
printf("Queue not empty\n");
}
while(1) {
status=xQueueReceive(xQueue,&ReceiveValue,10);//0表示不等待
if(status==pdPASS) {
printf("Received Value=%l\n",ReceivedValue);
}
}
沒有留言:
張貼留言
文章有誤或有問題麻煩您留言告知! 謝謝您~~