FreeRTOS-队列

news2024/11/18 21:37:39

FreeRTOS-消息队列

  • 一、队列简介
  • 二、队列相关函数
    • 2.1 队列结构体
    • 2.2 队列相关API函数
  • 三、队列操作实验

一、队列简介

  • 队列是任务到任务、任务到中断、中断到任务数据交流的一种机制(消息传递)
  • 使用队列的情况下如图,在读队列时,会进入临界区,无法触发任务调度,不会出现多任务冲突,只需要调用API函数即可
    在这里插入图片描述
  • 在队列中可以存储数量有限大小固定的数据。队列中的每一个数据叫做“队列项目”,队列能够存储“队列项目”的最大数量称为队列的长度
  • 队列采用先进先出(FIFO)的数据存储缓冲机制,即先入队的数据会先从队列中被读取,FreeRTOS也可以配置成先进后出的方式
  • FreeRTOS中队列采用实际值传递,或传递地址
  • 任何任务和中断都可以向队列发送/读取消息
  • 当任务向一个队列发送消息时,可以指定一个阻塞时间,设置阻塞时间,确定是否等待或者返回
  • 当任务A写入队列时,队列已满的情况下,可以将该任务挂在阻塞列表等待发送列表。当任务B从队列读取数据时,队列无数据的情况下,将任务挂在阻塞列表等待接收列表里

二、队列相关函数

2.1 队列结构体

  • 下面是队列结构体介绍
typedef struct QueueDefinition
{
    int8_t * pcHead;//存储区域的起始地址
    int8_t * pcWriteTo;//下一个写入位置
    union
    {
        QueuePointers_t xQueue;//用于队列使用时
        SemaphoreData_t xSemaphore;//用于互斥信号量和递归互斥信号量时
    } u;//联合体
    List_t xTasksWaitingToSend;//等待发送列表(队列满)
    List_t xTasksWaitingToReceive;//等待接收列表(队列空)
    volatile UBaseType_t uxMessagesWaiting;//非空闲队列项目的数量
    UBaseType_t uxLength;//队列长度
    UBaseType_t uxItemSize;//队列项目大小
    volatile int8_t cRxLock;//读取上锁计数器
    volatile int8_t cTxLock;//写入上锁计数器
    //其他条件编译
}xQUEUE;

2.2 队列相关API函数

  • 使用队列时,主要流程为:创建队列 -> 写队列 -> 读队列
  • 创建队列相关API函数
xQueueCreate();//动态方式创建队列
xQueueCreateStatic();//静态方式创建队列
  • 动态创建队列函数宏定义
#define xQueueCreate(uxQueueLength,uxItemSize)
					xQueueGenericCreate( (uxQueueLength),(uxItemSize),(queueQUEUE_TYPE_BASE) )
//形参:队列长度  队列项目大小  代表创建的是队列还是互斥信号量等等
//返回值:NULL创建失败 队列创建成功返回队列句柄
  • 队列写入消息API函数
xQueueSend();//队列尾部写消息
xQueueSendToBack();//同上
xQueueSendToFront();//队列头部写消息
xQueueOverwrite();//覆写队列消息(只用于队列长度为1的情况)
xQueueSendFromISR();//在中断中往队列尾部写消息
xQueueSendToBackFromISR();//同上
xQueueSendToFrontFromISR();//在中断中往队列头部写消息
xQueueOverwriteFromISR();//在中断中覆写队列消息(只用于队列长度为1的情况)
  • 队列写入消息函数宏定义
#define 函数名	xQueueGenericSend((xQueue),(pvItemToQueue),(xTicksToWait),位置)
//形参:待写入的队列 待写入消息 阻塞超时时间 写入位置
//返回值:pdTRUE队列写入成功 errQUEUE_FULL队列写入失败
  • 队列写入一共有三种位置
#define queueSEND_TO_BACK		((BaseType_t)0)//尾部
#define queueSEND_TO_FRONT		((BaseType_t)1)//头部
#define queueOVERWRITE			((BaseType_t)2)//覆写(队列长度为1)
  • 队列读取消息API函数
xQueueReceive();//从队列头部读取消息,并删除消息
xQueuePeek();//从队列头部读取消息
xQueueReceiveFromISR();//在中断中从队列头部读取消息,并删除消息
xQueuePeekFromISR();//在中断中从队列头部读取消息

