Chinaunix首页 | 论坛 | 博客
  • 博客访问: 810448
  • 博文数量: 281
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2770
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-02 19:45
个人简介

邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛

文章分类
文章存档

2020年(1)

2018年(1)

2017年(56)

2016年(72)

2015年(151)

分类: 嵌入式

2015-09-17 10:56:12

目的:
主要讲在freertos中,如何管理任务:这就包括如何创建任务,删除任务,改变任务的优先级等等。




一些概念:
软实时: 对每个输入的响应应当限定在一个恰当的时间范围内,但是如果响应时间超出了限定范围,也能接受。
硬实时: 响应必须在给定的时间内完成,如果无法做到,可能引起灾难性的后果。
大多数嵌入式系统都能完成软实时和硬实时的要求。

术语:
在freertos中,每个执行线程都被称作为“任务”。




任务函数:
  1. 任务是由C语言函数实现的,该函数原型必须返回void,而且带有一个void指针的参数;
  2. 每个任务都是在自己权限里的一个小程序,具有程序入口,通常运行在一个死循环里,也不会退出。
  3. 如果一个任务不再需要,可以显示地将其删除;
  4. 一个任务可以用来创建若各个任务,创建出的任务均是独立的执行实体,拥有自己的栈空间,以及属于自己的自动变量(栈变量),及任务函数本身定义的变量。
void ATaskFunction(void *pvParameters);



想一个问题,下面这个让LED闪烁的任务,state如何定义呢?
是定义成:
u8 state = 0;
还是:
static u8 state = 0;
void redLed_Task(void *pvParameters)
{
    u8 state = 0;
    pvParameters = pvParameters;
    
    while(1)
    {
        //(state = !state) == 1 ? RED_ON(): RED_OFF();
        state ++;
        if(state == 1)      RED_ON();
        else if(state == 2) RED_OFF();
        else if(state == 3) RED_ON();       
        else if(state == 4) {RED_OFF(); state = 0;}
 
        vTaskDelay(1000/portTICK_RATE_MS);        // ???±?à?????????è??  ???±500??????
    }
}
这跟以前我们写法,还是不同的,想想为什么可以定义成: u8 state =0 ???

任务状态:
应用程序可以包含多个任务。如果运行应用程序的微控制器只有一个核(core),那么在任意给定时间,实际上只会有一个任务被执行。这就意味着一个任务可以有一个或
两个状态,即运行状态和非运行状态。我们先考虑这种最简单的模型——但请牢记这其实是过于简单,我们稍后将会看到非运行状态实际上又可划分为若干个子状态。
当某个任务处于运行态时,处理器就正在执行它的代码。当一个任务处于非运行态时,该任务进行休眠,它的所有状态都被妥善保存,以便在下一次调试器决定让它进入
运行态时可以恢复执行。当任务恢复执行时,其将精确地从离开运行态时正准备执行的那一条指令开始执行。



创建任务:
是一个宏定义:
#define xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask )
    xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ) )


