ESP32嵌入式FreeRtos--Task
Posted 稚子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ESP32嵌入式FreeRtos--Task相关的知识,希望对你有一定的参考价值。
FreeRTOS中文数据手册:https://www.freertos.org/zh-cn-cmn-s/RTOS.html
任务函数
任务函数 | 描述 |
---|---|
xTaskCreate() | 使用动态的方法创建一个任务 |
xTaskCreateStatic() | 使用静态的方法创建一个任务 |
xTaskCreatePinnedToCore | 指定任务运行的核心(最后一个参数) |
vTaskDelete() | 删除一个任务 |
vTaskDelete(NULL) | 不创建任务句柄,表示删除当前任务 |
xTaskCreate()
BaseType_t xTaskCreate(TaskFunction_t pxTaskCode, // 函数指针, 任务函数
const char *const pcName, // 任务的名字
const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小
void *const pvParameters, // 调用任务函数时传入的参数
UBaseType_t uxPriority, // 优先级
TaskHandle_t *const pxCreatedTask); // 任务句柄, 以后使用它来操作这个任务
任务的句柄,相当于任务的地址,可用通过获取任务的句柄,对任务进行设置。
#include <Arduino.h>
TaskHandle_t myHandle = NULL; // 创建一个任务句柄,空指针,避免产生野指针
void mytask(void *pt) // 不指定传入指针的类型
while (1)
Serial.println("hello world");
vTaskDelay(1000);
void setup()
xTaskCreate(mytask, "", 1024, NULL, 1, &myHandle);
vTaskDelay(1000);
if (myHandle != NULL)
vTaskDelete(myHandle); // 任务被删除后就不会在执行了,可以用于删除setup这个任务
void loop()
Task四种输入参数
传递整数
#include <Arduino.h>
int testnum = 1;
void mytask(void *pt)
int *pint = (int *)pt; // 数据解耦
Serial.println(*pint); // 输出结果为1
vTaskDelete(NULL);
void setup()
Serial.begin(9600);
xTaskCreate(mytask, "", 1024, (void *)&testnum, 1, NULL);
void loop()
传递数组
#include <Arduino.h>
int array[] = 1, 2, 3;
void mytask(void *pt)
int *parray = (int *)pt; // 强制转换为数组指针
for (int i = 0; i < sizeof(array) / sizeof(int); i++)
Serial.println(*(parray + i)); // 输出结果:1 2 3
vTaskDelete(NULL);
void setup()
Serial.begin(9600);
// 数组名为数组元素的首地址,所以不需要&
xTaskCreate(mytask, "", 1024 * 2, (void *)array, 1, NULL);
void loop()
传递结构体
#include <Arduino.h>
typedef struct STRUCT
int a;
char b;
myStruct;
myStruct test = 2, 'a';
void mytask(void *pt)
myStruct *mytest = (myStruct *)pt; // 强制转换为结构体指针
Serial.println(mytest->a); // 输出2
Serial.println(mytest->b); // 输出a
vTaskDelete(NULL);
void setup()
Serial.begin(9600);
xTaskCreate(mytask, "", 1024, (void *)&test, 1, NULL);
void loop()
传递字符串
#include <Arduino.h>
static const char *str = "hello world"; // static修饰代表只能在本文件中使用
void mytask(void *pt)
char *pstr = (char *)pt; // 强制转换为字符指针
Serial.println(pstr);
vTaskDelete(NULL);
void setup()
Serial.begin(115200);
xTaskCreate(mytask, "", 1024, (void *)&str, 1, NULL);
void loop()
任务优先级
一共有25个优先级别,最低为0,最高为24。(可用修改优先级别的数目超过25,但是不建议,级别越高,越占内存)
- 同一优先级别:创建以后,顺序运行,切换相同的时间线,给与相同的运行时间
- 不同优先级别:任务创建以后,先运行优先级别的任务,再运行低级别的任务
/*获取任务优先级、修改任务优先级*/
UBaseType_t priority = 0; // 任务优先级变量
TaskHandle_t pxtask = NULL; // 创建任务的句柄
xTaskCreatePinnedToCore(task1, "", 1024 * 2, NULL, 1, &pxtask, 1);
priority = uxTaskPriorityGet(pxtask); // 查看任务的优先级
vTaskPrioritySet(pxtask, 3); // 设置任务的优先级
// 这种方法,设置优先级不起作用
xTaskCreate(task1, "", 1024 * 2, NULL, 1, NULL);
xTaskCreate(task2, "", 1024 * 2, NULL, 2, NULL);
xTaskCreatePinnedToCore(task1, "", 1024 * 2, NULL, 1, NULL, 1);
xTaskCreatePinnedToCore(task2, "", 1024 * 2, NULL, 2, NULL, 1);
使用ESP32测试注意事项:
- 由于ESP32具有双核运行的功能,因此设置优先级和任务挂起无效,需要指定任务工作的核心,在同一个核心上,设置优先级才起作用。
任务的挂起和恢复
任务的状态:running、ready、blocked、suspended(挂起,暂停)
- running:任务处于运行状态,如果运行 RTOS 的处理器只有一个内核,那么在任何给定时间内都只能有一个任务处于运行状态。
- ready:不处于阻塞或挂起状态,但目前没有执行的任务,因为同等或更高优先级的不同任务已经处于运行状态。
- blocked:如果一个任务调用vTaskDelay(),它将被阻塞(被置于阻塞状态),直到延迟结束一个时间事件。
- 挂起状态:与“阻塞”状态下的任务一样,“挂起”状态下的任务不能被选择进入运行状态,但处于挂起状态的任务 没有超时。
/*任务挂起*/
TaskHandle_t pxtask = NULL; // 创建任务的句柄
xTaskCreatePinnedToCore(task1, "", 1024 * 2, NULL, 1, &pxtask, 1);
vTaskSuspend(pxtask); // 挂起任务,任务不再执行
vTaskResume(pxtask); // 恢复被挂起的任务,继续执行
vTaskSuspendAll(); // 挂起所有函数,挂起后不可以执行
vTaskResumeAll(); // 恢复所有挂起函数
Task系统信息显示
vTaskList()
Task堆栈设置和调试
uxTaskGetStackHighWaterMark(句柄)
查看当前函数剩余的内存大小,如果分配的内存不够,程序虽然不会报错,但是开发板会不断地重启。
分配的数量每+1,内存+4byte
以word为单位,1word = 4bytes
TaskHandle_t taskHandle; // 计算task的空间大小
xTaskCreatePinnedToCore(task1, "", 1024 * 2, NULL, 1, &taskHandle;, 1);
int waterMark = uxTaskGetStackHighWaterMark(taskHandle);
Serial.print(F("Task Free Memory: ")); // 任务剩余空间
Serial.print(waterMark); // 返回值即是当前任务所剩栈空间的最小值
Task看门狗
- watch dog有两种:一种是中断的watch dog,一种是task的watch dog
- 中断看门狗里面不能执行太多的代码,避免其他任务没有时间执行
esp_task_wdt_add(句柄)
开启看门狗esp_task_wdt_reset(句柄)
喂狗
野路子学习esp32 新建一个应用@a.宏万
选择菜单 新建一个项目
#include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_system.h" #include "esp_spi_flash.h" void app_main() { printf("Hello world!\\n"); }
# # "main" pseudo-component makefile. # # (Uses default behaviour of compiling all source files in directory, adding \'include\' to include path.)
# # This is a project Makefile. It is assumed the directory this Makefile resides in is a # project subdirectory. # PROJECT_NAME := hello include $(IDF_PATH)/make/project.mk
运行效果
以上是关于ESP32嵌入式FreeRtos--Task的主要内容,如果未能解决你的问题,请参考以下文章
嵌入式硬件Esp32例程Hello World Example 注释