BaseType_t xQueueReceive(QueueHandle_t xQueue,void *const pvBuffer,TickType_t xTicksToWait)
//形参:待读取队列 信息读取缓冲区 阻塞超时时间
//返回值:pdTRUE 读取成功 pdFALSE 读取失败
BaseType_t xQueuePeek(QueueHandle_t xQueue,void *const pvBuffer,TickType_t xTicksToWait)
//形参:待读取队列 信息读取缓冲区 阻塞超时时间
//返回值:pdTRUE 读取成功 pdFALSE 读取失败

三、队列操作实验

  • 创建四个任务
  • start_task:创建task1、task2和task3
  • task1:当按键key0或key1按下,将按键键码拷贝到队列key_queue(入队),当key2按下,将传输大数据,拷贝大数据内容到队列big_data_queue
  • task2:读取队列key_queue中的消息(出队),打印出接收的键值
  • task3:从队列big_data_queue读取大数据地址,通过地址访问大数据
#define configSUPPORT_DYNAMIC_ALLOCATION					1//动态创建任务宏定义配置
#define INCLUDE_vTaskSuspend								1//挂起/恢复任务宏定义配置

//start_task参数宏定义
#define	START_TASK_STACK_SIZE 								128//堆栈大小
#define	START_TASK_PRIO										1//任务优先级
TaskHandle_t	start_task_handle;							//任务句柄
//task1参数宏定义
#define	TASK1_STACK_SIZE 									128//堆栈大小
#define	TASK1_PRIO											2//任务优先级
TaskHandle_t	task1_handle;								//任务句柄
//task2参数宏定义
#define	TASK2_STACK_SIZE 									128//堆栈大小
#define	TASK2_PRIO											3//任务优先级
TaskHandle_t	task2_handle;								//任务句柄
//task3参数宏定义
#define	TASK3_STACK_SIZE 									128//堆栈大小
#define	TASK3_PRIO											4//任务优先级
TaskHandle_t	task3_handle;								//任务句柄

QueueHandle_t key_queue;//小数据句柄
QueueHandle_t big_key_queue;//大数据句柄
char buff[] = "hello world";//大数据内容

//task1任务函数:入队操作
void task1( void * pvParameters )
{
		uint8_t KeyNum = 0;
		char *buf;
		buf = buff;//buf指针指向buff首地址
		BaseType_t err = 0;//返回值
		while(1)
		{
			KeyNum = Key_GetNum();
			if(KeyNum==0 || KeyNum==1)//键值写入队列
			{
				err = xQueueSend(key_queue,&KeyNum,portMAX_DELAY);//写入键值到队列中,返回值判断是否写入成功
			}
			else if(KeyNum == 2)//数组内容写入队列
			{
				err = xQueueSend(big_date_queue,&buf,portMAX_DELAY);//写入buf数组内容到队列中,返回值判断是否写入成功
			}
			vTaskDelay(10);//自带延时函数
		}
}
//task2任务函数:读取小数据(出队)
void task2( void * pvParameters )
{
		uint8_t KeyNum = 0;
		BaseType_t err = 0;
		while(1)
		{
			err = xQueueReceive(key_queue,&keyNum,portMAX_DELAY);//出队操作,返回值判断是否读取成功
		}
}
//task3任务函数:读取大数据(出队)
void task3( void * pvParameters )
{
		char *buf;
		BaseType_t err = 0;
		while(1)
		{
			err = xQueueReceive(big_date_queue,&buf,portMAX_DELAY);//出队操作,返回值判断是否读取成功
		}
}
//Start_task任务函数
void Start_task( void * pvParameters )
{
		taskENTER_CRITICAL();//进入临界区
		//创建任务1
		xTaskCreate(task1,//任务函数
					"task1",//任务名称
					TASK1_STACK_SIZE,//堆栈大小/字
					NULL,//入口参数没有
					TASK1_PRIO,//优先级
					&task1_handle//任务句柄
					);
		//创建任务2
		xTaskCreate(task2,//任务函数
					"task2",//任务名称
					TASK2_STACK_SIZE,//堆栈大小/字
					NULL,//入口参数没有
					TASK2_PRIO,//优先级
					&task2_handle//句柄
					);
		//创建任务3
		xTaskCreate(task3,//任务函数
					"task3",//任务名称
					TASK3_STACK_SIZE,//堆栈大小/字
					NULL,//入口参数没有
					TASK3_PRIO,//优先级
					&task3_handle//句柄
					);
		vTaskDelete(start_task_handle);
		//删除自身任务Start_task,start_task_handle或NULL都可以
		taskEXIT_CRITICAL();//退出临界区
}