点击(此处)折叠或打开

  1. /*-----------------------------------------------------------
  2.  * TASK CREATION API
  3.  *----------------------------------------------------------*/

  4. /**
  5.  * task. h
  6.  *<pre>
  7.  BaseType_t xTaskCreate(
  8.                              TaskFunction_t pvTaskCode,
  9.                              const char * const pcName,
  10.                              uint16_t usStackDepth,
  11.                              void *pvParameters,
  12.                              UBaseType_t uxPriority,
  13.                              TaskHandle_t *pvCreatedTask
  14.                          );</pre>
  15.  *
  16.  * Create a new task and add it to the list of tasks that are ready to run.
  17.  *
  18.  * xTaskCreate() can only be used to create a task that has unrestricted
  19.  * access to the entire microcontroller memory map. Systems that include MPU
  20.  * support can alternatively create an MPU constrained task using
  21.  * xTaskCreateRestricted().
  22.  *
  23. 第一个参数: pvTaskCode 是指向任务函数的指针
  24.  * @param pvTaskCode Pointer to the task entry function. Tasks
  25.  * must be implemented to never return (i.e. continuous loop).
  26.  *
  27. 第二个参数: 是具有描述性的函数名字
  28.  * @param pcName A descriptive name for the task. This is mainly used to
  29.  * facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN - default
  30.  * is 16.
  31.  *
  32. 第三个参数: 用于分配任务堆栈大小。注意: 这里不是指字节数,而是跟处理器的位宽相关。
  33.  * @param usStackDepth The size of the task stack specified as the number of
  34.  * variables the stack can hold - not the number of bytes. For example, if
  35.  * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes
  36.  * will be allocated for stack storage.
  37.  *
  38. 第四个参数: 传递到任务中的参数
  39.  * @param pvParameters Pointer that will be used as the parameter for the task
  40.  * being created.
  41.  *
  42. 第五个参数: 任务的优先级。最低优先级从0开始,优先级没有上限。
  43.  * @param uxPriority The priority at which the task should run. Systems that
  44.  * include MPU support can optionally create tasks in a privileged (system)
  45.  * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For
  46.  * example, to create a privileged task at priority 2 the uxPriority parameter
  47.  * should be set to ( 2 | portPRIVILEGE_BIT ).
  48.  *
  49. 第六个参数: 用于传出任务的句柄。
  50.  * @param pvCreatedTask Used to pass back a handle by which the created task
  51.  * can be referenced.
  52.  *
  53. 返回参数: 如果返回pdPASS,则创建成功。
  54.  * @return pdPASS if the task was successfully created and added to a ready
  55.  * list, otherwise an error code defined in the file projdefs.h
  56.  *
  57.  * Example usage:
  58.    <pre>
  59.  // Task to be created.
  60.  void vTaskCode( void * pvParameters )
  61.  {
  62.      for( ;; )
  63.      {
  64.          // Task code goes here.
  65.      }
  66.  }

  67.  // Function that creates a task.
  68.  void vOtherFunction( void )
  69.  {
  70.  static uint8_t ucParameterToPass;
  71.  TaskHandle_t xHandle = NULL;

  72.      // Create the task, storing the handle. Note that the passed parameter ucParameterToPass
  73.      // must exist for the lifetime of the task, so in this case is declared static. If it was just an
  74.      // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
  75.      // the new task attempts to access it.
  76.      xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
  77.      configASSERT( xHandle );

  78.      // Use the handle to delete the task.
  79.      if( xHandle != NULL )
  80.      {
  81.      vTaskDelete( xHandle );
  82.      }
  83.  }
  84.    </pre>
  85.  * \defgroup xTaskCreate xTaskCreate
  86.  * \ingroup Tasks
  87.  */

例子1:
建立两个任务,只是周期性的打印字符串到串口,指定了相同的优先级。

main.c函数:

