FreeRTOS学习笔记(六)队列
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、队列的基本内容
- 1.1 队列的引入
- 1.2 FreeRTOS 队列的功能与作用
- 1.3 队列的结构体
- 1.4 队列的使用流程
- 二、相关API详解
- 2.1 xQueueCreate
- 2.2 xQueueSend
- 2.3 xQueueReceive
- 2.4 xQueueSendFromISR
- 2.5 xQueueReceiveFromISR
- 2.6 uxQueueMessagesWaiting
- 2.7 uxQueueSpacesAvailable
- 2.8 vQueueDelete
前言
队列(Queue) 是一种用于任务间通信和同步的重要机制。它允许不同任务或者中断服务例程之间交换数据,而无需直接共享变量。这种机制不仅确保数据在任务之间传递的安全性,还解决了多任务系统中的并发和同步问题。
一、队列的基本内容
1.1 队列的引入
在以前的代码中,如果我们想让一个变量在不同函数中进行传递操作,下意识可能会想到全局变量,但是这种方式存在一个问题:当我们使用freertos时,低优先级的任务会被高优先级的任务打断,这意味着可能会导致变量的结果不可控。为了解决这个问题,我们引入了队列,他自带临界保护,我们只要进行相关的API操作即可。在队列中可以存储固定大小且有限的数据,其中每一个数据叫“队列项目”,而所能存储的最大“队列项目”的数量称为队列的长度。除了可以被多任务访问之外,队列还有以下的特性:
- FreeRTOS 中的队列是先进先出的结构,即最先插入队列的数据会最先被读取;
- 队列的长度和每个队列项的大小在创建时由用户指定;
- FreeRTOS 提供了阻塞模式和非阻塞模式的队列操作。如果任务需要立即返回,可以使用超时为 0 的非阻塞模式;如果任务愿意等待队列有空位或数据,可以设置阻塞时间(如 0~portMAX_DELAY)让任务进入阻塞状态;
- FreeRTOS 中的队列在数据传递时通常会直接拷贝数据进行实值传输,当然也可以传递指针。
1.2 FreeRTOS 队列的功能与作用
- 任务间通信:FreeRTOS 的队列可以让多个任务之间安全地传递数据。例如,一个任务可以向队列发送数据,另一个任务从队列读取数据。这使得不同任务之间可以高效地共享信息,而不需要频繁访问全局变量。
- 任务与中断间通信:队列不仅适用于任务间通信,还适用于中断和任务之间的通信。FreeRTOS 提供了特定的 ISR(中断服务例程)函数,比如 xQueueSendFromISR() 和 xQueueReceiveFromISR(),可以让中断处理函数安全地与任务交换数据。
- 同步与调度:当一个任务尝试从空队列中读取数据时,任务可以选择进入阻塞状态,直到有数据可读。当另一个任务或中断向队列中发送数据时,等待的任务会被唤醒并立即处理数据。这样,队列不仅传递数据,还能用作同步机制,协调任务间的执行顺序。
- 队列引发的任务切换: 在 FreeRTOS 中,如果一个任务向队列发送数据,并唤醒了一个更高优先级的任务,该任务会立刻抢占当前任务进行执行。这使得队列不仅用于数据交换,还起到了一定的任务调度作用。
1.3 队列的结构体
在 FreeRTOS 中,队列是通过一个结构体来实现的。虽然具体实现可能根据不同平台有所调整,但通常队列的结构体包含了队列长度、队列项大小、存储数据的缓冲区指针、队列的头尾指针、队列的同步机制(如等待队列的任务列表)等信息。在 FreeRTOS 的源码中,定义队列的结构体一般为 QueueDefinition,其在 queue.c 中实现,通常通过类型定义 QueueHandle_t 来间接引用该结构体。
struct QueueDefinition
{int8_t *pcHead; /* 指向队列存储区的指针(队列缓冲区的头部) */int8_t *pcTail; /* 指向队列存储区的尾部 */int8_t *pcWriteTo; /* 指向队列中下一个写入位置 */int8_t *pcReadFrom; /* 指向队列中下一个读取位置 */UBaseType_t uxMessagesWaiting; /* 队列中的消息数 */UBaseType_t uxLength; /* 队列的长度(队列项的最大数量) */UBaseType_t uxItemSize; /* 每个队列项的大小(以字节为单位) */TaskHandle_t xTasksWaitingToSend; /* 等待发送的任务列表 */TaskHandle_t xTasksWaitingToReceive;/* 等待接收的任务列表 *//* 下面的成员用于同步多任务或中断访问队列 */BaseType_t xRxLock; /* 接收锁,用于控制接收操作 */BaseType_t xTxLock; /* 发送锁,用于控制发送操作 *//* Mutexes 和 Semaphores 使用的额外信息 */UBaseType_t uxQueueType; /* 队列的类型(普通队列、互斥量、信号量等) */...
} xQUEQUE;
值得一提的是,这个结构体中还包含了一个联合体,它的作用是允许 QueueDefinition 结构体根据队列类型的不同(普通消息队列、信号量、互斥量)共享不同的结构。具体而言:对于普通的消息队列,队列用 xQueue 这个结构来管理等待发送和等待接收的任务列表;对于互斥量,队列使用 xMutex 这个结构来管理递归计数和互斥量的持有者。通过这个联合体,队列的结构体可以根据不同的队列类型选择不同的字段来使用,从而节省内存,并让队列既能处理消息队列,也能处理信号量和互斥量。
/* 通过联合体实现不同类型队列的支持 */union{/* 用于消息队列和信号量 */struct{UBaseType_t uxRecursiveCallCount; /* 递归互斥量使用时的递归计数 */TaskHandle_t xMutexHolder; /* 持有互斥量的任务句柄 */} xMutex;/* 用于普通队列 */struct{List_t xTasksWaitingToSend; /* 等待发送的任务列表 */List_t xTasksWaitingToReceive; /* 等待接收的任务列表 */} xQueue;} u; /* 联合体名称 */
参数说明:
- uxRecursiveCallCount 用于递归互斥量的递归调用计数,这样持有互斥量的任务可以多次锁定互斥量。
- xMutexHolder 用于保存当前持有互斥量的任务句柄。
1.4 队列的使用流程
- 创建队列:可以指定队列的长度和每个队列项的大小(例如,传递一个整数,结构体,或者更复杂的数据)。
- 向队列发送数据:一个任务可以使用 xQueueSend() 或 xQueueSendToBack() 向队列中发送数据,如果队列已满,任务可以选择进入阻塞状态,直到队列有空位,或者直接返回发送失败。
- 从队列读取数据:任务可以使用 xQueueReceive() 从队列中读取数据,如果队列为空,任务可以选择阻塞,直到有数据可读取。
- 中断安全的队列操作:如果队列操作发生在中断服务例程中,FreeRTOS 提供了 xQueueSendFromISR() 和 xQueueReceiveFromISR() 等函数,以确保队列操作的线程安全。
二、相关API详解
FreeRTOS 提供了丰富的队列相关 API,用于在任务之间或中断和任务之间传递数据,进行任务同步。队列机制是 FreeRTOS 中最常用的 IPC(进程间通信)工具之一。以下是一些常用的队列 API 及其功能介绍:
2.1 xQueueCreate
// 功能:创建一个新的队列,并返回该队列的句柄。
QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
- 参数:
- uxQueueLength:队列中可以容纳的最大数据项数
- uxItemSize:每个队列项的大小(以字节为单位)
- 返回值:
- 成功:队列句柄
- 失败:NULL
这里简单提一下,xQueueCreate的实现是调用了xQueueGenericCreate这个的底层函数,所有的队列(包括普通队列、信号量、互斥量)都通过这个函数创建。通常我们不会直接调用 xQueueGenericCreate,而是使用更高层的 API,如 xQueueCreate、xSemaphoreCreate 等。
QueueHandle_t xQueueGenericCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize, uint8_t ucQueueType);
- 参数说明
- uxQueueLength:队列的长度,即队列中可以容纳的最大数据项数。
- uxItemSize:每个队列项的大小(以字节为单位)。如果创建的是信号量或互斥量,这个值为 0。
- ucQueueType:队列的类型,常见的类型有:
- queueQUEUE_TYPE_BASE:普通队列
- queueQUEUE_TYPE_SET:队列集
- queueQUEUE_TYPE_MUTEX:互斥量
- queueQUEUE_TYPE_BINARY_SEMAPHORE:二元信号量
- queueQUEUE_TYPE_COUNTING_SEMAPHORE:计数信号量
- 返回值
- 成功:创建的队列的句柄
- 失败:返回 NULL
2.2 xQueueSend
// 功能 :将一个项目发送到队列中,如果队列满,任务将阻塞直到有空间可用或超时(不可应用于中断)
BaseType_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait);
- 参数:
- xQueue:队列的句柄
- pvItemToQueue:指向要放入队列的数据项的指针
- xTicksToWait:如果队列满,任务等待插入的时间(以 Tick 数表示),portMAX_DELAY 表示无限等待
- 返回值:
- 成功:pdPASS
- 失败:errQUEUE_FULL(队列已满)
2.3 xQueueReceive
// 功能:从队列中接收一个项目,如果队列为空,任务将阻塞直到有数据可用或超时。
BaseType_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);
- 参数:
- xQueue:队列的句柄
- pvBuffer:指向接收数据项的缓冲区
- xTicksToWait:如果队列为空,任务等待接收的时间(以 Tick 数表示),portMAX_DELAY 表示无限等待
- 返回值:
- 成功:pdPASS
- 失败:errQUEUE_EMPTY(队列为空)
2.4 xQueueSendFromISR
// 功能:从中断服务例程(ISR)中向队列发送数据,与 xQueueSend 类似,但适用于中断上下文。
BaseType_t xQueueSendFromISR(QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken);
- 参数:
- xQueue:队列的句柄
- pvItemToQueue:指向要放入队列的数据项的指针
- pxHigherPriorityTaskWoken:如果发送数据后需要进行任务切换,设置为 pdTRUE
- 返回值:
- 成功:pdPASS
- 失败: errQUEUE_FULL
2.5 xQueueReceiveFromISR
// 功能:从中断服务例程(ISR)中接收队列数据。与 xQueueReceive 类似,但适用于中断上下文。
BaseType_t xQueueReceiveFromISR(QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxHigherPriorityTaskWoken);
- 参数:
- xQueue:队列的句柄。
- pvBuffer:指向接收数据项的缓冲区。
- pxHigherPriorityTaskWoken:如果接收数据后需要进行任务切换,设置为 pdTRUE。
- 返回值:
- 成功:pdPASS
- 失败:errQUEUE_EMPTY
2.6 uxQueueMessagesWaiting
// 功能:返回队列中当前存储的消息数。
UBaseType_t uxQueueMessagesWaiting(QueueHandle_t xQueue);
- 参数:
- xQueue:队列的句柄
- 返回值:队列中已存储的消息数
2.7 uxQueueSpacesAvailable
// 功能:返回队列中剩余可用的空间数。
UBaseType_t uxQueueSpacesAvailable(QueueHandle_t xQueue);
- 参数:
- xQueue:队列的句柄。
- 返回值:队列中剩余的可用空间数量
2.8 vQueueDelete
// 功能:删除队列并释放其占用的内存。
void vQueueDelete(QueueHandle_t xQueue);
- 参数:
- xQueue:要删除的队列句柄
免责声明:本文参考了网上公开资料,仅用于学习交流,若有错误或侵权请联系笔者。
相关文章:
FreeRTOS学习笔记(六)队列
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、队列的基本内容1.1 队列的引入1.2 FreeRTOS 队列的功能与作用1.3 队列的结构体1.4 队列的使用流程 二、相关API详解2.1 xQueueCreate2.2 xQueueSend2.3 xQu…...
【Python篇】PyQt5 超详细教程——由入门到精通(中篇一)
文章目录 PyQt5入门级超详细教程前言第4部分:事件处理与信号槽机制4.1 什么是信号与槽?4.2 信号与槽的基本用法4.3 信号与槽的基础示例代码详解: 4.4 处理不同的信号代码详解: 4.5 自定义信号与槽代码详解: 4.6 信号槽…...
LinuxQt下的一些坑之一
我们在使用Qt开发时,经常会遇到Windows上应用正常,但到Linux嵌入式下就会出现莫名奇妙的问题。这篇文章就举例分析下: 1.QPushButton按钮外侧虚线框问题 Windows下QPushButton按钮设置样式正常,但到了Linux下就会有一个虚线边框。…...
Statement batch
我们可以看到 Statement 和 PreparedStatement 为我们提供的批次执行 sql 操作 JDBC 引入上述 batch 功能的主要目的,是加快对客户端SQL的执行和响应速度,并进而提高数据库整体并发度,而 jdbc batch 能够提高对客户端SQL的执行和响应速度,其…...
PPP 、PPPoE 浅析和配置示例
一、名词: PPP: Point to Point Protocol 点到点协议 LCP:Link Control Protocol 链路控制协议 NCP:Network Control Protocol 网络控制协议,对于上层协议的支持,N 可以为IPv4、IPv6…...
【Python机器学习】词向量推理——词向量
目录 面向向量的推理 使用词向量的更多原因 如何计算Word2vec表示 skip-gram方法 什么是softmax 神经网络如何学习向量表示 用线性代数检索词向量 连续词袋方法 skip-gram和CBOW:什么时候用哪种方法 word2vec计算技巧 高频2-gram 高频词条降采样 负采样…...
Python 语法糖:让编程更简单(续二)
Python 语法糖:让编程更简单(续) 10. Type hints Type hints 是 Python 中的一种语法糖,用于指定函数或变量的类型。例如: def greet(name: str) -> None:print(f"Hello, {name}!")这段代码将定义一个…...
6 - Shell编程之sed与awk编辑器
目录 一、sed 1.概述 2.sed命令格式 3.常用操作的语法演示 3.1 输出符合条件的文本 3.2 删除符合条件的文本 3.3 替换符合条件的文本 3.4 插入新行 二、awk 1.概述 2. awk命令格式 3.awk工作过程 4.awk内置变量 5.awk用法示例 5.1 按行输出文本 5.2 按字段输出文…...
什么是XML文件,以及如何打开和转换为其他文件格式
本文描述了什么是XML文件以及它们在哪里使用,哪些程序可以打开XML文件,以及如何将XML文件转换为另一种基于文本的格式,如JSON、PDF或CSV。 什么是XML文件 XML文件是一种可扩展标记语言文件。它们是纯文本文件,除了描述数据的传输、结构和存储外,本身什么也不做。 RSS提…...
海外直播对网速、带宽、安全的要求
要满足海外直播的要求,需要拥有合适的网络配置。在全球化的浪潮下,海外直播正逐渐成为企业、个人和各类组织的重要工具。不论是用于市场推广、品牌宣传,还是与观众互动,海外直播都为参与者带来了丰富的机会。然而,确保…...
UWB定位室外基站
定位基站,型号SW,是一款基于无线脉冲技术开发的UWB定位基站,基站可用于人员、车辆、物资的精确定位, 该基站专为恶劣环境使用而设计,防尘、防水等级IP67,工业级标准支持365天连续运行,本安防爆可…...
高斯平面直角坐标讲解,以及地理坐标转换高斯平面直角坐标
高斯平面直角坐标系(Gauss-Krger 坐标系)是基于 高斯-克吕格投影 的一种常见的平面坐标系统,主要用于地理信息系统 (GIS)、测绘和工程等领域。该坐标系将地球表面的经纬度(地理坐标)通过一种投影方式转换为平面直角坐标,以便在二维平面中进行距离、面积和角度的计算。 一…...
C++入门(06)安装QT并快速测试体验一个简单的C++GUI项目
文章目录 1. 清华镜像源下载2. 安装3. 开始菜单上的 QT 工具4. 打开 Qt Creator5. 简单的 GUI C 项目5.1 打开 Qt Creator 并创建新项目5.2 设计界面5.3 添加按钮的点击事件5.4 编译并运行项目 6. 信号和槽(Signals and Slots) 这里用到了C类与对象的很多…...
一篇文章告诉你小程序为什么最近这么火?
微信小程序之所以最近这么火,主要得益于其低成本获取高流量、线上线下流量互换、社交裂变引爆流量以及封闭商业生态闭环等优势。下面将详细探讨小程序火爆的多个原因: 一篇文章告诉你小程序为什么这么火爆? 低成本获取高流量 无需安装注册&…...
Qt-常用控件(3)-多元素控件、容器类控件和布局管理器
1. 多元素控件 Qt 中提供的多元素控件有: QListWidgetQListViewQTableWidgetQTableViewQTreeWidgetQTreeView xxWidget 和 xxView 之间的区别,以 QTableWidget 和 QTableView 为例. QTableView 是基于 MVC 设计的控件.QTableView 自身不持有数据,使用 QTableView 的…...
【系统设计】主动查询与主动推送:如何选择合适的数据传输策略
基本描述总结 主动查询机制:系统A主动向系统B请求数据,采用严格的权限控制和身份认证,防止未授权的数据访问。数据在传输过程中使用TLS加密,并通过动态脱敏处理隐藏敏感信息。 推送机制:系统B在数据更新时主动向系统…...
mac 安装brew并配置国内源
前置条件 - Xcode 命令行工具 一行代码安装Homebrew 添加到路径(PATH) - zsh shell为例 背景介绍 最近重装了我的MAC mini (m1 芯片), 很多软件都需要重新安装,因为后续还需要安装一些软件,所以想着安装个包管理软件 什么…...
Temu官方宣导务必将所有的点位材料进行检测-RSL资质检测
关于饰品类产品合规问题宣导: 产品法规RSL要求 RSL测试是根据REACH法规及附录17的要求进行测试。REACH法规是欧洲一项重要的法规,其中包含许多对化学物质进行限制的规定和高度关注物质。 为了确保珠宝首饰的安全性,欧盟REACH法规规定&#…...
mysql高级sql
文章目录 一,查询1.按关键字排序1.1按关键字排序操作(1)按分数排序查询(不加asc默认为升序)(2)按分数降序查询(DESC)(3)使用where进行条件查询(4)使用ORDER BY语句对多个字段排序 1.2使用区间判断查询(and/…...
Linux CentOS 7.9 安装mysql8
1、新建mysql文件夹 数据比较大,所以我在服务器另外挂了一个盘装mysql,和默认安装一个道理,换路径即可 cd ../ //创建文件夹 mkdir mysql //进入mysql文件夹 cd mysql 2、下载mysql8.0安装包并解压、重命名 //下载安装包 wget https://dev…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...
