FreeRTOS库函数 API Reference(一)任务创建

目录

任务创建(Task Creation)

1.xTaskCreate(创建一个新任务并将其添加到准备运行的任务列表中)

2.xTaskCreateStatic(创建一个新任务并将其添加到准备运行的任务列表中)

3.xTaskCreateRestrictedStatic(创建一个新的内存保护单元(MPU)限制任务,并将其添加到准备运行的任务列表中)

4.vTaskDelete(从RTOS内核管理中删除一个任务)


英文原文:

FreeRTOS - A FREE Open Source RTOS. The Free RTOS API functions for creating RTOS tasks and deleting RTOS tasks - xTaskCreate() and vTaskDelete.https://www.freertos.org/a00019.html

任务创建(Task Creation)

1.xTaskCreate(创建一个新任务并将其添加到准备运行的任务列表中)

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,或者未定义(在这种情况下它将默认为1),这样RTOS API函数才可用。

每个任务都需要RAM来保存任务状态,并被任务用作它的堆栈。如果一个任务是使用xTaskCreate()创建的,那么所需的RAM会自动从FreeRTOS堆分配。如果一个任务是使用xTaskCreateStatic()创建的,那么RAM是由应用程序编写器提供的,因此它可以在编译时静态分配。

如果正在使用FreeRTOS-MPU,那么建议使用xTaskCreateRestricted()而不是xTaskCreate()。

参数:

pvTaskCode  

指向任务入口函数的指针(只是实现任务的函数的名称,参见下面的示例)。

任务通常被实现为一个无限循环;实现该任务的函数绝对不能试图返回或退出。但是,任务可以删除自己。

pcName  

任务的文本名称。这主要用于方便调试,也可以用来获取任务句柄。

任务名的最大长度由FreeRTOSConfig.h中的configMAX_TASK_NAME_LEN定义。

usStackDepth

分配给任务的堆栈的字数(不是字节!)例如,如果堆栈是16位宽,而usStackDepth是100,那么将分配200字节作为任务的堆栈。另一个例子,如果堆栈是32位宽,而usStackDepth是400,那么将分配1600字节作为任务的堆栈。

usStackDepth 乘以 堆栈宽度 不得超过 size_t 类型变量所能包含的最大值。

 查看常见问题:堆栈应该有多大?

FreeRTOS创建任务的堆栈应该有多大?_QxNL的博客-CSDN博客

pvParameters

传递给任务函数的参数。

如果pvParameters被设置为一个变量的地址,那么当创建的任务执行时,这个变量必须仍然存在——所以传递堆栈变量的地址是无效的。

uxPriority

创建的任务执行的优先级。

支持MPU的系统可以通过在uxPriority中设置portPRIVILEGE_BIT位,以特权(系统)模式创建任务。例如,创建优先级为2的特权任务,设置uxPriority为(2 | portPRIVILEGE_BIT)。

优先级被限制小于configMAX_PRIORITIES。如果configASSERT未定义,则优先级被默认地限制为(configMAX_PRIORITIES - 1)。

pxCreatedTaskpxCreatedTask用于通过xTaskCreate()函数向创建的任务传递句柄。pxCreatedTask是可选的,可以设置为NULL。

返回值:

任务创建成功pdPASS
任务创建失败errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY

使用示例:


/* 需要创建的任务 */
void vTaskCode( void * pvParameters )
{
    /* 该参数值预期为1,因为在下面的xTaskCreate()调用中,在pvParameters值中传递了1。*/
    configASSERT( ( ( uint32_t ) pvParameters ) == 1 );

    for( ;; )
    {
        /* 任务代码 */
    }
}

/* 用于创建任务的函数 */
void vOtherFunction( void )
{
    BaseType_t xReturned;
    TaskHandle_t xHandle = NULL;

    /* 创建任务,存储句柄 */
    xReturned = xTaskCreate(
                    vTaskCode,       /* 实现该任务的函数. */
                    "NAME",          /* 任务的文本名称. */
                    STACK_SIZE,      /* 堆栈大小以字为单位,而不是字节 */
                    ( void * ) 1,    /* 传入任务的参数 */
                    tskIDLE_PRIORITY,/* 任务优先级 */
                    &xHandle );      /* 用于传递已创建任务的句柄 */

    if( xReturned == pdPASS )
    {
        /* 任务创建完成。使用任务句柄删除任务 */
        vTaskDelete( xHandle );
    }
}

2.xTaskCreateStatic(创建一个新任务并将其添加到准备运行的任务列表中)

 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必须在FreeRTOSConfig.h中设置为1才能使RTOS API函数可用。

