ESP32 freeRTOS笔记 参数传递、任务优先级

一、四种参数传递方式

1.1 整数传递

使用 (void *) 任何类型传递参数,通过地址传递给任务。

#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"void myTask(void *pvPragma)
{int *getNum;getNum = (int *)pvPragma; //强转int类型指针printf("Task get num = %d\n",*getNum); //此处*为解地址符,解出地址存的东西vTaskDelay(1000 / portTICK_PERIOD_MS);vTaskDelete(NULL);
}int IntNum = 1;void app_main(void)
{xTaskCreate(myTask, "mytask1", 2048, (void *)&IntNum, 1, NULL);    //取地址后传递参数
}

效果如下: 

1.2 数组

#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"void myTask(void *pvPragma)
{int *pArrayNum;pArrayNum = (int *)pvPragma;printf("Task get num1 = %d\n", *pArrayNum);//因为是int类型指针 +1移动自动移动一个intprintf("Task get num2 = %d\n", *(pArrayNum + 1)); //此处*为解地址符,解出地址存的东西printf("Task get num3 = %d\n", *(pArrayNum + 2));vTaskDelay(1000 / portTICK_PERIOD_MS);vTaskDelete(NULL);
}int testNum[] = {5, 6, 7};void app_main(void)
{//数组本来就是地址 直接传递 不加&xTaskCreate(myTask, "mytask1", 2048, (void *)testNum, 1, NULL);    
}

效果如下:  

1.3 结构体

和整数传递很像,只不过换成了结构体,任务函数也是强转成结构体指针。

#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"//-------------------------------------------------------
typedef struct A_struct
{int num1;int num2;
} xstruct;//xstruct=struct A_struct,不清楚时查看struct和typedef struct的区别
xstruct testnum = {5,6};
void mytask(void *pvParam)
{xstruct *p;                             //声明一个结构体指针类型的变量,p = (xstruct *)pvParam;                 // 因为这里参数传的都是地址,将参数强制转化为相同的类型,取得输入参数的地址printf("I get testnum num1 = %d\n", p->num1); printf("I get testnum num2 = %d\n", p->num2); vTaskDelay(1000 / portTICK_PERIOD_MS);vTaskDelete(NULL);
}
//-------------------------------------------------------
void app_main(void)
{xTaskCreate(mytask, "mytask1", 2048, (void *)&testnum, 1, NULL);
}

效果如下:  

1.4 字符串

#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"static const char *ptest = "hello world";void mytask(void *pvParam)
{char *p;                            p = (char *)pvParam;                 printf("I get message = %s\n", p); vTaskDelay(1000 / portTICK_PERIOD_MS);vTaskDelete(NULL);
}void app_main(void)
{xTaskCreate(mytask, "mytask1", 2048, (void *)ptest, 1, NULL);
}

效果如下:  

二、Task 任务优先级

2.1 任务优先级简介

FreeRTOS 中任务优先级数字越大,优先级越高。

引用 RTOS 官方手册RTOS task priorities in FreeRTOS for pre-emptive and co-operative real time operation

也就是 configMAX_PRIORITIES 是当前项目中允许的最大优先级。

在下路径中可以找到这个宏定义,其中在 esp-idf 代码中(非项目代码,应该是模板代码路径),FreeRTOSConfig.h 文件保存了这个的默认值。 

2.2 使用 uxTaskPriorityGet()

函数原型:

UBaseType_t uxTaskPriorityGet(TaskHandle_t xTask );
//参数: xTask: 要查找的任务的任务句柄。
//返回值: 获取到的对应的任务的优先级。 

对于 esp32 默认的 configMAX_PRIORITIES 是 25。但是如果我们创建优先级的时候将优先级设置为 25 以上。比如下文的 41。

#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"static const char *ptest = "hello world";void mytask(void *pvParam)
{char *p;                            p = (char *)pvParam;                 printf("I get message = %s\n", p); vTaskDelay(1000 / portTICK_PERIOD_MS);vTaskDelete(NULL);
}void app_main(void)
{UBaseType_t iPriority = 0;TaskHandle_t pxTask = NULL;xTaskCreate(mytask, "mytask1", 2048, (void *)ptest, 41, &pxTask);iPriority = uxTaskPriorityGet(pxTask);printf("iPriority = %d\n",iPriority);
}