点击(此处)折叠或打开

  1. #include "led.h"
  2. #include "delay.h"
  3. #include "sys.h"
  4. #include "usart.h"

  5. // FreeRTOS head file, add here.
  6. #include "FreeRTOS.h"
  7. #include "task.h"
  8. #include "queue.h"
  9. #include "list.h"
  10. #include "portable.h"
  11. #include "FreeRTOSConfig.h"


  12. void task1(void *pvParameters)
  13. {
  14.     u8 state = 0;
  15.     
  16.     while(1)
  17.     {
  18.         printf("task 1 is running \r\n");
  19.         
  20.         (state = !state) == 1 ? RED_ON(): RED_OFF();
  21.         vTaskDelay(1000/portTICK_RATE_MS);
  22.     }
  23. }


  24. void task2(void *pvParameters)
  25. {
  26.     u8 state1 = 0;
  27.     
  28.     while(1)
  29.     {
  30.         printf("task 2 is running \r\n");
  31.         
  32.         (state1 = !state1) == 1 ? GREEN_ON() : GREEN_OFF();
  33.         vTaskDelay(1000/portTICK_RATE_MS);
  34.     }
  35. }



  36. int main(void)
  37. {
  38.     // board initialize.
  39.     LED_Init();             
  40.     uart_init(115200);
  41.     
  42.     //create two tasks, with the same priority.
  43.     // 优先级一样
  44.     xTaskCreate( task2, "task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
  45.     xTaskCreate( task1, "task2", configMINIMAL_STACK_SIZE, NULL, 1, NULL );
  46.     
  47.     // start scheduler now
  48.     vTaskStartScheduler();

  49.     return 0;
  50. }

打印输出信息:


可见,task1和task2轮流运行,打印字符串。


在main函数中,创建了两个任务,当然也可以从一个任务中创建另一个任务。

点击(此处)折叠或打开

  1. #include "led.h"
  2. #include "delay.h"
  3. #include "sys.h"
  4. #include "usart.h"

  5. // FreeRTOS head file, add here.
  6. #include "FreeRTOS.h"
  7. #include "task.h"
  8. #include "queue.h"
  9. #include "list.h"
  10. #include "portable.h"
  11. #include "FreeRTOSConfig.h"



  12. void task2(void *pvParameters)
  13. {
  14.     u8 state1 = 0;
  15.     
  16.     while(1)
  17.     {
  18.         printf("task 2 is running \r\n");
  19.         
  20.         (state1 = !state1) == 1 ? GREEN_ON() : GREEN_OFF();
  21.         vTaskDelay(1000/portTICK_RATE_MS);
  22.     }
  23. }


  24. void task1(void *pvParameters)
  25. {
  26.     u8 state = 0;
  27.    
  28.     // 在任务中创建另一个任务
  29.    xTaskCreate( task2, "task2", configMINIMAL_STACK_SIZE, NULL, 1, NULL );
  30.    
  31.     while(1)
  32.     {
  33.         printf("task 1 is running \r\n");
  34.         
  35.         (state = !state) == 1 ? RED_ON(): RED_OFF();
  36.         vTaskDelay(1000/portTICK_RATE_MS);
  37.     }
  38. }


  39. int main(void)
  40. {
  41.     // board initialize.
  42.     LED_Init();             
  43.     uart_init(115200);
  44.     
  45.     //create two tasks, with the same priority.
  46.     xTaskCreate( task1, "task2", configMINIMAL_STACK_SIZE, NULL, 1, NULL );
  47.     
  48.     // start scheduler now
  49.     vTaskStartScheduler();

  50.     return 0;
  51. }

例子2:
例1 中创建的两个任务几乎完全相同,唯一的区别就是打印输出的字符串。这种重复性可以通过创建同一个任务代码的两个实体来去除。这时任务参数就可以用来传递各自打印输出的字符串。

见main.c

点击(此处)折叠或打开

  1. #include "led.h"
  2. #include "delay.h"
  3. #include "sys.h"
  4. #include "usart.h"

  5. // FreeRTOS head file, add here.
  6. #include "FreeRTOS.h"
  7. #include "task.h"
  8. #include "queue.h"
  9. #include "list.h"
  10. #include "portable.h"
  11. #include "FreeRTOSConfig.h"


  12. void vTaskFunction(void *pvParameters)
  13. {
  14.     char *taskName;

  15.     // 接收创建任务时候传递过来的参数
  16.     taskName = (char *)pvParameters;
  17.     
  18.     while(1)
  19.     {
  20.         printf(taskName);
  21.         vTaskDelay(1000/portTICK_RATE_MS);
  22.     }
  23. }


  24. static const char * task1 = "task 1 is running \r\n";
  25. static const char * task2 = "task 2 is running \r\n";

  26. int main(void)
  27. {
  28.     // board initialize.
  29.     LED_Init();             
  30.     uart_init(115200);
  31.     
  32.     //create two tasks, with the same priority.

  33.     // 将参数传递给任务实体
  34.     xTaskCreate( vTaskFunction, "task1", configMINIMAL_STACK_SIZE, (void *)task1, 1, NULL);
  35.     xTaskCreate( vTaskFunction, "task2", configMINIMAL_STACK_SIZE, (void *)task2, 1, NULL );
  36.     
  37.     // start scheduler now
  38.     vTaskStartScheduler();

  39.     return 0;
  40. }












阅读(1428) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~