每个任务都需要RAM来保存任务状态,并被任务用作它的堆栈。如果一个任务是使用xTaskCreate()创建的,那么所需的RAM会自动从FreeRTOS堆分配。如果一个任务是使用xTaskCreateStatic()创建的,那么RAM是由应用程序编写器提供的,这将导致更多的参数,但允许在编译时静态分配RAM。

如果使用FreeRTOS-MPU,那么建议使用xTaskCreateRestricted()而不是xTaskCreateStatic()。

 参数:

pvTaskCode  

指向任务入口函数的指针(只是实现任务的函数的名称,参见下面的示例)。

任务通常被实现为一个无限循环;实现该任务的函数绝对不能试图返回或退出。但是,任务可以删除自己。

pcName  

任务的文本名称。这主要用于方便调试,也可以用来获取任务句柄。

任务名的最大长度由FreeRTOSConfig.h中的configMAX_TASK_NAME_LEN定义。

usStackDepth

puxStackBuffer参数用于向xTaskCreateStatic()传递StackType_t变量数组。ulStackDepth必须设置为数组中的索引数。

 查看常见问题:堆栈应该有多大?

FreeRTOS创建任务的堆栈应该有多大?_QxNL的博客-CSDN博客

pvParameters

传递给任务函数的参数。

如果pvParameters被设置为一个变量的地址,那么当创建的任务执行时,这个变量必须仍然存在——所以传递堆栈变量的地址是无效的。

uxPriority

创建的任务执行的优先级。

支持MPU的系统可以通过在uxPriority中设置portPRIVILEGE_BIT位,以特权(系统)模式创建任务。例如,创建优先级为2的特权任务,设置uxPriority为(2 | portPRIVILEGE_BIT)。

优先级被限制小于configMAX_PRIORITIES。如果configASSERT未定义,则优先级被默认地限制为(configMAX_PRIORITIES - 1)。

puxStackBuffer必须指向至少有ulStackDepth索引的StackType_t数组(参见上面的ulStackDepth参数)-该数组将被用作任务的堆栈,因此它必须是持久的(不是在函数的堆栈上声明)。
pxTaskBuffer必须指向StaticTask_t类型的变量。该变量将用于保存新任务的数据结构(TCB),因此它必须是持久的(没有在函数的堆栈上声明)。

返回值:

如果puxStackBuffer和pxTaskBuffer都不为NULL,则创建任务,并返回任务句柄。
如果puxStackBuffer或pxTaskBuffer为NULL,则任务不会被创建,返回NULL。

使用示例:

    /* 正在创建的任务将用作其堆栈的缓冲区的空间。
    注意:这是堆栈将保存的单词数,而不是字节数。
    例如,如果每个堆栈项都是32位,并且设置为100,那么将分配400个字节(100 * 32位)。 */
    #define STACK_SIZE 200

    /* 结构,它将保存正在创建的任务的TCB */
    StaticTask_t xTaskBuffer;

    /* 正在创建的任务将使用缓冲区作为其堆栈。注意,这是一个StackType_t变量数组。StackType_t的大小与RTOS端口有关。 */
    StackType_t xStack[ STACK_SIZE ];

    /* 函数,该函数实现正在创建的任务。 */
    void vTaskCode( void * pvParameters )
    {
        /* 该参数值预期为1,因为1在调用xTaskCreateStatic()的pvParameters值中被传递。 */
        configASSERT( ( uint32_t ) pvParameters == 1UL );

        for( ;; )
        {
            /* 任务代码. */
        }
    }

    /* 函数,用于创建任务。 */
    void vOtherFunction( void )
    {
        TaskHandle_t xHandle = NULL;

        /* 创建任务时不使用任何动态内存分配 */
        xHandle = xTaskCreateStatic(
                      vTaskCode,       /* 实现该任务的函数 */
                      "NAME",          /* 任务的文本名称 */
                      STACK_SIZE,      /* xStack数组中的索引数 */
                      ( void * ) 1,    /* 传入任务的参数 */
                      tskIDLE_PRIORITY,/* 创建任务的优先级 */
                      xStack,          /* 数组用作任务的堆栈 */
                      &xTaskBuffer );  /* 变量来保存任务的数据结构 */

        /* puxStackBuffer和pxTaskBuffer不是NULL,所以任务已经创建,xHandle将是任务的句柄。使用句柄暂停任务。 */
        vTaskSuspend( xHandle );
    }

3.xTaskCreateRestrictedStatic(创建一个新的内存保护单元(MPU)限制任务,并将其添加到准备运行的任务列表中)

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

创建一个新的内存保护单元(MPU)限制任务,并将其添加到准备运行的任务列表中。configSUPPORT_STATIC_ALLOCATION必须在FreeRTOSConfig.h中设置为1才能使RTOS API函数可用。

