原理篇5、ESP32中的FreeRTOS

您所在的位置:网站首页 delaycam软件 原理篇5、ESP32中的FreeRTOS

原理篇5、ESP32中的FreeRTOS

2023-12-12 03:22| 来源: 网络整理| 查看: 265

目录 ESP32简介1、CPU2、储存3、通信4、硬件 FreeRTOS简介说明任务任务创建任务删除 软件定时器创建软件定时器软件定时器激活软件定时器停止软件定时器删除 队列队列创建队列写入队列读取 信号量信号量创建信号量获取信号量释放信号量删除 任务通知向其他任务[发送通知](https://www.freertos.org/xTaskNotifyGive.html)等待其他任务的通知

ESP32简介

乐鑫官网关于ESP32 系列模组的技术规格书 https://www.espressif.com/zh-hans/products/modules

乐鑫官网关于 ESP32-­WROOM-­32E 模组的技术规格书 https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32e_esp32-wroom-32ue_datasheet_cn.pdf

以下介绍的都是以 ESP32-­WROOM-­32E 模组为准。

.

1、CPU

内置 ESP32-D0WD-V3 芯片,Xtensa® 双核 32位 LX6 微处理器,支持高达 240 MHz 的时钟频率。

.

2、储存 类型大小ROM448 KBSRAM520 KBRTC SRAM16 KBSPI flash4 MB

.

3、通信 类型-Wi­Fi2.4G (802.11b/g/n)蓝牙蓝牙 V4.2 BR/EDR 和蓝牙 LE 标准

.

4、硬件 模组接口IRSPII2CADCDACGPIOUARTSD 卡LED PWM脉冲计数器霍尔传感器电容式触摸传感器

.

.

FreeRTOS简介

FreeRTOS官网 https://www.freertos.org/index.html

FreeRTOS内核开发文档 https://www.freertos.org/features.html

FreeRTOS开发API参考 https://www.freertos.org/a00106.html

.

介绍FreeRTOS的原因:我们编写的 Arduino 代码是跑在FreeRTOS系统上的,并非裸奔。 例如 loop()函数是通过创建一个优先级为1的任务来运行此函数。

检查方法:在Arduino IDE内随便打开一个关于ESP32开发板的示例,点击左上角的 项目-显示项目文件夹(或者按下 Ctrl+K )。 在打开的文件夹内的文件路径一直往后退,直到找到如下文件名 在这里插入图片描述 名称为1.0.4的目录名表示版本号,和你下载安装的版本有关。 在此目录下可看到如下目录 在这里插入图片描述 打开cores目录,找到以下内容。 在这里插入图片描述 打开 main.cpp 文件即可查看 setup() 和loop()函数所在的运行位置。 在这里插入图片描述

#include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_task_wdt.h" #include "Arduino.h" TaskHandle_t loopTaskHandle = NULL; #if CONFIG_AUTOSTART_ARDUINO bool loopTaskWDTEnabled; void loopTask(void *pvParameters) { setup(); for(;;) { if(loopTaskWDTEnabled){ esp_task_wdt_reset(); } loop(); } } extern "C" void app_main() { loopTaskWDTEnabled = false; initArduino(); xTaskCreateUniversal(loopTask, "loopTask", 8192, NULL, 1, &loopTaskHandle, CONFIG_ARDUINO_RUNNING_CORE); } #endif

.

.

说明

关于FreeRTOS的设置,如任务最大优先级,软件定时器优先级,任务最小深度,系统时钟频率等,可在目录 在这里插入图片描述 中的FreeRTOSConfig.h文件查看。

.

.

.

任务

高优先级任务必须延迟一定时间,给低优先级任务留出执行时间,否则低优先级任务永远处于挂起状态,会导致系统复位。

任务创建

定义任务句柄

TaskHandle_t xHandle1 = NULL;

定义任务函数

void vTaskFunction(void *pvParameters) { for(;;) { vTaskDelay(1000); } }

开启任务 未指定ESP32的CPU

BaseType_t xReturned; xReturned = xTaskCreate ( vTaskFunction, //定义的任务函数 "Task1", //任务名称 configMINIMAL_STACK_SIZE, //任务深度 此值并非字节数 NULL, //输入参数 tskIDLE_PRIORITY + 2, //优先级 tskIDLE_PRIORITY 为最低优先级0 &xHandle1 //绑定任务句柄 如果不删除或不检测任务自身信息 也可以不填入句柄直接为 NULL );

指定ESP32的CPU

BaseType_t xReturned; xReturned = xTaskCreatePinnedToCore ( vTaskFunction, //定义的任务函数 "Task1", //任务名称 configMINIMAL_STACK_SIZE, //任务深度 此值并非字节数 NULL, //输入参数 tskIDLE_PRIORITY + 2, //优先级 tskIDLE_PRIORITY 为最低优先级0 &xHandle1, //绑定任务句柄 如果不删除或不检测任务自身信息 也可以不填入句柄直接为 NULL vTask_CORE //绑定到指定CPU );

注: xTaskCreate() 和 xTaskCreatePinnedToCore() 的返回值xReturned 成功返回 pdPASS, 失败返回 errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY。

.

任务删除

指定任务句柄

//删除任务句柄为 xHandle1 的任务 vTaskDelete(xHandle1);

不指定任务句柄

//删除调用此句的任务自身 vTaskDelete(NULL);

.

.

.

软件定时器 创建软件定时器

定义定时器句柄

TimerHandle_t xSoftwareTimerHandle_t = NULL;

定义定时器回调函数

//括号内的内容不能删除 void vTimerCallback(TimerHandle_t pxTimer ) { }

开启软件定时器

//如果成功创建了计时器,则返回新创建的计时器的句柄 xSoftwareTimerHandle_t = xTimerCreate ( "vTimerCallback", //名称 2000, //周期时长 系统滴答数(默认ms) pdTRUE, //是否重新加载,pdFALSE为单次调用 0, //pvTimerID vTimerCallback //定义的定时器回调函数 );

.

软件定时器激活 xTimerStart( xSoftwareTimerHandle_t, 0 );//激活成功返回 pdPASS //第1个参数:软件计时器的句柄 //第2个参数:指定在调用xTimerStart()时,如果队列已满, //则调用任务应保持在“阻塞”状态 //以等待开始命令成功发送到计时器命令队列的时间(以秒为单位)。

.

软件定时器停止 xTimerStop(xSoftwareTimerHandle_t, xBlockTime); //如果即使经过xBlockTime(默认ms)刻度后仍无法将stop命令发送到计时器命令队列, //则将返回pdFAIL。 //如果命令已成功发送到计时器命令队列, //则将返回pdPASS。 //实际处理命令的时间将取决于 //计时器服务/守护程序任务相对于系统中其他任务的优先级。 //计时器服务/守护程序任务优先级由 //configTIMER_TASK_PRIORITY 配置常量设置,默认为1。

.

软件定时器删除 xTimerDelete(xSoftwareTimerHandle_t, xBlockTime); //成功返回,pdPASS。失败返回pdFAIL。 //在调用xTimerDelete()时, //如果队列已满,则调用任务应保持在xBlockTime状态的时间(默认ms), //以等待删除命令成功发送到计时器命令队列。 //如果在启动RTOS调度程序之前调用了xTimerDelete(), //则将忽略xBlockTime。

.

.

.

队列 队列创建

定义队列句柄

QueueHandle_t xQueue1;

创建队列

//uxQueueLength:队列一次可以容纳的最大项目数,即队列长度 //uxItemSize: 存放队列中每个项目所需的大小(以字节为单位)。 QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize); //创建1个大小为 sizeof(double) 的队列。 POWER_IIR_QUEUE = xQueueCreate(1, sizeof(double));

.

队列写入

等待方法

//xQueue:队列句柄 //pvItemToQueue:指向要放在队列中的项目的指针 //如果任务已满,则该任务应阻止等待队列上的可用空间的最长时间。 //如果队列已满并且 xTicksToWait 设置为 0 ,则调用将立即返回 //如果队列已满并且 xTicksToWait 设置为 portMAX_DELAY, //将导致任务无限期地阻止(无超时)。 BaseType_t xQueueSend( QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait );

非等待方法

//即使队列已满,该版本也会写入队列,从而覆盖队列中已保存的数据。 //pdPASS是唯一可以返回的值,因为即使队列已满,xQueueOverwrite()也会写入队列。 BaseType_t xQueueOverwrite( QueueHandle_t xQueue, const void * pvItemToQueue );

.

队列读取

读取后不删除队列内数据

//从队列中接收项目而不从队列中删除该项目。 //xQueue: 所读取队列的句柄 //*pvBuffer:指向将接收的项目复制到其中的缓冲区的指针。 //必须至少足够大以容纳创建队列时定义的队列项目的大小。 //xTicksToWait: 如果在调用时队列为空, //任务应等待等待接收项目的最长时间。 //指定为portMAX_DELAY将导致任务无限期地阻止(无超时)。 BaseType_t xQueuePeek( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait );

读取后删除队列内数据

//从队列中接收项目。 //该项目以副本形式接收,因此必须提供足够大小的缓冲区。 //创建队列时定义了复制到缓冲区中的字节数。 //xQueue: 所读取队列的句柄 //*pvBuffer:指向将接收的项目复制到其中的缓冲区的指针。 //xTicksToWait: 如果在调用时队列为空, //任务应等待等待接收项目的最长时间。 //指定为portMAX_DELAY将导致任务无限期地阻止(无超时)。 BaseType_t xQueueReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait );

.

.

.

.

信号量 信号量创建

定义信号量句柄

SemaphoreHandle_t xSemaphore = NULL;

创建

xSemaphore = xSemaphoreCreateBinary(); //成功返回信号量的句柄,失败返回 NULL

.

信号量获取 //成功返回 pdTRUE,过期/失败 返回 pdFALSE,等待 10 个系统节拍(即10ms) if(xSemaphoreTake(xSemaphore,10) == pdTRUE) { }

.

信号量释放 xSemaphoreGive(xSemaphore); //每次获取成功之后都要进行释放(重新给信号), //否则无法再次获取(获取信号),每次获取都将失败。

.

信号量删除 vSemaphoreDelete(xSemaphore); xSemaphore = NULL;

.

.

.

任务通知 向其他任务发送通知 //xTask2 为任务二的权柄 xTaskNotifyGive(xTask2);

.

等待其他任务的通知 //设置为 pdTRUE ,则在 ulTask​​NotifyTake() 退出之前, //RTOS 任务的通知值将重置为0。 //设置为 pdFALSE ,则在 ulTask​​NotifyTake() 退出之前, //RTOS任务的通知值将减小。 //portMAX_DELAY 为最大等待时间 等待期间不占用 CPU 时间 ​ulTask​​NotifyTake(pdTRUE, portMAX_DELAY);

.

.



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3