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
Creates a task to be managed by µC/OS-II. Tasks can either be created prior to the start of multitasking or by a running task. A task cannot be created by an ISR. This function is similar to
OSTaskCreate()
except that it allows additional information about a task to be specified.
Parameters
pdata prio id stk_size-
Size of the stack in number of elements. If
OS_STK
is set to
INT8U
,
stk_size
corresponds to the number of bytes available. If
OS_STK
is set to
INT16U
,
stk_size
contains the number of 16-bit entries available. Finally, if
OS_STK
is set to
INT32U
,
stk_size
contains the number of 32-bit entries available on the stack.
-
The lower 8 bits are reserved by µC/OS-II. The upper 8 bits control application-specific options. Select an option by setting the corresponding bit(s).
Return value
OS_PRIO_EXIT OS_PRIO_INVALIDLibrary
OS_TASK.C
第二個參數是個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