13-FreeRTOS任务创建与删除

任务创建和删除API函数位于文件task.c中,需要包含task.h头文件。
task.h里面包函数任务的类型函数。例如,对xTaskCreate的调用(通过指针方式)返回一个TaskHandle_t 变量,然后可将该变量用vTaskDelete来进行任务的删除工作。

1- 任务创建

 BaseType_t xTaskCreate(    TaskFunction_t pvTaskCode,
                            const char * const pcName,
                            configSTACK_DEPTH_TYPE usStackDepth,
                            void *pvParameters,
                            UBaseType_t uxPriority,
                            TaskHandle_t *pxCreatedTask
                          );

创建新的任务并加入任务就绪列表之中。
configSUPPORT_DYNAMIC_ALLOCATION在 FreeRTOSConfig.h文件中必须设置为1,只有这样才能访问API函数。
每个任务都需要用于保存任务状态的RAM,并被任务用作其堆栈。如果使用xTaskCreate()创建任务,则从FreeRTOS堆中自动分配所需的RAM。如果使用xTaskCreateStatic()创建任务,则RAM由应用程序编写器提供,因此可以在编译时静态分配。
如果你使用的是 FreeRTOS-MPU,官方建议是使用 xTaskCreateRestricted这个API,而不是xTaskCreateStatic()API函数。

1.1 xTaskCreate参数描述

  • pvTaskCode:指针,指向任务函数的入口,任务永远是无限循环实现,但是不会返回或者退出。但任务可以自行删除。
  • pcName :任务描述,主要用于调试。字符串的最大长度由宏configMAX_TASK_NAME_LEN指定,该宏位于FreeRTOSConfig.h文件中。
  • usStackDepth:指定任务堆栈大小。分配用作任务堆栈的字数(不是字节!)例如,如果堆栈是16位宽,usStackDepth是100,那么将分配200字节作为任务的堆栈。另一个例子,如果堆栈是32位宽,usStackDepth是400,那么将分配1600字节作为任务的堆栈。
    堆栈的宽度乘以深度必须不超过size_t类型所能表示的最大值。比如,size_t为16位,则可以表示的最大值是65535。
  • pvParameters:指针,任务创建时,作为一个参数传递给任务。
  • uxPriority :创建的任务执行的优先级。包含MPU支持的系统可以通过在uxPriority中设置位portPRIVILEGE_BIT来选择以特权(系统)模式创建任务。例如,要创建优先级为2的特权任务,将uxPriority设置为(2 | portPRIVILEGE_BIT)。
    优先级被设定为小于configMAX_PRIORITIES。如果configASSERT未定义,优先级将静默地限制在(configMAX_PRIORITIES - 1)。
  • pxCreatedTask:用于通过xTaskCreate()函数将句柄传递给创建的任务。pxCreatedTask是可选的,可以设置为NULL。
  • 返回:如果任务创建成功,则返回pdPASS。否则返回errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY。
  • 用例:
/* Task to be created. */
void vTaskCode( void * pvParameters )
{
    /* The parameter value is expected to be 1 as 1 is passed in the
    pvParameters value in the call to xTaskCreate() below. 
    configASSERT( ( ( uint32_t ) pvParameters ) == 1 );

    for( ;; )
    {
        /* Task code goes here. */
    }
}

/* Function that creates a task. */
void vOtherFunction( void )
{
BaseType_t xReturned;
TaskHandle_t xHandle = NULL;

    /* Create the task, storing the handle. */
    xReturned = xTaskCreate(
                    vTaskCode,       /* Function that implements the task. */
                    "NAME",          /* Text name for the task. */
                    STACK_SIZE,      /* Stack size in words, not bytes. */
                    ( void * ) 1,    /* Parameter passed into the task. */
                    tskIDLE_PRIORITY,/* Priority at which the task is created. */
                    &xHandle );      /* Used to pass out the created task's handle. */

    if( xReturned == pdPASS )
    {
        /* The task was created.  Use the task's handle to delete the task. */
        vTaskDelete( xHandle );
    }
}

2- 静态任务创建

task. h
 TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
                                 const char * const pcName,
                                 const uint32_t ulStackDepth,
                                 void * const pvParameters,
                                 UBaseType_t uxPriority,
                                 StackType_t * const puxStackBuffer,
                                 StaticTask_t * const pxTaskBuffer );

创建新任务并将其添加到准备运行的任务列表中。configSUPPORT_STATIC_ALLOCATION必须设置为 1。这时候API函数才可以调用。

参数描述:

