首页 > 技术文章 > FreeRTOS——使用任务参数创建任务

Liu-Jing 2017-06-24 21:15 原文

 1. main()函数在启动调度器之前先完成两个任务的创建。如下面所示:

static void AppTaskCreate(void)
{
    xTaskCreate(vTaskBeep,"Task Beep", 512, NULL, 1, &xHandleTaskBeep);
    
    xTaskCreate(vTaskLed1,                   /* 任务函数名 */
                            "Task Led1",                   /* 任务名,字符串形式,方便调试 */
                             512,                          /* 栈大小,单位为字,即4个字节 */
                             NULL,                      /* 任务形参 */
                             2,                     /* 优先级,数值越大,优先级越高 */
                 &xHandleTaskLED1);     /* 任务句柄 */
    
    
}

2、从一个任务中创建另一个任务。我们可以先在 main()中创建任务 1,然后在任务 1 中创建任务2。

这样,在调度器启动之前,任务 2 还没有被创建,但是整个程序运行的输出结果还是相同的。

void vTask1( void *pvParameters )
{
  const char *pcTaskName = "Task 1 is running\r\n";
  volatile unsigned long ul;
  /* 如果已经执行到本任务的代码,表明调度器已经启动。在进入死循环之前创建另一个任务。 */
  xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, NULL );
  for( ;; )
  {
    /* Print out the name of this task. */
    vPrintString( pcTaskName );
    /* Delay for a period. */
    for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
    {
      /* This loop is just a very crude delay implementation. There is
      nothing to do in here. Later examples will replace this crude
      loop with a proper delay/sleep function. */
    }
  }
}

 

3、用唯一一个任务函数代码(vTaskFunction),

这一个任务函数代替了上例中的两个任务函数(vTask1 与 vTask2)。

void vTaskFunction(void *pvParameters)
{
    int * pcTaskName;
    
    pcTaskName = (int *)pvParameters;
    
    
    while(1)
    {
        if(*pcTaskName==1)
        {
            LED1_ON;
            /* 阻塞延时,单位ms */        
            vTaskDelay( 500 );
            LED1_OFF;
            vTaskDelay( 500 );
        }
        else if(*pcTaskName==2)
        {
                BEEP_ON;
                /* 阻塞延时,单位ms */        
                vTaskDelay( 500 );
                BEEP_OFF;
                vTaskDelay( 500 );
        }
    }
    
}

创建任务函数修改为:

static void AppTaskCreate(void)
{
    xTaskCreate(vTaskFunction,                   /* 任务函数名 */
                 "Task 1",                   /* 任务名,字符串形式,方便调试 */
                 512,                          /* 栈大小,单位为字,即4个字节 */
                 (void *)&pcLED,                      /* 任务形参 */
                  1,                     /* 优先级,数值越大,优先级越高 */
                 &xHandleTaskLED1);     /* 任务句柄 */
    
    xTaskCreate(vTaskFunction,"Task 2", 512, (void *)&pcBeep, 1, &xHandleTaskBeep);
}

 注意任务参数处不再是NULL;

全局区增加标志定义:

static const int pcLED = 1;
static const int pcBeep = 2;
任务参数的原型:void * const pvParameters;如果我们不强制转化成void *将会报错。

 

 官方手册源码:

 

字符串常量是一个特殊的东西,把字符串常量通过函数

void vTaskFunction( void *pvParameters )

从入口参数void *pvParameters传入,再强转为字符指针。

 

图 3 中 t1 与 t2 之间的时段就等于一个时间片。

  

  要能够选择下一个运行的任务,调度器需要在每个时间片的结束时刻运行自己本身。一个称为心跳中断的周期性中断用于此目的。
 时间片的长度通过心跳中断的频率进行设定,心跳中断频率由FreeRTOSConfig.h 中的编译时配置常量 configTICK_RATE_HZ 进行配置。

  比如说,如果 configTICK_RATE_HZ 设为 100(HZ),则时间片长度为 10ms。可以将图 图 3 进行扩展,将调度器本身的执行时间在整个执行流程中体现出来。见图 4:

 

  FreeRTOS API 函数调用中指定的时间总是以心跳中断为单位(通常的提法为心跳”ticks”)。
  常量 portTICK_RATE_MS 用于将以心跳为单位的时间值转化为以毫秒为单位的时间值。
  有效精度依赖于系统心跳频率。

 

  

 

 



 

 



 

推荐阅读