任务可以存在于以下状态:

运行
当任务实际执行时,它被称为处于运行状态。任务当前正在使用处理机。如果运行RTOS的处理器只有一个内核,那么在任何给定时间内都只能有一个任务处于运行状态。

准备就绪
准备就绪任务指那些能够执行(它们不处于阻塞或挂起状态),但目前没有执行的任务,因为同等或更高优先级的不同任务已经处于运行状态。

阻塞
如果任务当前正在等待时间或外部时间,则该任务被认为处于阻塞状态。例如,如果一个任务调用vTaskDelay(),它将被阻塞(被置于阻塞状态),直到延迟结束一个时间事件。任务也可以通过阻塞来等待队列、信号量、事件组、通知或信号量事件。处于阻塞状态的任务通常有一个“超时”期,超时后任务被超时,并被解除阻塞,即使该任务所等待的事件没有发生。

“阻塞”状态下的任务不使用任何处理时间,不能 被选择进入运行状态。

挂起
与“阻塞”状态下的任务一样,“挂起”状态下的任务不能 被选择进入运行状态,但处于挂起状态的任务 没有超时。相反,任务只有在分别通过vTaskSuspend() 和 xTaskResume() API调用明确命令时才会进入或退出挂起状态。

任务创建

![[Pasted image 20250515092426.png]]

1
2
3
4
5
6
7
8
9
10
11

Base Type_t xTaskCreatePinnedToCore(
TaskFunction pvTaskCode,//任务函数指针,原型是void fun(void *param)
const char * constpcName,//任务的名称,打印调试可能会有用
const uint32_t usStackDepth,//指定的任务堆栈空间大小(字节)
void * constpvParameters,//任务参数
UBaseType_t uxPriority,//优先级,数字越大,优先级越大,0到(configMAX_PRIORITIES-1)
TaskHandle_t * constpvCreatedTask,//传回来的任务句柄
const BaseType_t xCoreID//分配在哪个内核运行
)

关于栈区大小

任务在运行的时候,每个任务是来回切换运行的,操作系统在切换别的任务运行的时候,会把当前任务运行的寄存器,变量的值存储到内存(ram)里面.

当再次回到这个任务运行的时候,从内存把寄存器,变量的值读取出来,这样子的话就可以接着上次运行了.

阻塞

![[Pasted image 20250515094654.png]]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

//延时xTicksToDelay个周期
void vTaskDelay(const TickType_t xTicksToDelay)

//用于表示精确的解除阻塞时间
void vTaskDelayUntil(TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement);
//参数1:保存了上一次任务解除阻塞的时间,
//参数2:1+2后结束阻塞

cnt = xTaskGetTickCount();//获取当前系统节拍数
while(1)
{
vTaskDelayUntil(&cnt, 100);
···
}

实例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include "esp_log.h"
#include "freertos\FreeRTOS.h"
#include "freertos\task.h"

QueueHandle_t queue_handle = NULL;

typedef struct
{
    int value;
}queue_data_t;

void taskA(void * param)
{
    while (1)
    {
        ESP_LOGI("main","Hello world!");
        vTaskDelay(pdMS_TO_TICKS(500));
        //vTaskDelay(500/portTICK_PERIOD_MS);
    }
}
void app_main(void)
{
    xTaskCreatePinnedToCore(taskA, "helloworld", 2048, NULL, 3, NULL, 1);
}

难道使用了 2048-568 = 1480 ????

一个啥也没有的任务不可能使用这么多的,其实返回的是这个任务运行的时候使用的最大空间.

但是网络是都是说这个函数是剩下的栈空间呢? 如何解释?

其实是栈的生长方向的问题!

首先呢保存数据就是使用的数组保存的,数组有首地址和尾地址.

假设存储数据的时候是从首地址开始存储的,假设存储了568个数据,那么数据最大存储在568这个地址

那么就剩余1480个空间没有使用.那么返回的时候返回剩下的就是1480;

如果存储数据的时候是从数组的尾地址开始存储的,假设存储568个数据,其实数据是存储到 2047,2046,…,1479,1480 这些地址上

最终存储的地址是1480,但是呢从数组的首地址开始计算的话就会认为存储了1480个数据

那么便会计算出剩余568,正好和上面的相反.所以才返回568.

一般呢把空间设置为实际使用空间的1.5倍或者2倍就可以 568****2=1136