task1,task2具相同優先權時,其時序圖如下:
void printTask1(void *ptr)
{
int i;
char *str="Task 1\n";
while(1) {
printf(str);
for(i=0;i<10000;i++);
}
}
void printTask2(void *ptr)
{
int i;
char *str="Task 2\n";
while(1) {
printf(str);
for(i=0;i<10000;i++);
}
}
int main(void) {
xTaskCreat(printTask1,"Task 1",256,NULL,1,NULL);
xTaskCreat(printTask1,"Task 2",256,NULL,1,NULL);
vTaskStartScheduler();
while(1);
return 0;
}
不同工作共用工作程序
使用參數
上一範例Task1,Task2只有列印字串不同,故可以共用工作程序,將要列印字串以參數輸入
範例
void printTask(void *ptr)//空資料型態,讓程式碼可以接收任何資料型態,在程式碼中在予以轉型成所要的資料型態
{
char *str;
int i;
str=(char *)ptr;
while(1) {
printf(str);
for(i=0;i<10000;i++);
}
}
int main(void) {
char *str1="Task 1\n"
char *str2="Task 2\n"
xTaskCreat(printTask,"Task 1",256,(void *)str1,1,NULL);
xTaskCreat(printTask,"Task 2",256,(void *)str2,1,NULL);
vTaskStartScheduler();
while(1);
return 0;
}
void printTask(void *ptr)
{
char *str;
int i;
str=(char *)ptr;
while(1){
printf(str);
for(i=0;i<10000;i++);
}
}
int main(void){
char *str1="Task1 \n";
char *str2="Task2 \n";
xTaskCreate(printTask,"Task1",256,(void *)str1,1,NULL);
xTaskCreate(printTask,"Task2",256,(void *)str2,1,NULL);
vTaskStartScheduler();
while(1);
return 0;
}
clementyan@Lenovo-B480:~$ cd Document/micro/Posix_GCC_Simulator/FreeRTOS_Posix/Release/
clementyan@Lenovo-B480:~/Document/micro/Posix_GCC_Simulator/FreeRTOS_Posix/Release$ mkdir example
clementyan@Lenovo-B480:~/Document/micro/Posix_GCC_Simulator/FreeRTOS_Posix/Release$ cd example/
clementyan@Lenovo-B480:~/Document/micro/Posix_GCC_Simulator/FreeRTOS_Posix/Release/example$ mkdir ex1
clementyan@Lenovo-B480:~/Document/micro/Posix_GCC_Simulator/FreeRTOS_Posix/Release/example$ cd ex1/
clementyan@Lenovo-B480:~/Document/micro/Posix_GCC_Simulator/FreeRTOS_Posix/Release/example/ex1$
clementyan@Lenovo-B480:~/Document/micro/Posix_GCC_Simulator/FreeRTOS_Posix/Release/example/ex1$ vi main.c
撰寫完成後把main.c複製到FreeRTOS_Posix
在至Release底下
make clean
make
clementyan@Lenovo-B480:~/Document/micro/Posix_GCC_Simulator/FreeRTOS_Posix/Release/example/ex1$ cp main.c ../../../main1.c
clementyan@Lenovo-B480:~/Document/micro/Posix_GCC_Simulator/FreeRTOS_Posix/Release/example/ex1$ cd ../../../
clementyan@Lenovo-B480:~/Document/micro/Posix_GCC_Simulator/FreeRTOS_Posix$
clementyan@Lenovo-B480:~/Document/micro/Posix_GCC_Simulator/FreeRTOS_Posix/Release$ make
clementyan@Lenovo-B480:~/Document/micro/Posix_GCC_Simulator/FreeRTOS_Posix/Release$ make clean
不同優先權時序圖如下:
大於Tick中斷→Task1進入Ready→排程管理員找所有Ready工作中優先權最高之工作來執行或輪流→Task1最高故執行Task1工作→低優先權工作將飢餓而死(starvation)
避免飢餓現象,高優先權工作需進入阻斷狀態(blocked state),即當高優先權工作進入等待時間需能讓出執行權,通常可經由阻斷API呼叫而達成
阻斷API有下列兩個
vTaskDelay(延遲滴答數)//延遲時間較不固定
vTaskDelayUntil(上次工作時間,延遲滴答數)//延遲時間較固定
排程管理元只看ready的工作,在阻斷狀態不會被檢查到,故不會執行,只有在ready狀態時被排程管理員看到才會被執行
方塊圖如下:
時序圖圖下:
void vTask1(void *ptr) {//priority=2
char *str=(char *)ptr;
while(1) {
printf(str);
vTaskDelay(20);
}
}
void vTask2(void *ptr) {//priority=1
char *str=(char *)ptr;
int i;
while(1) {
printf(str);
vTaskDelay(2);
}
}
int main(void) {
char *str1="Task 1\n";
char *str2="Task 2\n";
xTaskCreate(vTask1,"Task 1",256,(void *)str1,2,NULL);
xTaskCreate(vTask2,"Task 2",256,(void *)str2,1,NULL);
vTaskStartScheduler();
while(1);
return 0;
}
vTaskDelayUntil與vTaskDelay功能相似,但可以達到更精確之時間延遲
取得執行時間(目前系統之滴答數)其資料型態為portTickType故變數之宣告方式為portTicktype 變數名稱;
例
porTickType xLastWakeTime;
xLastWakeTime=xTaskGetTickCount();
使用vTaskDelayUntil之工作程序格式為
void 工作名稱(void *ptr) {
portTickType xLastWake;
xLastWake=xTaskGetTickCount();//會有一個Tick的時間誤差,但較精準
.
.
while(1) {
.
.
vTaskDelayUntil(xLastWake,延遲之Tick數);
}
}
透過工作指標改變工作優先權,一此方式亦可解決飢餓現象,其方法為高優先權之工作提升低優先權工作之優先權,使其可以取得工作時間,但也需低優先權工作需回覆自己之優先權,以維護程式之正常運作(由高優先權來決定是否要給低優先權工作,則可以提高低優先權之優先權)
工作指標(Task Handle)之資料型態為
xTaskHandle工作指標變數之宣告
xTaskHandle 工作指標變數名稱;
通常需宣告為全域變數
取得工作指標(由xTaskCreate函式之第六個參數位置可以取得)
如:
xTaskHandle task1Handle;
xTaskHandle task2Handle;
int main(void) {
xTaskCreate(vTask1,"Task 1",256,NULL,2,&task1Handle);//&task1Handle指該task1Handle變數的位址
xTaskCreate(vTask2,"Task 2",256,NULL,2,&task2Handle);
.
.
}
更改優先權
vTaskPrioritySet(工作指標,優先權值)要更改工作自己優先權時,工作指標為NULL
取得工作優先權之API
uxTaskPriorityGet(工作指標)
其回傳值之資料型態為portBASE.TYPE
例
porBASE.TYPE myPriority;
myPriority=uxTaskPriorityGet(NULL);//取得工作自己
更改優先權範例
原Task1優先權=2
Task1優先權=1
執行Task1時將Task2之優先權提升為3
執行Task2時將Task2之優先權提升為1
xTaskHandle task2Handle;
void Task1(void *ptr) {
char *str=(char *)ptr;
int i;
while(1) {
printf(str);
vTaskPrioritySet(&task2Handle,3);
for(i=0;i<1000;i++);
}
}
void Task2(void *ptr) {
char *str=(char *)ptr;
int i;
while(1) {
printf(str);
vTaskPrioritySet(NULL,1);
for(i=0;i<1000;i++);
}
}
沒有留言:
張貼留言
文章有誤或有問題麻煩您留言告知! 謝謝您~~