UCOS學習筆記——任務相關的API函數的使用
任務相關的API函數的使用
任務的創建與刪除
OSTaskCreateO創建任務函數
OSTaskDel()刪除任務函數
任務的掛起與恢復
OSTaskSuspend()函數
OSTaskResume()函數
程序設計
主函數:
開始任務函數
tsck1()任務函數
task2()任務函數
任務的掛起與恢復
任務的創建與刪除
OSTaskCreateO創建任務函數
UCOSIII是多任務系統,那么肯定要能創建任務,創建任務就是將任務控制塊、任務堆棧、任務代碼等聯系在一起,并且初始化任務控制塊的相應字段。在UCOSIII中我們通過函數OSTaskCreate(來創建任務,OSTaskCreate()函 數原型如下(在os_task.c 中有義)。調用OSTaskCreat()創建一一個任務 以后,剛創建的任務就會進入就緒態,注意!
不能在中斷服務程序中調用OSTaskCreat( )函數來創建任務。
void OSTaskCreate (OS TCB *p_ tcb, CPU CHAR *p_ name, OS TASK PTR p_ task, void *p_ arg, OS PRIO prio, CPU STK *p_ stk_ base, CPU STK SIZE stk_ limit, CPU STK_ SIZE stk_ size, OS MSG QTY q size, OS TICK time_ quanta, void *p_ ext, OS OPT opt, OS ERR *p_ err)
1
2
3
4
5
6
7
8
9
10
11
12
*p_ tcb: 指向任務的任務控制塊OS_ TCB
*P_ name: 指向任務的名字,我們可以給每個任務取一一個名字
p_ task: 執行任務代碼,也就是任務函數名字.
*P_ arg: 傳遞給任務的參數
prio: 任務優先級,數值越低優先級越高,用戶不能使用系統任務使用的那些優先級!
*p_stk_base: 指向任務堆棧的基地址。
stk_ limit: 任務堆棧的堆棧深度,用來檢測和確保堆棧不溢出。
stk_ size: 任務堆棧大小
q_ size: UCOSIII中每個任務都有一一個可選的內部消息隊列,我們要定義宏OS_ CFG_ TASK_ Q EN>0,這是才會使用這個內部消息隊列。
time_quanta: 在使能時間片輪轉調度時用來設置任務的時間片長度,默認值為時鐘節拍除以10。
*P_ ext: 指向用戶補充的存儲區。
opt: 包含任務的特定選項,有如下選項可以設置。
*p_ err: 用來保存調用該函數后返回的錯誤碼。
OSTaskDel()刪除任務函數
OSTaskDel()函數用來刪除任務,當一個任務不需要運行的話,我們就可以將其刪除掉,刪除任務不是說刪除任務代碼,而是UCOSIII不再管理這個任務,在有些應用中我們只需要某個任務只運行一一次,運行完成后就將其刪除掉,比如外設初始化任務, OSTaskDel()函數原型如下:
void OSTaskDel (OS_TCB *P_ tcb, OS_ERR *p_err)
1
雖然UCOSIII允許用戶在系統運行的時候來刪除任務,但是應該盡量的避免這樣的操作,如果多個任務使用同一個共享資源,這個時候任務A正在使用這個共享資源,如果刪除了任務A,這個資源并沒有得到釋放,那么其他任務就得不到這個共享資源的使用權,會出現各種奇怪的結果。
我們調用OSTaskDel()刪除一個任務后, 這個任務的任務堆棧、OS_ TCB所占用的內存并沒有釋放掉,因此我們可以利用他們用于其他的任務,當然我們也可以使用內存管理的方法給任務堆棧和OS_ TCB分配內存,這樣當我們刪除掉某個任務后我們就可以使用內存釋放函數將這個任務的任務堆棧和OS_ TCB所占用的內存空間釋放掉。
任務的掛起與恢復
OSTaskSuspend()函數
有時候有些任務因為某些原因需要暫停運行,但是以后還要運行,因此我們就不能刪除掉任務,這里我們可以使用OSTaskSuspend()函 數掛起這個任務,以后再恢復運行,函數OSTaskSuspend()的原型如下:
void OSTaskSuspend (OS TCB *p tcb,OS ERR*p_ err)
OSTaskResume()函數
OSTaskResume()函數用來恢復
被OSTaskSuspend()函數掛起的任務
,OSTaskResume()函數是唯一能恢復被掛起任務的函數。如果被掛起的任務還在等待別的內核對象,比如事件標志組、信號量、互斥信號量、消息隊列等,即使使用OSTaskResume()函數恢復了被掛起的任務,該任務也不一定能立即運行,該任務還是要等相應的內核對象,只有等到內核對象后才可以繼續運行,OSTaskResume()函數原型如下:
void OSTaskResume (OS_ TCB *p_ tcb,OS_ ERR *p_ err)
*p_ tcb:
向需要解掛的任務的OS_ TCB, 指向一個NULL指針是無效的,因為該任務正
在運行,不需要解掛。
*p err:
指向一個變量,用來保存該函數的錯誤碼。
程序設計
(1)創建開始任務start_ task, start_ task任務用來創建另外兩個任務: task1_ task和task2_ task。
(2)開始任務start_ task 中用來創建任務1: taskl_ task.
(3)開始任務start task 中用來創建任務2: task2_ task.
(4)開始任務start task只是用來創建任務task1_ task 和task2_ task, 那么這個任務肯定只需要執行–次,
兩個任務創建完成以后就可以刪除掉start_task任務
了,這里我們使用OSTaskDel()函數刪除掉任務自身,這里傳遞給OSTaskDel(函數參數p_ tcb 的值為0,表示刪除掉任務自身。
(5)根據要求我們在任務1執行5次后由任務1刪除掉任務2,這里通過調用OSTaskDel()函數刪除掉任務2,注意這時我們傳遞給OSTaskDel)中參數p_ tcb 的值為任務2的任務控制塊Task2_ TaskTCB的地址,因此這里我們用了取址號“&”。
(6)調用函數OSTimeDlyHMSM(延時ls, 調用OSTimeDlyHMSM()函數以后就會發起一個任務切換。
主函數:
#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "lcd.h" #include "includes.h" //任務優先級 #define START_TASK_PRIO 3 //任務堆棧大小 #define START_STK_SIZE 128 //任務控制塊 OS_TCB StartTaskTCB; //任務堆棧 CPU_STK START_TASK_STK[START_STK_SIZE]; //任務函數 void start_task(void *p_arg); //任務優先級 #define TASK1_TASK_PRIO 4 //任務堆棧大小 #define TASK1_STK_SIZE 128 //任務控制塊 OS_TCB Task1_TaskTCB; //任務堆棧 CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE]; void task1_task(void *p_arg); //任務優先級 #define TASK2_TASK_PRIO 5 //任務堆棧大小 #define TASK2_STK_SIZE 128 //任務控制塊 OS_TCB Task2_TaskTCB; //任務堆棧 CPU_STK TASK2_TASK_STK[TASK2_STK_SIZE]; //任務函數 void task2_task(void *p_arg); //LCD刷屏時使用的顏色 int lcd_discolor[14]={ WHITE, BLACK, BLUE, BRED, GRED, GBLUE, RED, MAGENTA, GREEN, CYAN, YELLOW,BROWN, BRRED, GRAY }; int main(void) { OS_ERR err; CPU_SR_ALLOC(); delay_init(); //時鐘初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中斷分組配置 uart_init(115200); //串口初始化 LED_Init(); //LED初始化 LCD_Init(); //LCD初始化 POINT_COLOR = RED; LCD_ShowString(30,10,200,16,16,"ALIENTEK STM32F1"); LCD_ShowString(30,30,200,16,16,"UCOSIII Examp 6-1"); LCD_ShowString(30,50,200,16,16,"Task Creat and Del"); LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK"); LCD_ShowString(30,90,200,16,16,"2015/3/19"); OSInit(&err); //初始化UCOSIII OS_CRITICAL_ENTER(); //進入臨界區 //創建開始任務 OSTaskCreate((OS_TCB * )&StartTaskTCB, //任務控制塊 (CPU_CHAR * )"start task", //任務名字 (OS_TASK_PTR )start_task, //任務函數 (void * )0, //傳遞給任務函數的參數 (OS_PRIO )START_TASK_PRIO, //任務優先級 (CPU_STK * )&START_TASK_STK[0], //任務堆棧基地址 (CPU_STK_SIZE)START_STK_SIZE/10, //任務堆棧深度限位 (CPU_STK_SIZE)START_STK_SIZE, //任務堆棧大小 (OS_MSG_QTY )0, //任務內部消息隊列能夠接收的最大消息數目,為0時禁止接收消息 (OS_TICK )0, //當使能時間片輪轉時的時間片長度,為0時為默認長度, (void * )0, //用戶補充的存儲區 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任務選項 (OS_ERR * )&err); //存放該函數錯誤時的返回值 OS_CRITICAL_EXIT(); //退出臨界區 OSStart(&err); //開啟UCOSIII }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
開始任務函數
void start_task(void *p_arg) { OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; CPU_Init(); #if OS_CFG_STAT_TASK_EN > 0u OSStatTaskCPUUsageInit(&err); //統計任務 #endif #ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了測量中斷關閉時間 CPU_IntDisMeasMaxCurReset(); #endif #if OS_CFG_SCHED_ROUND_ROBIN_EN //當使用時間片輪轉的時候 //使能時間片輪轉調度功能,時間片長度為1個系統時鐘節拍,既1*5=5ms OSSchedRoundRobinCfg(DEF_ENABLED,1,&err); #endif OS_CRITICAL_ENTER(); //進入臨界區 //創建TASK1任務 //創建TASK1任務 OSTaskCreate((OS_TCB * )&Task1_TaskTCB, (CPU_CHAR * )"Task1 task", (OS_TASK_PTR )task1_task, (void * )0, (OS_PRIO )TASK1_TASK_PRIO, (CPU_STK * )&TASK1_TASK_STK[0], (CPU_STK_SIZE)TASK1_STK_SIZE/10, (CPU_STK_SIZE)TASK1_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); //創建TASK2任務 OSTaskCreate((OS_TCB * )&Task2_TaskTCB, (CPU_CHAR * )"task2 task", (OS_TASK_PTR )task2_task, (void * )0, (OS_PRIO )TASK2_TASK_PRIO, (CPU_STK * )&TASK2_TASK_STK[0], (CPU_STK_SIZE)TASK2_STK_SIZE/10, (CPU_STK_SIZE)TASK2_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); OS_CRITICAL_EXIT(); //退出臨界區 OSTaskDel((OS_TCB*)0,&err); //刪除start_task任務自身 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
tsck1()任務函數
void task1_task(void *p_arg) { u8 task1_num=0; OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; POINT_COLOR = BLACK; OS_CRITICAL_ENTER(); LCD_DrawRectangle(5,110,115,314); //畫一個矩形 LCD_DrawLine(5,130,115,130); //畫線 POINT_COLOR = BLUE; LCD_ShowString(6,111,110,16,16,"Task1 Run:000"); OS_CRITICAL_EXIT(); while(1) { task1_num++; //任務執1行次數加1 注意task1_num1加到255的時候會清零!! LED0= ~LED0; printf("任務1已經執行:%d次\r\n",task1_num); if(task1_num==5) { OSTaskDel((OS_TCB*)&Task2_TaskTCB,&err); //任務1執行5此后刪除掉任務2 printf("任務1刪除了任務2!\r\n"); } LCD_Fill(6,131,114,313,lcd_discolor[task1_num%14]); //填充區域 LCD_ShowxNum(86,111,task1_num,3,16,0x80); //顯示任務執行次數 OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //延時1s } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
task2()任務函數
void task2_task(void *p_arg) { u8 task2_num=0; OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; POINT_COLOR = BLACK; OS_CRITICAL_ENTER(); LCD_DrawRectangle(125,110,234,314); //畫一個矩形 LCD_DrawLine(125,130,234,130); //畫線 POINT_COLOR = BLUE; LCD_ShowString(126,111,110,16,16,"Task2 Run:000"); OS_CRITICAL_EXIT(); while(1) { task2_num++; //任務2執行次數加1 注意task1_num2加到255的時候會清零!! LED1=~LED1; printf("任務2已經執行:%d次\r\n",task2_num); LCD_ShowxNum(206,111,task2_num,3,16,0x80); //顯示任務執行次數 LCD_Fill(126,131,233,313,lcd_discolor[13-task2_num%14]); //填充區域 OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //延時1s } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
任務的掛起與恢復
(1) 根據要求任務1運行5次后調用OSTaskSuspend()函數掛起任務2。
(2)當任務1運行到第10次就調用函數OSTaskResume()函數解掛任務2。
API
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。