pxTaskCode:参考1
pcName:参考1
ulStackDepth:参考1
pvParameters:参考1
uxPriority:参考1
puxStackBuffer:必须指向一个至少具有ulStackDepth索引的StackType_t数组(参见上面的ulStackDepth参数)-该数组将被用作任务的堆栈,因此它必须是持久的(没有在函数的堆栈上声明)。
pxTaskBuffer:必须指向StaticTask_t类型的变量。该变量将用于保存新任务的数据结构(TCB),因此它必须是持久的(没有在函数的堆栈上声明)。
返回:如果puxStackBuffer和pxTaskBuffer都不是NULL,那么将创建任务,并返回任务句柄。如果puxStackBuffer或pxTaskBuffer中有一个是NULL,那么任务将不会被创建,并返回NULL。
用例

 /* Dimensions of the buffer that the task being created will use as its stack.
    NOTE:  This is the number of words the stack will hold, not the number of
    bytes.  For example, if each stack item is 32-bits, and this is set to 100,
    then 400 bytes (100 * 32-bits) will be allocated. */
    #define STACK_SIZE 200

    /* Structure that will hold the TCB of the task being created. */
    StaticTask_t xTaskBuffer;

    /* Buffer that the task being created will use as its stack.  Note this is
    an array of StackType_t variables.  The size of StackType_t is dependent on
    the RTOS port. */
    StackType_t xStack[ STACK_SIZE ];

    /* Function that implements the task being created. */
    void vTaskCode( void * pvParameters )
    {
        /* The parameter value is expected to be 1 as 1 is passed in the
        pvParameters value in the call to xTaskCreateStatic(). */
        configASSERT( ( uint32_t ) pvParameters == 1UL );

        for( ;; )
        {
            /* Task code goes here. */
        }
    }

    /* Function that creates a task. */
    void vOtherFunction( void )
    {
        TaskHandle_t xHandle = NULL;

        /* Create the task without using any dynamic memory allocation. */
        xHandle = xTaskCreateStatic(
                      vTaskCode,       /* Function that implements the task. */
                      "NAME",          /* Text name for the task. */
                      STACK_SIZE,      /* Number of indexes in the xStack array. */
                      ( void * ) 1,    /* Parameter passed into the task. */
                      tskIDLE_PRIORITY,/* Priority at which the task is created. */
                      xStack,          /* Array to use as the task's stack. */
                      &xTaskBuffer );  /* Variable to hold the task's data structure. */

        /* puxStackBuffer and pxTaskBuffer were not NULL, so the task will have
        been created, and xHandle will be the task's handle.  Use the handle
        to suspend the task. */
        vTaskSuspend( xHandle );
    }

3-xTaskCreateRestrictedStatic

BaseType_t xTaskCreateRestrictedStatic( TaskParameters_t *pxTaskDefinition,
                                        TaskHandle_t *pxCreatedTask );

创建一个新的内存保护单元(MPU)受限任务,并将其添加到准备运行的任务列表。必须在FreeRTOSConfig.h中将configSUPPORT_STATIC_ALLOCATION设置为1,才能使这个RTOS API函数可用。
在FreeRTOS内部,每个任务都需要两块内存。第一个块用于保存任务的数据结构。第二个块用作任务的堆栈。如果使用xTaskCreateRestricted()创建任务,那么任务堆栈的内存由应用程序编写者提供,任务数据结构的内存从FreeRTOS堆中自动分配。如果使用xTaskCreateRestrictedStatic()创建任务,那么应用程序编写者也必须为任务的数据结构提供内存。因此,xTaskCreateRestrictedStatic()允许在不使用任何动态内存分配的情况下创建内存保护任务。

3.1 参数

pxTaskDefinition :指向定义任务的结构的指针
pxCreatedTask:用于传回可引用所创建任务的句柄。
返回: 如果任务成功创建并添加到就绪列表,则为pdPASS,否则为projdefs.h文件中定义的错误代码。
包含MPU支持的任务比不包含MPU支持的任务需要创建更多的参数。将每个参数单独传递给xTaskCreateRestrictedStatic()会很麻烦,因此使用结构TaskParameters_t来允许在编译时静态地配置参数。结构在task.h中定义为:

typedef struct xTASK_PARAMETERS
{
    TaskFunction_t pvTaskCode;
    const signed char * const pcName;
    unsigned short usStackDepth;
    void *pvParameters;
    UBaseType_t uxPriority;
    portSTACK_TYPE *puxStackBuffer;
    MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ];
    #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
        StaticTask_t * const pxTaskBuffer;
    #endif
} TaskParameters_t;
....where MemoryRegion_t is defined as:
typedef struct xMEMORY_REGION
{
    void *pvBaseAddress;
    unsigned long ulLengthInBytes;
    unsigned long ulParameters;
} MemoryRegion_t;

下面是上面这个结构体的说明:

  • pvTaskCode to uxPriority
    这些成员与发送给xTaskCreate()的同名参数完全相同。特别是,uxPriority用于设置任务的优先级和任务执行的模式。例如,要创建优先级为2的用户模式任务,只需将uxPriority设置为2,要创建优先级为2的特权模式任务,则将uxPriority设置为(2 | portPRIVILEGE_BIT)。
  • puxStackBuffer
    每次一个任务被切换时,MPU都会动态地重新配置,定义一个区域,为任务提供对自己堆栈的读写访问。MPU区域必须满足一些约束条件——特别是,所有这些区域的大小和对齐必须等于两个值的相同幂。标准FreeRTOS端口在每次创建任务时使用pvPortMalloc()分配一个新的堆栈。提供一个pvPortMalloc()实现来处理MPU数据对齐需求是可能的,但在RAM使用方面也会比较复杂和低效。为了消除这种复杂性,FreeRTOS-MPU允许在编译时静态地声明堆栈。这允许使用编译器扩展来管理对齐,并由链接器管理RAM使用效率。例如,如果使用GCC,可以使用以下代码声明并正确对齐堆栈:
char cTaskStack[ 1024 ] __attribute__((aligned(1024));

puxStackBuffer通常被设置为静态声明的堆栈的地址。作为替代,puxStackBuffer可以设置为NULL——在这种情况下,pvportmallocalsigned()将被调用来分配任务堆栈,应用程序编写人员有责任提供pvportmallocalsigned()的实现,以满足MPU的对齐要求。

  • xRegions
    xRegions是一个MemoryRegion_t结构数组,每个结构都定义了一个用户可定义的内存区域,供正在创建的任务使用。ARM Cortex-M3 FreeRTOS-MPU端口定义portNUM_CONFIGURABLE_REGIONS为3。pvBaseAddress和ulLengthInBytes成员是不言自明的,分别作为内存区域的开始和内存区域的长度。ulParameters定义了如何允许任务访问内存区域,并且可以取以下值的位或:
   portMPU_REGION_READ_WRITE
    portMPU_REGION_PRIVILEGED_READ_ONLY
    portMPU_REGION_READ_ONLY
    portMPU_REGION_PRIVILEGED_READ_WRITE
    portMPU_REGION_CACHEABLE_BUFFERABLE
    portMPU_REGION_EXECUTE_NEVER
  • pxTaskBuffer
    必须指向StaticTask_t类型的变量。变量将用于保存新任务的数据结构,因此它必须是持久的(没有在函数的堆栈上声明)。
    用例
/* Create an TaskParameters_t structure that defines the task to be created.
 * The StaticTask_t variable is only included in the structure when
 * configSUPPORT_STATIC_ALLOCATION is set to 1.  The PRIVILEGED_DATA macro can
 * be used to force the variable into the RTOS kernel's privileged data area. */
static PRIVILEGED_DATA StaticTask_t xTaskBuffer;
static const TaskParameters_t xCheckTaskParameters =
{
  vATask,     /* pvTaskCode - the function that implements the task. */
  "ATask",    /* pcName - just a text name for the task to assist debugging. */
  100,        /* usStackDepth - the stack size DEFINED IN WORDS. */
  NULL,       /* pvParameters - passed into the task function as the function parameters. */
  ( 1UL | portPRIVILEGE_BIT ),/* uxPriority - task priority, set the portPRIVILEGE_BIT 
                                   if the task should run in a privileged state. */
  cStackBuffer,/* puxStackBuffer - the buffer to be used as the task stack. */

  /* xRegions - Allocate up to three separate memory regions for access by
   * the task, with appropriate access permissions.  Different processors have
   * different memory alignment requirements - refer to the FreeRTOS documentation
   * for full information. */
  {
      /* Base address                 Length  Parameters */
      { cReadWriteArray,              32,     portMPU_REGION_READ_WRITE },
      { cReadOnlyArray,               32,     portMPU_REGION_READ_ONLY },
      { cPrivilegedOnlyAccessArray,   128,    portMPU_REGION_PRIVILEGED_READ_WRITE }
  }

  &xTaskBuffer; /* Holds the task's data structure. */
 };

 int main( void )
 {
 TaskHandle_t xHandle;

  /* Create a task from the const structure defined above.  The task handle
   * is requested (the second parameter is not NULL) but in this case just for
   * demonstration purposes as its not actually used. */
  xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );

  /* Start the scheduler. */
  vTaskStartScheduler();

  /* Will only get here if there was insufficient memory to create the idle
   * and/or timer task. */
  for( ;; );
 }

4-任务删除

void vTaskDelete( TaskHandle_t xTask );

INCLUDE_vTaskDelete必须定义为1才能使该函数可用。
从RTOS内核管理中移除一个任务。被删除的任务将从所有就绪、阻塞、挂起和事件列表中删除。
注意:空闲任务负责从已删除的任务中释放RTOS内核分配的内存。因此,如果应用程序调用vTaskDelete(),空闲任务不缺少微控制器处理时间是很重要的。任务代码分配的内存不会自动释放,应该在删除任务之前释放。

4.1 参数描述

xTask要删除的任务句柄。传递NULL将导致调用任务被删除。
用例:

 void vOtherFunction( void )
 {
 TaskHandle_t xHandle = NULL;

     // Create the task, storing the handle.
     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

     // Use the handle to delete the task.
     if( xHandle != NULL )
     {
         vTaskDelete( xHandle );
     }
 } 

你可能感兴趣的:(FreeRTOS基础知识篇,FreeRTOS,RTOS,stm32)