【FreeRTOS】FreeRTOS 中关于任务创建 osThreadNew() 函数详解

1. 引言

转载至 知乎博主:cp404 —— FreeRTOS中关于任务创建osThreadNew()函数详解

2. 正文

在开始讲osThreadNew()这个函数之前,我们先需要了解xTaskCreate()和xTaskCreateStatic()这两个更加基本的任务创建函数。

xTaskCreate();//位置task.c
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
	BaseType_t xTaskCreate(	TaskFunction_t pxTaskCode,
	const char * const pcName,	/*lint !e971 Unqualified char types are allowed for strings and single characters only. */
	const configSTACK_DEPTH_TYPE usStackDepth,
	void * const pvParameters,
	UBaseType_t uxPriority,
	TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
#endif

· pvTaskCode 这是一个函数指针,指向执行任务的函数。

· pcName 任务的描述名称,方便调试,不用的话可以设为Null。

· usStackDepth 每个任务有自己的栈空间,这里根据任务占用需求设置栈空间的大小。

· pvParameters 用于传递给任务的参数,不用的话可以设为Null。

· uxPriority 设置任务的优先级,范围由0到(configMAX_PRIORITIES – 1)。数值越大,等级越高。

· pxCreatedTask 任务的句柄(handle),通过句柄可以对任务进行设置,比如改变任务优先级等,不用可以设为Null。(关于句柄的解析可以看这个 https://www.cnblogs.com/zpcdbky/p/4652151.html )

函数的返回值有两个pdPass和pdFail,pdPass表示任务创建成功,相反pdFail表示创建失败,创建失败的原因大多是因为系统没有足够的堆空间来保存任务的数据。

xTaskCreateStatic();//位置tasks.c
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
	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 ) PRIVILEGED_FUNCTION;
#endif

xTaskCreate()与 xTaskCreateStatic()的区别:
xTaskCreate是操作系统自动分配内存,xTaskCreateStatic是需要程序员手动定义内存。

· xTaskCreate适用于项目开发中内存余量比较充足的项目,只是简单的分配大小就可以了;

· xTaskCreateStatic适用于项目开发中内存比较紧张的项目,事先定义好内存大小并占用内存空间,这样在系统编译的时候就可以确定总内存大小,也不会出现系统运行到当前任务时内存不足而出现崩溃的情况。

· 使用动态方法创建任务(xTaskCreate)的时候需要将宏 configSUPPORT_DYNAMIC_ALLOCATION 设置为 1

· 使用静态方法创建任务(xTaskCreateStatic)的时候需要将宏 configSUPPORT_STATIC_ALLOCATION 设为1

宏定义位置Core/Inc/ FreeRTOSConfig.h

osThreadNew();//函数位置CMSIS_RTOS_V2/cmsis_os2.c
osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr) {
  const char *name;
  uint32_t stack;
  TaskHandle_t hTask;
  UBaseType_t prio;
  int32_t mem;

  hTask = NULL;

  if (!IS_IRQ() && (func != NULL)) {
    stack = configMINIMAL_STACK_SIZE;
    prio  = (UBaseType_t)osPriorityNormal;

    name = NULL;
    mem  = -1;

    if (attr != NULL) {
      if (attr->name != NULL) {
        name = attr->name;
      }
      if (attr->priority != osPriorityNone) {
        prio = (UBaseType_t)attr->priority;
      }

      if ((prio < osPriorityIdle) || (prio > osPriorityISR) || ((attr->attr_bits & osThreadJoinable) == osThreadJoinable)) {
        return (NULL);
      }

      if (attr->stack_size > 0U) {
        /* In FreeRTOS stack is not in bytes, but in sizeof(StackType_t) which is 4 on ARM ports.       */
        /* Stack size should be therefore 4 byte aligned in order to avoid division caused side effects */
        stack = attr->stack_size / sizeof(StackType_t);
      }

      if ((attr->cb_mem    != NULL) && (attr->cb_size    >= sizeof(StaticTask_t)) &&
          (attr->stack_mem != NULL) && (attr->stack_size >  0U)) {
        mem = 1;
      }
      else {
        if ((attr->cb_mem == NULL) && (attr->cb_size == 0U) && (attr->stack_mem == NULL)) {
          mem = 0;
        }
      }
    }
    else {
      mem = 0;
    }

    if (mem == 1) {
      hTask = xTaskCreateStatic ((TaskFunction_t)func, name, stack, argument, prio, (StackType_t  *)attr->stack_mem,
                                                                                    (StaticTask_t *)attr->cb_mem);
    }
    else {
      if (mem == 0) {
        if (xTaskCreate ((TaskFunction_t)func, name, (uint16_t)stack, argument, prio, &hTask) != pdPASS) {
          hTask = NULL;
        }
      }
    }
  }

  return ((osThreadId_t)hTask);
}

事实上,在STM32CubeIDE中的CMSIS RTOS的API函数中,负责创建任务的函数是osThreadNew()这个函数,其封装了FreeRTOS中的xTaskCreate()和xTaskCreateStatic()

osThreadNew()的三个入口参数func, argument, attr:
image
osThreadNew()的三个入口参数

· func为xTaskCreate()和xTaskCreateStatic()中的第一个入口参数,是一个函数指针,指向执行任务的函数。

· argument为xTaskCreate()和xTaskCreateStatic()中的第四个入口参数,是传递给任务的参数,不用时设为NULL。

· attr 是个Handle句柄,包含了.name,.stack_size,.priority等属性,分别覆盖了xTaskCreate()和xTaskCreateStatic()中的第二、三、五个入口参数

image
osThreadNew()函数调用xTaskCreate()和xTaskCreateStatic()

至此,osThreadNew()中的三个入口参数包含了基本任务创建函数中的前六个入口参数。对于第七个入口参数,我们注意到xTaskCreate()函数和xTaskCreateStatic()函数的不同。事实上osThreadNew()选择调用xTaskCreate()还是xTaskCreateStatic(),与mem这个参数有关。

image

当你在attr这个结构体中设定了栈区的大小,mem就会被设为1,进而osThreadNew()选择调用xTaskCreateStatic(),反之mem设为0,调用xTaskCreate ()。

博客导航

博客导航

posted @ 2026-09-02 08:28  膝盖中箭卫兵  阅读(9)  评论(0)    收藏  举报
ORCID iD icon https://orcid.org/0000-0001-5102-772X