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移动自动移动一个int
    printf("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多字节的堆栈。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

简单了解HTTP报文及示例

简单了解HTTP报文及示例 HTTP报文请求报文响应报文通用首部字段Cache-ControlConnectionDate 请求首部字段AcceptAccept-CharsetAccept-EncodingAccept-LanguageHostIf-MatchIf-Modified-SinceIf-None-MatchRefererUser-Agent 响应首部字段Accpet-RangesAgeLocationServer 实体…

8.HTTP工作原理

HTTP是什么 HTTP工作原理 HTTP协议的请求类型和响应状态码 总结 1.HTTP是什么 HTTP超文本传输协议就是在一个网络中上传下载文件的一套规则 2.HTTP工作原理 HTTP超文本传输协议的本质是TCP通信&#xff0c;链接—>请求—>响应—>断开 3.HTTP协议的请求类型和响应状…

stm32L071KB单片机字节对齐问题

字节对齐问题由来很关键 字节对齐问题由来 字节对齐问题由来 在移植同事代码的时候发现到一个赋值变量的地方就会出现死机&#xff0c;进入hardfault,怎么也找不不到原因&#xff0c;最后没办法去了github https://github.com/armink/CmBacktrace/blob/master/README_ZH.md Cm…

AWS攻略——使用中转网关(Transit Gateway)连接同区域(Region)VPC

文章目录 环境准备创建VPC 配置中转网关给每个VPC创建Transit Gateway专属挂载子网创建中转网关创建中转网关挂载修改VPC的路由 验证创建业务Private子网创建可被外网访问的环境测试子网连通性Public子网到Private子网Private子网到Private子网 知识点参考资料 在《AWS攻略——…

Hadoop的介绍与安装

1 Hadoop的简介 Hadoop是一个开源的大数据框架&#xff0c;是一个分布式计算的解决方案。Hadoop是由java语言编写的&#xff0c;在分布式服务器集群上存储海量数据并运行分布式分析应用的开源框架&#xff0c;其核心部件是HDFS与MapReduce。 HDFS是一个分布式文件系统&#x…

新华三数字大赛复赛知识点 AAA

AAA的概念和架构&#xff0c;RADIUS和TACASS的原理和配置 AAA是网络访问控制的一种安全管理框架&#xff0c;他决定哪些的用户能够访问网络&#xff0c;以及用户能够访问哪些资源或者得到哪些服务。 第一个A&#xff1a;认证 认证用来识别访问网络的用户的身份&#xff0c;判断…

Proteus仿真--基于1602LCD与DS18B20设计的温度报警器

本文介绍基于1602LCD与DS18B20设计的温度报警器设计&#xff08;完整仿真源文件及代码见文末链接&#xff09; 仿真图如下 其中温度传感器选用DS18B20器件&#xff0c;主要用于获取温度数据并上传&#xff0c;温度显示1602LCD液晶显示器&#xff0c;报警模块选用蜂鸣器&#…

【电机控制】PMSM无感foc控制(五)相电流检测及重构 — 单电阻采样

0. 前言 相电流采样再FOC控制中是一个关键的环节&#xff0c;鉴于成本和易用性&#xff0c;目前应用较多的相电流采样方式是分流电阻采样&#xff0c;包括单电阻、双电阻以及三电阻采样法。 本章节先讲解单电阻采样相电流的检测及重构技术&#xff0c;在下一章讲解双电阻和三电…

linux 应用开发笔记---【标准I/O库/文件属性及目录】

一&#xff0c;什么是标准I/O库 标准c库当中用于文件I/O操作相关的一套库函数&#xff0c;实用标准I/O需要包含头文件 二&#xff0c;文件I/O和标准I/O之间的区别 1.标准I/O是库函数&#xff0c;而文件I/O是系统调用 2.标准I/O是对文件I/O的封装 3.标准I/O相对于文件I/O具有更…

spark sql基于RBO的优化

前言 这里只对RBO优化进行简单的讲解。讲解RBO之前必须对spark sql的执行计划做一个简单的介绍。 这个里讲解的不是很清楚&#xff0c;需要结合具体的执行计划来进行查看 1、执行计划 在spark sql的执行计划中&#xff0c;执行计划分为两大类&#xff0c;即逻辑执行计划、物…

基于Docker构建Python开发环境

1. Dockerfile dockerfile所在目录结构 FROM python:3.8 WORKDIR /leo RUN apt-get install -y wget RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai >/etc/timezone # ssh免密登录 COPY id_rsa.pub /leo RUN mkdir ~/.s…

【Unity动画】状态机中层的融合原理与用法详解

1. 状态机概念介绍 在Unity中&#xff0c;动画状态机&#xff08;Animator State Machine&#xff09;是一种强大的工具&#xff0c;用于控制游戏对象的动画行为。动画状态机由多个动画状态Animation和过渡条件Transition、层组成&#xff01;而层&#xff08;Layers&#xff…

IDEA构建springBoot新项目时JDK只有17和21,无法选择JDK8解决方案

今天创建springboot新项目时&#xff0c;发现IDEA里JDK选项只有17和21&#xff0c;无法选择本机的JDK8&#xff0c;网上查资料后发现是springboot2.7于11.24号后停止维护&#xff0c;基于2.7和java8的spring Initializ官方不再维护&#xff0c;解决方案是在server URL栏&#x…

[RK-Linux] 移植Linux-5.10到RK3399(三)| 检查eMMC与SD卡配置

这个专题主要记录把 RK Linux-5.10 移植到 ROC-RK3399-PC Pro 的过程。 文章目录 一、eMMC二、SD 卡三、两个接口的区别一、eMMC RK3399 的 eMMC 接口如图: datasheet 介绍: 实际上,连接 eMMC 存储器用的是 SDHCI 接口。SDHCI(Secure Digital Host Controller Interface)…

【MySQL语言汇总[DQL,DDL,DCL,DML]以及使用python连接数据库进行其他操作】

MySQL语言汇总[DQL,DDL,DCL,DML] SQL分类1.DDL:操作数据库&#xff0c;表创建 删除 查询 修改对数据库的操作对表的操作复制表&#xff08;重点&#xff09;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 2.DML:增删改表中数据3.DQL&#xff1a;查询表中的记录…

Pytorch CIFAR10图像分类 Swin Transformer篇

Pytorch CIFAR10图像分类 Swin Transformer篇 文章目录 Pytorch CIFAR10图像分类 Swin Transformer篇4. 定义网络&#xff08;Swin Transformer&#xff09;Swin Transformer整体架构Patch MergingW-MSASW-MSARelative position biasSwin Transformer 网络结构Patch EmbeddingP…

【深度学习】回归模型相关重要知识点总结

回归分析为许多机器学习算法提供了坚实的基础。在这篇文章中&#xff0c;我们将总结 10 个重要的回归问题和5个重要的回归问题的评价指标。 一、线性回归的假设是什么 线性回归有四个假设&#xff1a; 线性&#xff1a;自变量&#xff08;x&#xff09;和因变量&#xff08;y&…

创新领航 | 竹云参编《基层智治系统安全接入规范》团体标准正式发布!

近日&#xff0c;由杭州市委办公厅&#xff08;市密码管理局&#xff09;、杭州市基层治理综合指挥保障中心、杭州市拱墅区社会治理中心、杭州市拱墅区数据资源管理局、杭州竹云数字智能科技有限公司、杭州智诚质量标准技术评定中心共同参与编写的《基层智治系统安全接入规范》…

录视频人不在电脑旁,怎么设置定时关机

如果你平常工作比较忙&#xff0c;或者要录制的视频/音频文件需要很长时间&#xff0c;最好选择预约录制&#xff0c;这样可使录屏软件自动开始和停止录制&#xff0c;并且定时关机。此外&#xff0c;你还可以设置保存录制文件、关闭录屏软件。是不是听起来很感兴趣&#xff1f…

【unity3D】创建游戏物体的三种方式

&#x1f497; 未来的游戏开发程序媛&#xff0c;现在的努力学习菜鸡 &#x1f4a6;本专栏是我关于游戏开发的学习笔记 &#x1f236;本篇是在unity中创建游戏物体的三种方式 unity中创建游戏物体 使用构造函数创建一个空的游戏对象根据现有的预制体资源或者场景中已有的物体进…