(原創) 如何傳參數到每個task? (SOC) (Nios II) (μC/OS-II) (DE2-70)
Abstract
當我們在μC/OS-II使用Multi Thread時,會將程式包在task內,但要如何將參數傳到task內呢?
Introduction
使用環境:Quartus II 8.1 + Nios II EDS 8.1 + DE2-70(Cyclone II EP2C35F627C6)
當我們想利用μC/OS-II的Multi Thread功能時,我們會使用Nios II EDS內建的Hello MicroC/OS-II project template
他會產生如下的code
hello_ucosii.c / C
2 #include "includes.h"
3
4 /* Definition of Task Stacks */
5 #define TASK_STACKSIZE 2048
6 OS_STK task1_stk[TASK_STACKSIZE];
7 OS_STK task2_stk[TASK_STACKSIZE];
8
9 /* Definition of Task Priorities */
10
11 #define TASK1_PRIORITY 1
12 #define TASK2_PRIORITY 2
13
14 /* Prints "Hello World" and sleeps for three seconds */
15 void task1(void* pdata)
16 {
17 while (1)
18 {
19 printf("Hello from task1\n");
20 OSTimeDlyHMSM(0, 0, 3, 0);
21 }
22 }
23 /* Prints "Hello World" and sleeps for three seconds */
24 void task2(void* pdata)
25 {
26 while (1)
27 {
28 printf("Hello from task2\n");
29 OSTimeDlyHMSM(0, 0, 3, 0);
30 }
31 }
32 /* The main function creates two task and starts multi-tasking */
33 int main(void)
34 {
35
36 OSTaskCreateExt(task1,
37 NULL,
38 (void *)&task1_stk[TASK_STACKSIZE-1],
39 TASK1_PRIORITY,
40 TASK1_PRIORITY,
41 task1_stk,
42 TASK_STACKSIZE,
43 NULL,
44 0);
45
46
47 OSTaskCreateExt(task2,
48 NULL,
49 (void *)&task2_stk[TASK_STACKSIZE-1],
50 TASK2_PRIORITY,
51 TASK2_PRIORITY,
52 task2_stk,
53 TASK_STACKSIZE,
54 NULL,
55 0);
56 OSStart();
57 return 0;
58 }
假如我們想從main()傳參數到task1或task2,你可能會發現不知道該怎麼傳,主要task1與task2是個callback,是由μC/OS-II所呼叫,並不是由main()去呼叫,就算你自己替task1增加1個參數如下
{
while (1)
{
printf("Hello from task1\n");
OSTimeDlyHMSM(0, 0, 3, 0);
}
}
還是會發現這個int i不知道要怎麼傳進去…。
Solution
你可能有發現 void *pdata這個參數,對!!這就是μC/OS-II所留下的後門。
根據http://www.rabbit.com/documentation/docs/modules/ucos2/ModUcos49.htm
OSTaskCreateExt()這個API的定義如下
INT8U OSTaskCreateExt (void (*task)(), void *pdata, INT8U prio, INT16U id, INT16U stk_size, void *pext, INT16U opt);
Description
Parameters
- task
- pdata
- prio
- id
- stk_size
- Size of the stack in number of elements. If
OS_STK
is set toINT8U
,stk_size
corresponds to the number of bytes available. IfOS_STK
is set toINT16U
,stk_size
contains the number of 16-bit entries available. Finally, ifOS_STK
is set toINT32U
,stk_size
contains the number of 32-bit entries available on the stack. - pext
- opt
Return value
Library
第二個參數是個void *,讓你可以傳各種參數的pointer進去,但也由於是void *,所以在使用時,必須自己轉型回來。
以下的範例實際傳入int, char *與struct *,示範怎麼將值傳進task內。
hello_ucosii.c / C
2 #include <string.h>
3 #include "includes.h"
4
5 /* Definition of Task Stacks */
6 #define TASK_STACKSIZE 2048
7 OS_STK task1_stk[TASK_STACKSIZE];
8 OS_STK task2_stk[TASK_STACKSIZE];
9 OS_STK task3_stk[TASK_STACKSIZE];
10
11 /* Definition of Task Priorities */
12
13 #define TASK1_PRIORITY 1
14 #define TASK2_PRIORITY 2
15 #define TASK3_PRIORITY 3
16
17 typedef struct people {
18 int no;
19 char name[20];
20 } student, *pstudent;
21
22 /* Prints "Hello World" and sleeps for three seconds */
23 void task1(void* pdata)
24 {
25 while (1)
26 {
27 printf("task1 is %s\n", (char *)pdata);
28 OSTimeDlyHMSM(0, 0, 3, 0);
29 }
30 }
31 /* Prints "Hello World" and sleeps for three seconds */
32 void task2(void* pdata)
33 {
34 while (1)
35 {
36 printf("task2 is %d\n", *((int *)pdata));
37 OSTimeDlyHMSM(0, 0, 3, 0);
38 }
39 }
40
41 /* Prints "Hello World" and sleeps for three seconds */
42 void task3(void* pdata)
43 {
44 while (1)
45 {
46 printf("task3 is %d\n", ((pstudent)pdata)->no);
47 printf("task3 is %s\n", ((pstudent)pdata)->name);
48 OSTimeDlyHMSM(0, 0, 3, 0);
49 }
50 }
51 /* The main function creates two task and starts multi-tasking */
52 int main(void)
53 {
54 char str[] = "Hello World";
55 int i = 10;
56 student p;
57 p.no = 1;
58 strcpy(p.name, "oomusou");
59
60
61 OSTaskCreateExt(task1,
62 str,
63 (void *)&task1_stk[TASK_STACKSIZE-1],
64 TASK1_PRIORITY,
65 TASK1_PRIORITY,
66 task1_stk,
67 TASK_STACKSIZE,
68 NULL,
69 0);
70
71
72 OSTaskCreateExt(task2,
73 &i,
74 (void *)&task2_stk[TASK_STACKSIZE-1],
75 TASK2_PRIORITY,
76 TASK2_PRIORITY,
77 task2_stk,
78 TASK_STACKSIZE,
79 NULL,
80 0);
81
82
83 OSTaskCreateExt(task3,
84 &p,
85 (void *)&task3_stk[TASK_STACKSIZE-1],
86 TASK3_PRIORITY,
87 TASK3_PRIORITY,
88 task3_stk,
89 TASK_STACKSIZE,
90 NULL,
91 0);
92 OSStart();
93 return 0;
94 }
執行結果
task1示範怎麼傳遞字串,由於字串本身就是pointer,所以比較單純。task2示範如何傳遞int,task3示範如何傳struct,這兩個都必須另外使用&取pointer值。
傳進去後,由於接的是void *pdata,要另外轉型成各自型別的pointer,才能夠繼續使用。
完整程式碼下載
DE2_70_NIOS_pass_data_to_task.7z
Conclusion
這是C語言比較進階的部分,用到了callback、function pointer與void *等概念,也學到了若要使用callback時,可以設計void *的方式,讓各種型別的參數都能傳進去。
Reference
http://www.rabbit.com/documentation/docs/modules/ucos2/ModUcos49.htm