2.3 使用 vTaskPrioritySet() 

vTaskPrioritySet() 可以设置任务的优先级。如果设置的优先级高于当前执行任务的优先级,则上下文切换将在此函数返回之前发生。

void app_main(void)
{TaskHandle_t pxTask = NULL;UBaseType_t iPriority = 0;xTaskCreate(myTask1, "mytask1", 2048, (void *)ptest, 1,&pxTask);xTaskCreate(myTask2, "mytask2", 2048, (void *)ptest, 4, NULL);vTaskPrioritySet(pxTask,3);iPriority = uxTaskPriorityGet(pxTask);printf("Task1 iPriority = %d\n",iPriority);
}

 

三、Task 堆栈设置和调试

3.1 显示任务详细信息 vTaskList()

通过 vTaskList来协助分析操作系统当前 task 状态,以帮助优化内存,帮助定位栈溢出问题。

void vTaskList( char *pcWriteBuffer );
parameterdescription
pcWriteBuffer保存任务状态信息表的存储区,须足够大
return

pcWriteBuffe 表中信息:

说明定义
Name创建任务的时候给任务分配的名字
State任务的状态信息,X:运行态,B:阻塞态,R:就绪态,S:挂起态,D:删除态
Priority任务优先级
Stack任务堆栈的“高水位线”,就是堆栈历史最小剩余值
Num任务编号,这个编号是唯一的;当多个任务使用同一个任务名的时候;可以通过编号来区分
void task1(void *pvParam)
{while (1){printf("task1!\n");vTaskDelay(3000 / portTICK_PERIOD_MS);}
}void task2(void *pvParam)
{while (1){printf("task2!\n");vTaskDelay(3000 / portTICK_PERIOD_MS);}
}void app_main(void)
{xTaskCreate(task1, "task1", 4096, NULL, 1, NULL);xTaskCreate(task2, "task2", 4096, NULL, 1, NULL);static char pcWriteBuffer[512] = {0};while(1){vTaskList(pcWriteBuffer);printf("-----------------------------------------\n");printf("Name    State   Priority    Stack   Num\n");printf("%s\n",pcWriteBuffer);vTaskDelay(1000 / portTICK_PERIOD_MS);}
}

 3.2  查看任务剩余的堆栈空间 uxTaskGetStackHighWaterMark() 

函数原型:

UBaseType_t uxTaskGetStackHighWaterMark(TaskHandle_t xTask)

传 入 值:xTask 要查询的任务的任务句柄,若为NULL表示查询自身任务的高水位线

返 回 值:任务堆栈的高水位线值,即堆栈的历史剩余最小值。

注意是以字节为单位

void task1(void *pvParam)
{while (1){printf("task1!\n");vTaskDelay(3000 / portTICK_PERIOD_MS);}
}void app_main(void)
{TaskHandle_t pxTask1;xTaskCreate(task1, "task1", 4096, NULL, 1,&pxTask1);UBaseType_t iStack;while(1){iStack = uxTaskGetStackHighWaterMark(pxTask1);printf("task1 iStack = %d\n",iStack);vTaskDelay(3000 / portTICK_PERIOD_MS);}
}

 上述代码中,task1有两行函数。运行效果如下:

如果我们将 task1中的 printf 注释掉

void task1(void *pvParam)
{while (1){printf("task1!\n");vTaskDelay(3000 / portTICK_PERIOD_MS);}
}

效果如下:

与之对比,可得出printf占用了大概300多字节的堆栈。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/247410.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端笔记(三)CSS 盒子模型

结构伪类选择器 基本的结构伪类选择器 可以根据元素的结构关系来查找元素 比如列标签 li&#xff0c;使用 li:first-child { background-color: green; }就可以选中第一个该标签。 <!DOCTYPE html> <html lang"en"> <head><meta charset&q…

JavaWeb 前端工程化

前端工程化是使用软件工程的方法来单独解决前端的开发流程中模块化、组件化、规范化、自动化的问题,其主要目的为了提高效率和降低成本。 前端工程化实现技术栈 前端工程化实现的技术栈有很多,我们采用ES6nodejsnpmViteVUE3routerpiniaaxiosElement-plus组合来实现 ECMAScri…

