[笔记].怎样给μC/OS-II的任务传递参数
0 引子
近日,我在萧大哥的博客里闲逛,渐知μC/OS-II用途甚广,使用方便;于是就照虎画猫,写几篇博文。
1 范例
(1) ucos_ii_test.c
#include <stdio.h> #include <string.h> #include "includes.h" // 定义任务的栈 #define TASK_STACKSIZE 2048 OS_STK task1_stk[TASK_STACKSIZE]; OS_STK task2_stk[TASK_STACKSIZE]; OS_STK task3_stk[TASK_STACKSIZE]; OS_STK task4_stk[TASK_STACKSIZE]; // 定义任务的优先级 #define TASK1_PRIORITY 1 #define TASK2_PRIORITY 2 #define TASK3_PRIORITY 3 #define TASK4_PRIORITY 4 // 声明任务 void task1(void* pData); // 任务1:传递整型参数 void task2(void* pData); // 任务2:传递字符参数 void task3(void* pData); // 任务3:传递字符串参数 void task4(void* pData); // 任务4:传递结构体参数 // 定义结构体 typedef struct { int iA; char cB; char sC[10]; }myStruct_t; int main() { // int iA=5; // char cB = 't'; // char sC[] = "test"; // myStruct_t pStr; pStr.iA = 5; pStr.cB = 't'; strcpy(pStr.sC, "test"); // 任务1:传递整型参数 OSTaskCreateExt(task1, &iA, (void *)&task1_stk[TASK_STACKSIZE-1], TASK1_PRIORITY, TASK1_PRIORITY, task1_stk, TASK_STACKSIZE, NULL, 0); // 任务2:传递字符参数 OSTaskCreateExt(task2, &cB, (void *)&task2_stk[TASK_STACKSIZE-1], TASK2_PRIORITY, TASK2_PRIORITY, task2_stk, TASK_STACKSIZE, NULL, 0); // 任务3:传递字符串参数 OSTaskCreateExt(task3, sC, (void *)&task3_stk[TASK_STACKSIZE-1], TASK3_PRIORITY, TASK3_PRIORITY, task3_stk, TASK_STACKSIZE, NULL, 0); // 任务4:传到结构体参数 OSTaskCreateExt(task4, &pStr, (void *)&task4_stk[TASK_STACKSIZE-1], TASK4_PRIORITY, TASK4_PRIORITY, task4_stk, TASK_STACKSIZE, NULL, 0); OSStart(); return 0; } // 任务1:传递整型参数 void task1(void* pData) { while (1) { printf("task1, iA = %d\n", *((int *)pData)); OSTimeDlyHMSM(0, 0, 1, 0); } } // 任务2:传递字符参数 void task2(void* pData) { while (1) { printf("task2, cB = %c\n", *((char *)pData)); OSTimeDlyHMSM(0, 0, 1, 0); } } // 任务3:传递字符串参数 void task3(void* pData) { while (1) { printf("task3, sC = %s\n", (char *)pData); OSTimeDlyHMSM(0, 0, 1, 0); } } // 任务4:传递结构体参数 void task4(void* pData) { while (1) { printf("task4, iA = %i\n", ((myStruct_t *)pData)->iA); printf("task4, cB = %c\n", ((myStruct_t *)pData)->cB); printf("task4, sC = %s\n", ((myStruct_t *)pData)->sC); OSTimeDlyHMSM(0, 0, 1, 0); } }
(2)运行结果
2 解析
从OSTaskCreateExt()的源代码中,可知pData就是所能传递的参数。
第48行,传递整型变量iA的地址;但是pdata却是空型指针。为了匹配存储内容,在第99行,将从&iA开始的存储区域强制转化为整型指针,故有(
int
*)pData;使用(*)访问内容即可,如
*((
int
*)pData)
。如表1所示。
表1 task1中所传参数的存储映射
表达式 | 存储地址 | 存储长度 | 存储内容 |
int iA=5; |
&iA | sizeof(int) | 5 |
void * pData |
不变 | 未知 | 未知 |
*(( int *)pData) |
不变 | sizeof(int) | 5 |
任务2的字符参数与任务1的整型参数类似,如表2所示。
表达式 | 存储地址 | 存储长度 | 存储内容 |
char cB = 't' ; |
&cB | sizeof(char) | t |
void * pData |
不变 | 未知 | 未知 |
*(( char *)pData) |
不变 | sizeof(char) | t |
任务3中%s本身只需传入参数的地址即可,故使用(
char
*)pData将从*pData开始的存储区域强制转化为char型指针即可。
任务4中,传入的参数是结构体,另写博文浅析。
总之,以上所谓传递的四种参数类型,皆是在在传递地址,以准确映射所在地址的存储内容。
3 附录
(1)INT8U OSTaskCreateExt() 源代码
/* ********************************************************************************************************* * CREATE A TASK (Extended Version) * * Description: This function is used to have uC/OS-II manage the execution of a task. 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. * * Arguments : task is a pointer to the task's code * * pdata is a pointer to an optional data area which can be used to pass parameters to * the task when the task first executes. Where the task is concerned it thinks * it was invoked and passed the argument 'pdata' as follows: * * void Task (void *pdata) * { * for (;;) { * Task code; * } * } * * ptos is a pointer to the task's top of stack. If the configuration constant * OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high * memory to low memory). 'pstk' will thus point to the highest (valid) memory * location of the stack. If OS_STK_GROWTH is set to 0, 'pstk' will point to the * lowest memory location of the stack and the stack will grow with increasing * memory locations. 'pstk' MUST point to a valid 'free' data item. * * prio is the task's priority. A unique priority MUST be assigned to each task and the * lower the number, the higher the priority. * * id is the task's ID (0..65535) * * pbos is a pointer to the task's bottom of stack. If the configuration constant * OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high * memory to low memory). 'pbos' will thus point to the LOWEST (valid) memory * location of the stack. If OS_STK_GROWTH is set to 0, 'pbos' will point to the * HIGHEST memory location of the stack and the stack will grow with increasing * memory locations. 'pbos' MUST point to a valid 'free' data item. * * stk_size is the 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 is a pointer to a user supplied memory location which is used as a TCB extension. * For example, this user memory can hold the contents of floating-point registers * during a context switch, the time each task takes to execute, the number of times * the task has been switched-in, etc. * * opt contains additional information (or options) about the behavior of the task. The * LOWER 8-bits are reserved by uC/OS-II while the upper 8 bits can be application * specific. See OS_TASK_OPT_??? in uCOS-II.H. * * Returns : OS_NO_ERR if the function was successful. * OS_PRIO_EXIT if the task priority already exist * (each task MUST have a unique priority). * OS_PRIO_INVALID if the priority you specify is higher that the maximum allowed * (i.e. > OS_LOWEST_PRIO) ********************************************************************************************************* */ INT8U OSTaskCreateExt (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio, INT16U id, OS_STK *pbos, INT32U stk_size, void *pext, INT16U opt) { #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; #endif OS_STK *psp; INT8U err; #if OS_ARG_CHK_EN > 0 if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */ return (OS_PRIO_INVALID); } #endif OS_ENTER_CRITICAL(); if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority */ OSTCBPrioTbl[prio] = (OS_TCB *)1; /* Reserve the priority to prevent others from doing ... */ /* ... the same thing until task is created. */ OS_EXIT_CRITICAL(); if (((opt & OS_TASK_OPT_STK_CHK) != 0x0000) || /* See if stack checking has been enabled */ ((opt & OS_TASK_OPT_STK_CLR) != 0x0000)) { /* See if stack needs to be cleared */ #if OS_STK_GROWTH == 1 (void)memset(pbos, 0, stk_size * sizeof(OS_STK)); #else (void)memset(ptos, 0, stk_size * sizeof(OS_STK)); #endif } psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, opt); /* Initialize the task's stack */ err = OS_TCBInit(prio, psp, pbos, id, stk_size, pext, opt); if (err == OS_NO_ERR) { OS_ENTER_CRITICAL(); OSTaskCtr++; /* Increment the #tasks counter */ OS_EXIT_CRITICAL(); if (OSRunning == TRUE) { /* Find HPT if multitasking has started */ OS_Sched(); } } else { OS_ENTER_CRITICAL(); OSTCBPrioTbl[prio] = (OS_TCB *)0; /* Make this priority avail. to others */ OS_EXIT_CRITICAL(); } return (err); } OS_EXIT_CRITICAL(); return (OS_PRIO_EXIST); }
4 参考
1. 真 OO無雙.(原創) 如何傳參數到每個task? (SOC) (Nios II) (μC/OS-II) (DE2-70)
2. Micrium.Micrium-uCOS-II-V286.ZIP\Micrium\SOFTWARE\uCOS-II\Source\os_task.c