FreeRTOS 提供了两种创建任务的方式:动态创建和静态创建。这两种方式的主要区别在于内存分配的时机和灵活性。
动态创建任务
动态创建任务时,FreeRTOS 会在堆中为任务栈和控制块分配内存。这种方式更为灵活,但需要确保有足够的堆空间来支持任务的创建。
函数原型
BaseType_t xTaskCreate(
TaskFunction_t pvTaskCode,
const char * const pcName,
configSTACK_DEPTH_TYPE usStackDepth,
void *pvParameters,
UBaseType_t uxPriority,
TaskHandle_t *pxCreatedTask );
pvTaskCode
: 指向任务函数的指针。pcName
: 任务名称字符串。usStackDepth
: 任务栈大小(单位取决于configUSE_16_BIT_TICKS
配置)。pvParameters
: 传递给任务的参数。uxPriority
: 任务优先级。pxCreatedTask
:pxCreatedTask
是一个指向TaskHandle_t
类型的指针。- 它用于接收新创建任务的任务句柄。
- 通过任务句柄,可以对任务进行各种管理和控制操作。
- 任务管理: 通过任务句柄,你可以对任务执行各种操作,例如:
- 挂起任务: 使用
vTaskSuspend(xTaskHandle)
。 - 恢复任务: 使用
vTaskResume(xTaskHandle)
。 - 删除任务: 使用
vTaskDelete(xTaskHandle)
。 - 查询任务状态: 使用
eTaskGetState(xTaskHandle)
。
- 挂起任务: 使用
静态创建任务
静态创建任务时,所有必要的内存都需要在编译时预先分配好,这使得系统更加稳定和可预测,适用于对内存使用有严格要求的应用场景。
函数原型
TaskHandle_t xTaskCreateStatic(
TaskFunction_t pvTaskCode,
const char * const pcName,
uint32_t ulStackDepth,
void *pvParameters,
UBaseType_t uxPriority,
StackType_t *puxStackBuffer,
StaticTask_t *pxTaskBuffer );
pvTaskCode
: 指向任务函数的指针。pcName
: 任务名称字符串。ulStackDepth
: 任务栈大小(单位是StackType_t
类型的元素数量)。pvParameters
: 传递给任务的参数。uxPriority
: 任务优先级。puxStackBuffer
: 指向预先分配好的栈缓冲区。pxTaskBuffer
: 指向预先分配好的任务控制块缓冲区。
重点讲解
当使用 xTaskCreateStatic
创建静态任务时,你需要提供两个缓冲区:
StackType_t *puxStackBuffer
: 用于任务的堆栈。
StackType_t 和 栈深度
-
StackType_t
- 定义:
StackType_t
是一个平台相关的类型,通常定义为uint32_t
或uint16_t
,具体取决于配置选项configSTACK_DEPTH_TYPE
。 - 作用: 用于表示堆栈中的每个元素。
- 定义:
StaticTask_t *pxTaskBuffer
: 用于任务的 任务控制块TCB。
在 FreeRTOS 中,StaticTask_t *pxTaskBuffer
和任务控制块(Task Control Block, TCB)之间有着密切的关系。StaticTask_t
实际上是一个结构体,用于存储任务的所有状态信息,即任务控制块的内容。
-
TCB (Task Control Block)
- 定义: TCB 是一个数据结构,包含了任务的所有必要信息,如任务的状态、优先级、堆栈指针、任务函数指针等。
- 作用: 操作系统使用 TCB 来管理任务的生命周期和调度。
-
StaticTask_t
- 定义:
StaticTask_t
是一个结构体,专门用于静态任务的 TCB 存储。 - 作用: 在静态任务创建时,
StaticTask_t
提供了预先分配的内存空间来存储任务的 TCB。
- 定义:
对比
特性 | 动态创建任务 | 静态创建任务 |
---|---|---|
内存分配 | 在运行时从堆中分配 | 在编译时由用户预先分配 |
灵活性 | 更高,易于管理大量任务 | 较低,每个任务需要单独配置内存 |
可靠性 | 中等,依赖于堆可用性 | 更高,避免了堆碎片化问题 |
性能 | 较差,涉及堆分配 | 更好,没有额外的内存分配开销 |
应用场景 | 适合大多数应用,尤其是资源相对充足的情况 | 适合对内存使用有严格限制或实时性能要求较高的场合 |