(原創) 如何傳參數到每個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

task01

他會產生如下的code

hello_ucosii.c / C

1 #include <stdio.h>
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個參數如下

void task1(void* pdata, int i)
{
 
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
task
Pointer to task's code.
pdata
Pointer to optional data area; used to pass parameters to the task at start of execution.
prio
The task's unique priority number; the lower the number the higher the priority.
id
The task's identification number (0...65535).
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.
pext
Pointer to a user-supplied Task Control Block (TCB) extension.
opt
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_NO_ERR
The call was successful.
OS_PRIO_EXIT
Task priority already exists (each task MUST have a unique priority).
OS_PRIO_INVALID
The priority specified is higher than the maximum allowed (i.e., ≥OS_LOWEST_PRIO).
Library

OS_TASK.C

第二個參數是個void *,讓你可以傳各種參數的pointer進去,但也由於是void *,所以在使用時,必須自己轉型回來。

以下的範例實際傳入int, char *與struct *,示範怎麼將值傳進task內。

hello_ucosii.c / C

1 #include <stdio.h>
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 }


執行結果

task02

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

posted on 2009-05-16 08:51  真 OO无双  阅读(4581)  评论(5编辑  收藏  举报

导航