大姨吗网站,修改wordpress rss,做网站网上怎么挂公告,网站建设费用计算依据提示#xff1a;文章写完后#xff0c;目录可以自动生成#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、队列的基本内容1.1 队列的引入1.2 FreeRTOS 队列的功能与作用1.3 队列的结构体1.4 队列的使用流程 二、相关API详解2.1 xQueueCreate2.2 xQueueSend2.3 xQu… 提示文章写完后目录可以自动生成如何生成可参考右边的帮助文档 文章目录 前言一、队列的基本内容1.1 队列的引入1.2 FreeRTOS 队列的功能与作用1.3 队列的结构体1.4 队列的使用流程 二、相关API详解2.1 xQueueCreate2.2 xQueueSend2.3 xQueueReceive2.4 xQueueSendFromISR2.5 xQueueReceiveFromISR2.6 uxQueueMessagesWaiting2.7 uxQueueSpacesAvailable2.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要删除的队列句柄
免责声明本文参考了网上公开资料仅用于学习交流若有错误或侵权请联系笔者。