在FreeRTOS实现的内部,每个任务需要两个内存块。第一个块用于保存任务的数据结构。第二个块用作任务的堆栈。如果一个任务是使用xTaskCreateRestricted()创建的,那么任务栈的内存由应用程序编写器提供,任务数据结构的内存自动从FreeRTOS堆分配。如果一个任务是使用xTaskCreateRestrictedStatic()创建的,那么应用程序编写器也必须为任务的数据结构提供内存。因此,xTaskCreateRestrictedStatic()允许创建内存保护任务,而无需使用任何动态内存分配。

参数:

pxTaskDefinition 指向定义任务的TaskParameters_t结构体的指针。该结构将在下文中描述。
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;

其中MemoryRegion_t定义为:

typedef struct xMEMORY_REGION
{
    void *pvBaseAddress;
    unsigned long ulLengthInBytes;
    unsigned long ulParameters;
} MemoryRegion_t;

下面是每个结构成员的描述:

从 pvTaskCode 到 uxPriority

这些成员与发送给xTaskCreate()的同名参数完全相同。

具体来说,uxPriority用于设置任务的优先级和任务执行的模式。例如,创建优先级为2的User模式任务,只需将uxPriority设置为2,创建优先级为2的privilege模式任务,将uxPriority设置为(2 | portPRIVILEGE_BIT)。

puxStackBuffer

每次任务切换时,主控板都会动态地重新配置,定义一个区域,为任务提供对自己栈的读写权限。MPU区域必须满足许多约束条件——特别是,所有这些区域的大小和对齐必须等于相同的2次方值。

标准的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。

pvBaseAddressulLengthInBytes成员分别作为内存区域的开始和内存区域的长度是自解释的。

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类型的变量。变量将用于保存新任务的数据结构,因此它必须是持久的(没有在函数的堆栈上声明)。

使用示例:

/* 创建一个TaskParameters_t结构,它定义要创建的任务。
 * 只有当configSUPPORT_STATIC_ALLOCATION设置为1时,StaticTask_t变量才包含在结构中。
   PRIVILEGED_DATA宏可用于将变量强制放入RTOS内核的特权数据区域。*/
static PRIVILEGED_DATA StaticTask_t xTaskBuffer;
static const TaskParameters_t xCheckTaskParameters =
{
  vATask,     /* pvTaskCode -实现任务的函数 */
  "ATask",    /* pcName - 只是用于协助调试的任务的文本名称 */
  100,        /* usStackDepth - 用WORDS定义的堆栈大小 */
  NULL,       /* pvParameters - 作为函数参数传入任务函数 */
  ( 1UL | portPRIVILEGE_BIT ),/* uxPriority - 任务优先级,如果任务应该运行在特权状态,设置portPRIVILEGE_BIT */
  cStackBuffer,/* puxStackBuffer - 用作任务栈的缓冲区 */

  /* xRegions - 分配最多三个独立的内存区域供任务访问,并具有适当的访问权限。
     不同的处理器有不同的内存对齐要求-参考FreeRTOS文档获得完整信息。 */
  {
      /* Base address                 Length  Parameters */
      { cReadWriteArray,              32,     portMPU_REGION_READ_WRITE },
      { cReadOnlyArray,               32,     portMPU_REGION_READ_ONLY },
      { cPrivilegedOnlyAccessArray,   128,    portMPU_REGION_PRIVILEGED_READ_WRITE }
  }

  &xTaskBuffer; /* 保存任务的数据结构 */
 };

 int main( void )
 {
  TaskHandle_t xHandle;

  /* 使用上面定义的const结构创建任务。任务句柄被请求(第二个参数不是NULL),
     但在本例中只是出于演示目的,因为实际上并没有使用它。 */
  xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );

  /* 开始调度器 */
  vTaskStartScheduler();

  /* 只有在没有足够的内存来创建空闲任务 and/or 计时器任务时才会到达这里。 */
  for( ;; );
 }

4.vTaskDelete(从RTOS内核管理中删除一个任务)

void vTaskDelete( TaskHandle_t xTask );

INCLUDE_vTaskDelete必须定义为1才能使用该函数。

从RTOS内核管理中删除一个任务。被删除的任务将从所有就绪、阻塞、挂起和事件列表中删除。

注意:空闲任务负责从被删除的任务中释放RTOS内核分配的内存。因此,如果应用程序调用vTaskDelete(),空闲任务不缺乏微控制器处理时间是很重要的。由任务代码分配的内存不会自动释放,应该在删除任务之前释放。

参数:

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 );
     }
 }

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

QxNL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值