//FreeRTOS入口函数,程序从此处开始执行
void freertos_demo()
{
		key_queue = xQueueCreate(2,sizeof(uint8_t));//创建小数据队列,2个队列项,按键返回字节,队列创建成功返回句柄,失败返回NULL
		big_date_queue = xQueueCreate(1,sizeof(char*));//创建大数据队列,1个队列项,字符数组首地址,队列创建成功返回句柄,失败返回NULL
		xTaskCreate(Start_task,//任务函数
					"Start_task",//任务名称
					START_TASK_STACK_SIZE,//堆栈大小/字
					NULL,//入口参数没有
					START_TASK_PRIO,//优先级
					&start_task_handle//句柄
					);//创建Start任务
		vTaskStartScheduler();//开启任务调度器,开启执行Start任务,创建task123
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端使用vue点击上传文件,传送给后端,后端进行文件接收

一、效果图 前端页面&#xff1a; 在java这边后端的target文件就可以接收到前端发送的文件&#xff0c;文件可以打开 接下来看具体代码是怎么实现的&#xff01; 二、代码部分 Vue代码 <template> <el-upload ref"upload" class"upload-demo&q…

黑马头条day5- 延迟任务精准发布文章

这个过程主要是流程负责 但是我没有仔细的过所有的流程 需要多刷几遍 今天只是照着md文档执行了一下 运行起来没差错 主要实现文章定时发布 通过schedule模块作为延迟队列的任务 通过redis实现的延迟任务 具体 实现还要在多走几遍流程 逻辑一点不清楚 没看网课 这节要多看几遍…

【最大公约数】

题目 思路 g c d ( x , y ) p x , y ∈ [ 1 , N ] gcd(x, y) p\;\;x,y\in[1,N] gcd(x,y)px,y∈[1,N] 转换为 g c d ( x p , y p ) 1 x p , y p ∈ [ 1 , N p ] gcd(\frac{x}{p}, \frac{y}{p}) 1\;\;\frac{x}{p},\frac{y}{p}\in[1,\frac{N}{p}] gcd(px​,py​)1px​,py​∈…

云栖实录 | 开源大数据全面升级:Native 核心引擎、Serverless 化、湖仓架构引领云上大数据发展

本文根据2024云栖大会实录整理而成&#xff0c;演讲信息如下&#xff1a; 演讲人&#xff1a; 王 峰 | 阿里云智能集团研究员、开源大数据平台负责人 李 钰&#xff5c;阿里云智能集团资深技术专家 范 振&#xff5c;阿里云智能集团高级技术专家 李劲松&#xff5c;阿里云…

Vulnhub靶机:DerpNStink: 1

0x01 项目地址 DerpNStink: 1 0x02 靶机描述 Your goal is to remotely attack the VM and find all 4 flags eventually leading you to full root access. Dont forget to #tryharder 您的目标是远程攻击虚拟机并找到所有 4 个 flag &#xff0c;最终让您获得完全 root 访…

Updates were rejected because the tip of your current branch is behind 的解决方法

1. 问题描述 当我们使用 git push 推送代码出现以下问题时&#xff1a; 2. 原因分析 这个错误提示表明当前本地分支落后于远程分支&#xff0c;因此需要先拉取远程的更改。 3. 解决方法 1、拉取远程更改 在终端中执行以下命令&#xff0c;拉取远程分支的更新并合并到本地…

SpringBoot学习笔记(1)

1.Web技术基础 BS:(Browser/Server,浏览器/服务器架构模式)。C/S架构主要特点是交互性强&#xff0c;具有安全访问模式&#xff0c;网络流量低&#xff0c;响应速度快&#xff0c;因为客户端负责大多数业务逻辑和UI演示&#xff0c;所以也被称为胖客户端&#xff0c;C/S结构的软…

【含文档】基于Springboot+微信小程序 的中心医院用户移动端(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…

学习之什么是生成器

什么是生成器&#xff08;Generator&#xff09; 1、是一种数据类型能源源不断地生成数据 2、"惰性"特点:一次生成一个值&#xff0c;而不是生成一个序列 3、生成器一定是迭代器比迭代器更简洁使用生成器表达式创建生成器 from typing import Generator, Iterator,…

【hot100-java】【柱状图中最大的矩形】

R9-栈篇 面积最大矩形的高度一定是 heights 中的元素 简单解释&#xff0c;就是说&#xff0c;最大高度必然是heights中的一个元素&#xff0c;我们假设是h&#xff0c;然后我们基于h&#xff0c;左右拓展&#xff0c;尽量拓展到h越来越高&#xff08;符合单调栈&#xff09;&a…

7.6透视变换

基本概念 在计算机视觉和图像处理领域中&#xff0c;透视变换&#xff08;Perspective Transformation&#xff09;是一种重要的几何变换&#xff0c;用于模拟从一个视角到另一个视角的变换&#xff0c;比如从鸟瞰视角到正面视角的变换。透视变换通常用于图像配准、增强现实、…

ubuntu报错you don‘t have enough free space in /var/cache/apt/archivers.

使用df -h命令查看&#xff1b; 扩充前&#xff0c;dev/sda2的大小&#xff1a; 使用gparted工具对dev/sda2进行扩容

Steam黑神话悟空禁止更新进入游戏的解决方案

首先打开该网站&#xff1a;https://steamdb.info/app/2358720/ 2358720即为游戏ID 网页下翻&#xff0c;找到更新历史&#xff1a;https://steamdb.info/app/2358720/history/ 然后在Steam的steamapps下&#xff0c;找到后缀为2358720的文件&#xff0c;右击记事本打开 将St…

老照片修复工具有哪些?怎么让老照片焕发新光彩?

在那些泛黄的相框中&#xff0c;珍藏着我们最珍贵的记忆。 岁月流转&#xff0c;照片上的影像逐渐模糊&#xff0c;但那份情感却愈发深刻。 如何让这些老照片恢复往日的光彩&#xff0c;让那些珍贵的瞬间再次清晰呈现&#xff1f; 本文将带你探索老照片修复高清的技巧&#…

SpringMVC源码-SpringMVC框架中Spring父容器和SpringMVC子容器加载的流程以及SpringMVC九大内置组件的初始

一、Spring父容器启动 SpringMVC 的项目结构如下: applicationContext.xml spring的配置文件 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.o…

Spring Boot 进阶-如何自定义SpringBoot日志配置?

在之前的文章中我们介绍了Spring Boot中的日志框架,并且也介绍了SpringBoot日志框架中日志级别的调整。这篇文章我们主要来介绍关于如何让日志框架更加符合我们自己的需求。那么首先我们就来看一下日志文件输出路径的配置。 如何指定日志文件的输出位置 在Spring Boot中日志是…

Keepalived+MySQL 高可用集群

基础架构如下 准备干净的实验环境 [rootmysql1 ~]# systemctl stop firewalld [rootmysql1 ~]# cat /etc/sysconfig/selinux |grep "SELINUXdisabled" SELINUXdisabled [rootmysql1 ~]# setenforce 0 setenforce: SELinux is disabled [rootmysql1 ~…

动静态库(Linux)

文章目录 前言一、静态库二、动态库三、深入理解动态库总结 前言 我们之前用过c语言的库.Linux中默认的都是使用动态库&#xff0c;如果想要使用静态库&#xff0c;就必须加上-static选项。默认都是安装的动态库&#xff0c;系统中一般没有静态库&#xff0c;如果要使用&#…

算法复杂度之时间复杂度

一 . 数据结构前言 1.1 数据结构 数据结构(Data structure) 是计算机存储&#xff0c;组织数据的方式&#xff0c;指互相之间存在一种或多种特定关系的数据元素的集合。没有一种单一的数据结构对所有用途都有用&#xff0c;所以要学习各式各样的数据结构&#xff0c;如&#…

使用kaggle命令下载数据集

目录 报错 解决方案 报错 使用kaggle命令下载数据集报错了&#xff0c; 解决方案 &#xff08;1&#xff09;首先&#xff0c;确保已经安装 Python 和包管理器 pip。 运行以下命令以使用命令行访问 Kaggle API&#xff1a; pip install kaggle 可能需要在 Mac/Linux 上执行…