spring cloud 整合Feign经行远程调用

文章目录 Feign远程调用Feign替代RestTemplate1&#xff09;引入依赖2&#xff09;添加注解3&#xff09;编写Feign的客户端4&#xff09;测试5&#xff09;总结 自定义配置配置文件方式Java代码方式 Feign使用优化 Feign远程调用 先来看我们以前利用RestTemplate发起远程调用…

【Vue】使用 Vue CLI 脚手架创建 Vue 项目(使用GUI创建)

前言 在开始使用Vue进行开发之前&#xff0c;我们需要先创建一个Vue项目。Vue CLI&#xff08;Command Line Interface&#xff09;是一个官方提供的脚手架工具&#xff0c;可以帮助我们快速创建Vue项目。Vue CLI也提供了一个可视化的GUI界面来创建和管理Vue项目。 步骤 打开终…

MQ - KAFKA 高级篇

kafak是一个分布式流处理平台,提供消息持久化,基于发布-订阅的方式的消息中间件&#xff0c;同时通过消费端配置相同的groupId支持点对点通信。 ##适用场景&#xff1a; 构造实时流数据管道,用于系统或应用之间可靠的消息传输.数据采集及处理,例如连接到一个数据库系统,捕捉表…

SASE:网络与安全的未来之路

随着数字化时代的到来&#xff0c;企业和个人对网络连接和安全性的需求日益增长。传统的网络架构已经无法满足这些需求&#xff0c;因此&#xff0c;新兴的网络和安全框架SASE&#xff08;Secure Access Service Edge&#xff09;应运而生。本文将介绍什么是SASE&#xff0c;并…

T-SQL的多表查询

前面讲述过的所有查询都是基于单个数据库表的查询。如果一个查询需要对多个表进行操作&#xff0c;就称为联接查询&#xff0c;联接查询的结果集或结果称为表之间的联接。 联接查询实际上是通过各个表之间共同列的关联性来查询数据的&#xff0c;它是关系数据库查询最主要的特征…

OpenCV快速入门:移动物体检测和目标跟踪

文章目录 前言一、移动物体检测和目标跟踪简介1.1 移动物体检测的基本概念1.2 移动物体检测算法的类型1.3 目标跟踪的基本概念1.4 目标跟踪算法的类型 二、差值法检测移动物体2.1 差值法原理2.2 差值法公式2.3 代码实现2.3.1 视频或摄像头检测移动物体2.3.2 随机动画生成的移动…

使用栈解决括号匹配问题(详解)

项目结构 项目头文件的代码或截图 头文件代码 #ifndef LINKSTACK_H #define LINKSTACK_H #include <stdio.h> #include <stdlib.h> // 链式栈的节点 typedef struct LINKNODE {struct LINKNODE* next; }LinkNode; // 链式栈 typedef struct LINKSTACK {LinkNode h…

ES 快照到 S3 并从 Windows 共享目录恢复(qbit)

前言 业务需要将 Elasticsearch 快照到 AWS S3&#xff0c;再将快照拷贝到 Windows 系统&#xff0c;并恢复到 Elasticsearch。如下图所示&#xff1a; 环境 Elasticsearch 7.10.1 Windows Server 2019 Ubuntu 20.04 &#xff08;ES 宿主&#xff09; ES 集群1 安装 S3 插…

进入软件的世界

选择计算机 上高中的时候&#xff0c;因为沉迷于网络游戏&#xff0c;于是对计算机产生了浓厚的兴趣&#xff0c;但是那个时候对于计算机的了解还是非常肤浅的。上大学的时候&#xff0c;也就义无反顾的选择了计算机专业&#xff0c;其实并不是一个纯粹的计算机专业&#xff0…

4G基站BBU、RRU、核心网设备

目录 前言 基站 核心网 信号传输 前言 移动运营商在建设4G基站的时候&#xff0c;除了建设一座铁塔之外&#xff0c;更重要的是建设搭载铁塔之上的移动通信设备&#xff0c;这篇博客主要介绍BBU&#xff0c;RRU以及机房的核心网等设备。 基站 一个基站有BBU&#xff0c;…