[笔记].怎样给μ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)运行结果

image

 

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

posted @ 2010-05-10 09:45  _安德鲁  阅读(2550)  评论(2编辑  收藏  举报