文章目录
- 队列 API
- 头文件
- • freertos/include/freertos/queue.h
- 函数
- xQueueGenericSendFromISR
- xQueueGiveFromISR
- xQueueGenericSend
- xQueuePeek
- xQueuePeekFromISR
- xQueueReceive
- uxQueueMessagesWaiting
- uxQueueSpacesAvailable
- vQueueDelete
- xQueueReceiveFromISR
- xQueueIsQueueEmptyFromISR
- xQueueIsQueueFullFromISR
- uxQueueMessagesWaitingFromISR
- vQueueAddToRegistry
- vQueueUnregisterQueue
- pcQueueGetName
- xQueueGenericCreate
- xQueueGenericCreateStatic
- xQueueCreateSet
- xQueueAddToSet
- xQueueRemoveFromSet
- xQueueSelectFromSet
- xQueueSelectFromSetFromISR
- 宏
- xQueueCreate
- xQueueCreateStatic
- xQueueSendToFront
- xQueueSendToBack
- xQueueSend
- xQueueOverwrite
- xQueueSendToFrontFromISR
- xQueueSendToBackFromISR
- xQueueOverwriteFromISR
- xQueueSendFromISR
- xQueueReset
队列 API
头文件
• freertos/include/freertos/queue.h
函数
xQueueGenericSendFromISR
BaseType_t xQueueGenericSendFromISR(QueueHandle_t xQueue,
const void *const pvItemToQueue,
BaseType_t *const pxHigherPriorityTaskWoken,
const BaseType_t xCopyPosition)
优选使用宏xQueueSendFromISR()、 xQueueSendToFrontFromISR()和 xQueueSendToBackFromISR()来代替直接调用该函数。
xQueueGiveFromISR()相当于那些实际上不复制任何数据的信号量的使用。
在队列上发布一个项目。在中断服务例行程中使用此函数是安全的。
项目由副本排队,而不是引用,所以最好只排队小项目,特别是当从ISR调用时。
在大多数情况下,最好存储一个指向正在排队的项目的指针。
Return 如果数据已成功发送到队列,则为pdTRUE,否则为errQUEUE_FULL。
Parameters
• xQueue: 要发布项目的队列的句柄。
• pvItemToQueue: 指向要放置在队列中的项目的指针。在创建队列时定义了队列将保留的项的大小,因此这许多字节将从pvItemToQueue复制到队列存储区域中。
• [out] pxHigherPriorityTaskWoken: 如果发送到队列导致任务解除阻塞,并且解除阻塞的任务的优先级高于当前运行的任务, xQueueGenericSendFromISR()将pxHigherPriorityTaskWoken设置为pdTRUE。
如果xQueueGenericSendFromISR()将此值设置为pdTRUE,那么应该在退出中断之前请求一个上下文切换。
• xCopyPosition: 可以取值queueSEND_TO_BACK将项目放在队列后面,或者queueSEND_TO_FRONT将项目放在队列前面(对于高优先级消息)。
缓冲IO的使用示例(其中ISR每次调用可以获得多个值):
void vBufferISR( void )
{
char cIn;
BaseType_t xHigherPriorityTaskWokenByPost;
// 我们在ISR开始时还没有唤醒任何任务。
xHigherPriorityTaskWokenByPost = pdFALSE;
// 循环,直到缓冲区为空。
do
{
// 从缓冲区中获得一个字节。
cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
// 发布每个字节。
xQueueGenericSendFromISR( xRxQueue,
&cIn,
&HigherPriorityTaskWokenByPost,
queueSEND_TO_BACK );
} while( portINPUT_BYTE( BUFFER_COUNT ) );
// 现在缓冲区是空的,我们可以在必要时切换上下文。
// 请注意,所需的生成函数的名称是特定于端口的。
if( xHigherPriorityTaskWokenByPost )
{
taskYIELD_YIELD_FROM_ISR();
}
}
xQueueGiveFromISR
BaseType_t xQueueGiveFromISR(QueueHandle_t xQueue,
BaseType_t *const pxHigherPriorityTaskWoken)
xQueueGenericSend
BaseType_t xQueueGenericSend(QueueHandle_t xQueue,
const void *const pvItemToQueue,
TickType_t xTicksToWait,
const BaseType_t xCopyPosition)
首选使用宏xQueueSend()、xQueueSendToFront()和xQueueSendToBack()来代替直接调用此函数。
在队列上发布一个项目。该项目是通过副本来排队的,而不是通过引用来排队的。
不能从中断服务例程中调用此函数。有关ISR中使用的替代方案,请参阅xQueueSendFromISR()。
Return 如果项目已成功发布,则为pdTRUE,否则为errQUEUE_FULL。
Parameters
• xQueue: 要发布项目的队列的句柄。
• pvItemToQueue: 指向要放置在队列中的项目的指针。在创建队列时定义了队列将保留的项的大小,因此这许多字节将从pvItemToQueue复制到队列存储区域中。
• xTicksToWait: 如果队列已满,任务应阻塞等待空间可用的最长时间。
如果将其设置为0且队列已满,则调用将立即返回。
时间在滴答周期中定义,因此如果需要,应使用常数portTICK_PERIOD_MS转换为实时。
• xCopyPosition: 可以取值queueSEND_TO_BACK将项目放在队列后面,或者queueSEND_TO_FRONT将项目放在队列前面(对于高优先级消息)。
示例用法:
struct AMessage
{
char ucMessageID;
char ucData[ 20 ];
} xMessage;
uint32_t ulVar = 10UL;
void vATask( void *pvParameters )
{
QueueHandle_t xQueue1, xQueue2;
struct AMessage *pxMessage;
// 创建一个能够包含10个uint32_t值的队列。
xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
// 创建一个能够包含10个指向AMessage结构的指针的队列。
// 这些数据应该通过指针传递,因为它们包含了大量的数据。
xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
// ...
if( xQueue1 != 0 )
{
// 发送一个uint32_t。如有必要,等待10个滴答。
if( xQueueGenericSend( xQueue1,
( void * ) &ulVar,
( TickType_t ) 10,
queueSEND_TO_BACK ) != pdPASS )
{
// 即使在10滴答之后,也无法发出消息。
}
}
if( xQueue2 != 0 )
{
// 发送指向结构AMessage对象的指针。如果队列已满,则不要阻塞。
pxMessage = & xMessage;
xQueueGenericSend( xQueue2,
( void * ) &pxMessage,
( TickType_t ) 0,
queueSEND_TO_BACK );
}
// ... 其余的任务代码。
}
xQueuePeek
BaseType_t xQueuePeek(QueueHandle_t xQueue,
void *const pvBuffer,
TickType_t xTicksToWait)
从队列中接收项目,而不从队列中删除该项目。
该项目通过副本接收,因此必须提供足够大小的缓冲区。
在创建队列时定义了复制到缓冲区中的字节数。
成功接收的项目仍在队列中,因此将通过下次调用或调用xQueueReceive()再次返回。
不能在中断服务例程中使用此宏。有关可以从中断服务例程中调用的替代方案,请参见xQueuePeekFromISR()。
Return 如果已从队列成功接收到项目,则为pdTRUE,否则为pdFALSE。
Parameters
• xQueue: 要接收项目的队列的句柄。
• pvBuffer: 指向接收项目复制到的缓冲区的指针。
• xTicksToWait: 如果调用时队列为空,任务应阻塞等待项目接收的最长时间量。
时间在滴答周期中定义,因此如果需要,应使用常数portTICK_PERIOD_MS转换为实时。
如果xTicksToWait为0,xQueuePeek()将立即返回。
示例用法:
struct AMessage
{
char ucMessageID;
char ucData[ 20 ];
} xMessage;
QueueHandle_t xQueue;
// 创建队列并发布值的任务。
void vATask( void *pvParameters )
{
struct AMessage *pxMessage;
// 创建一个能够包含10个指向AMessage结构的指针的队列。
// 这些数据应该通过指针传递,因为它们包含了大量的数据。
xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
if( xQueue == 0 )
{
// 无法创建该队列。
}
// ...
// 发送指向结构AMessage对象的指针。如果队列已满,则不要阻塞。
pxMessage = &xMessage;
xQueueSend( xQueue,
( void * ) &pxMessage,
( TickType_t ) 0 );
// ... Rest of task code.
}
// 执行从队列中查看数据的任务。
void vADifferentTask( void *pvParameters )
{
struct AMessage *pxRxedMessage;
if( xQueue != 0 )
{
// 请查看已创建的队列上的消息。如果有一条消息不能立即可用,则阻塞10个ticks。
if( xQueuePeek( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
{
// pcRxedMessage现在指向vATask发布的结构AMessage变量,但该项仍保留在队列中。
}
}
// ... 其余的任务代码。
}
xQueuePeekFromISR
BaseType_t xQueuePeekFromISR(QueueHandle_t xQueue,
void *const pvBuffer)
可以从中断服务(ISR)中调用的xQueuePeek()的一个版本。
从队列中接收项目,而不从队列中删除该项目。
该项目通过副本接收,因此必须提供足够大小的缓冲区。
在创建队列时定义了复制到缓冲区中的字节数。
成功接收的项目仍在队列中,因此将通过下次调用或调用xQueueReceive()再次返回。
Return 如果已从队列成功接收到项目,则为pdTRUE,否则为pdFALSE。
Parameters
• xQueue: 要接收项目的队列的句柄。
• pvBuffer: 指向接收项目复制到的缓冲区的指针。
xQueueReceive
BaseType_t xQueueReceive(QueueHandle_t xQueue,
void *const pvBuffer,
TickType_t xTicksToWait)
从队列中接收一个项目。该项目通过副本接收,因此必须提供足够大小的缓冲区。
在创建队列时定义了复制到缓冲区中的字节数。
成功接收到的项目会在队列中删除。
此函数不能在中断服务例行程序中使用。请参见xQueueReceiveFromISR。
Return 如果已从队列成功接收到项目,则为pdTRUE,否则为pdFALSE。
Parameters
• xQueue: 要接收项目的队列的句柄。
• pvBuffer: 指向接收项目复制到的缓冲区的指针。
• xTicksToWait: 如果调用时队列为空,任务应阻塞等待项目接收的最长时间量。
如果xTicksToWait为0,xQueueReceive()将立即返回。
时间在滴答周期中定义,因此如果需要,应使用常数portTICK_PERIOD_MS转换为实时。
示例用法:
struct AMessage
{
char ucMessageID;
char ucData[ 20 ];
} xMessage;
QueueHandle_t xQueue;
// 创建队列并发布值的任务。
void vATask( void *pvParameters )
{
struct AMessage *pxMessage;
// 创建一个能够包含10个指向AMessage结构的指针的队列。这些数据应该通过指针传递,因为它们包含了大量的数据。
xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
if( xQueue == 0 )
{
// 无法创建该队列。
}
// ...
// 发送指向结构AMessage对象的指针。如果队列已满,则不要阻止。
pxMessage = & xMessage;
xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
// ... 其余的任务代码。
}
// 要从队列中接收的任务。
void vADifferentTask( void *pvParameters )
{
struct AMessage *pxRxedMessage;
if( xQueue != 0 )
{
// 接收已创建的队列上的消息。如果有一条消息不能立即可用,则阻止10个ticks。
if( xQueueReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
{
// pcRxedMessage现在指向vatask发布的结构AMessage变量。
}
}
// ... 其余的任务代码。
}
uxQueueMessagesWaiting
UBaseType_t uxQueueMessagesWaiting(const QueueHandle_t xQueue)
返回存储在队列中的消息数。
Return 队列中可用的消息数
Parameters
• xQueue: 对被查询的队列的一个句柄。
uxQueueSpacesAvailable
UBaseType_t uxQueueSpacesAvailable(const QueueHandle_t xQueue)
返回队列中可用的可用空间数。
这等于如果未删除任何项目,则在队列变满之前可以发送到队列的项目数量。
Return 队列中可用的空间数。
Parameters
• xQueue: 对被查询的队列的一个句柄。
vQueueDelete
void vQueueDelete(QueueHandle_t xQueue)
删除队列,释放为存储队列中的项目分配的所有内存。
Parameters
• xQueue: 对被查询的队列的一个句柄。
xQueueReceiveFromISR
BaseType_t xQueueReceiveFromISR(QueueHandle_t xQueue,
void *const pvBuffer,
BaseType_t *const pxHigherPriorityTaskWoken)
从队列中接收一个项目。在中断服务中使用此函数是安全的。
Return 如果已从队列成功接收到项目,则为pdTRUE,否则为pdFALSE。
Parameters
• xQueue: 要接收项目的队列的句柄。
• pvBuffer: 指向接收项目复制到的缓冲区的指针。
• [out] pxHigherPriorityTaskWoken: 任务可能被阻塞,等待队列中的空间可用。
如果xQueueReceiveFromISR()导致这样的任务解除阻塞*pxTaskWoken将设置为pdTRUE,否则*pxTaskWoken将保持不变。
xQueueIsQueueEmptyFromISR
BaseType_t xQueueIsQueueEmptyFromISR(const QueueHandle_t xQueue)
xQueueIsQueueFullFromISR
BaseType_t xQueueIsQueueFullFromISR(const QueueHandle_t xQueue)
uxQueueMessagesWaitingFromISR
UBaseType_t uxQueueMessagesWaitingFromISR(const QueueHandle_t xQueue)
vQueueAddToRegistry
void vQueueAddToRegistry(QueueHandle_t xQueue,
const char *pcQueueName)
该注册表是作为内核感知调试器找到队列、信号和互文的一种方法。
如果您希望该句柄可用于具有内核感知功能的调试器,调用vQueueAddToRegistry()可向注册表中添加队列、信号量或互斥体句柄。
如果不使用具有内核感知的调试器,则可以忽略此函数。
configQUEUE_REGISTRY_SIZE定义了注册表可容纳的最大句柄数。
在FreeRTOSConfig.h内,configQUEUE_REGISTRY_SIZE必须大于0,注册表可用。
它的值不会影响可以创建的队列、信号量和互文的数量——只是注册表可以保存的数量。
Parameters
• xQueue: 要添加到注册表中的队列的句柄。这是调用xQueueCreate()时返回的句柄。信号量和互斥体句柄也可以在这里传递。
• pcQueueName: 要与该句柄关联的名称。
这是内核感知调试器将显示的名称。
队列注册表只存储指向字符串的指针,因此字符串必须是持久的(全局的或最好在ROM/Flash中),而不是在堆栈上。
vQueueUnregisterQueue
void vQueueUnregisterQueue(QueueHandle_t xQueue)
仅允许对字符串和单个字符使用不限定的字符类型。
该注册表是作为内核感知调试器定位队列、信号和互文的一种方法。
如果您希望该句柄可用于具有内核感知的调试器,以及vQueueUnregisterQueue()可以从寄存器中删除该队列、信号量或互斥锁,调用vQueueAddToRegistry()可向注册表中添加队列、信号量或互斥体句柄。
如果不使用具有内核感知的调试器,则可以忽略此函数。
Parameters
• xQueue: 正在从注册表中删除的队列的句柄。
pcQueueGetName
const char *pcQueueGetName(QueueHandle_t xQueue)
队列注册表是作为内核感知调试器定位队列、语量和互文的一种方法。
调用pcQueueGetName()以查找并从队列句柄返回队列注册表中的队列名称。
Return 如果队列在注册表中,则返回指向队列名称的指针。如果该队列不在注册表中,则返回NULL。
Parameters
• xQueue: 将返回其名称的队列的句柄。
xQueueGenericCreate
QueueHandle_t xQueueGenericCreate(const UBaseType_t uxQueueLength,
const UBaseType_t uxItemSize,
const uint8_t ucQueueType)
仅允许对字符串和单个字符使用不限定的字符类型。
用于使用动态内存分配创建队列的函数的通用版本。
这被其他创建使用队列结构作为基础的其他RTOS对象的函数和宏调用。
xQueueGenericCreateStatic
QueueHandle_t xQueueGenericCreateStatic(const UBaseType_t uxQueueLength,
const UBaseType_t uxItemSize,
uint8_t *pucQueueStorage,
StaticQueue_t *pxStaticQueue,
const uint8_t ucQueueType)
用于使用动态内存分配创建队列的函数的通用版本。
这被其他创建使用队列结构作为基础的RTOS对象的其他函数和宏调用
xQueueCreateSet
QueueSetHandle_t xQueueCreateSet(const UBaseType_t uxEventQueueLength)
队列提供了一种机制,以允许一个任务同时对来自多个队列或信号量的读取操作进行阻塞(挂起)。
有关使用此函数的示例,请参见FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c
必须使用对xQueueCreateSet()的调用显式创建队列,然后才能使用。
创建后,可以使用调用xQueueAddToSet(),将标准的FreeRTOS队列和信号量添加到集合中。
然后,xQueueSelectFromSet()确定集中包含的队列或信号量处于队列读取或信号量执行操作的状态。
注1:请参阅http://wwwFreeRTOS.org/RTOS-queue-sets.html上的文档,以了解为什么在实践中很少需要队列集,因为有更简单的方法来阻塞多个对象。
注2:阻塞包含互斥体的队列集将不会导致互斥体保持器继承被阻止的任务的优先级。
注3:添加到队列集的每个队列中的每个空间都需要另外4个字节的RAM。因此,不应将最大值的计数信号量添加到队列集。
注4:不能对队列集的成员执行接收(对于队列)或接收操作,除非调用xQueueSelect()首先向该集合成员返回了句柄。
Return 如果成功创建队列集,则返回已创建的队列集的句柄。否则,将返回NULL。
Parameters
• uxEventQueueLength: 队列集存储发生在该集中包含的队列和信号上的事件。
uxEventQueueLength指定可以一次排队的最大事件数。
为了绝对确定事件不会丢失,uxEventQueueLength应该设置为添加到集合的队列长度的总和,其中二进制语量和互文的长度为1,而计数语量的长度由其最大计数值设置。
示例:
-如果队列集保留长度为5的队列、另一个长度为12的队列和二进制信号量,则uxEventQueueLength应设置为(5+12+1)或18。
-如果队列集包含三个二进制语量,则uxEventQueueLength应设置为(1+1+1)或3。
-如果队列集包含最大计数为5的计数信号量,而最大计数为3的计数信号量为3,则uxEventQueueLength应设置为(5+3)或8。
xQueueAddToSet
BaseType_t xQueueAddToSet(QueueSetMemberHandle_t xQueueOrSemaphore,
QueueSetHandle_t xQueueSet)
将队列或信号量添加到以前通过调用xQueueCreateSet()而创建的队列集中。
See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this function.
注1:不能对队列集的成员执行接收(对于队列)或接收操作,除非调用xQueueSelectFromSet()首先向该集合成员返回了句柄。
Return 如果队列或信号量已成功添加到队列集,则返回pdPASS。
如果由于该队列已添加到其他队列集的成员,因此无法成功添加到该队列集,则返回pdFAIL。
Parameters
• xQueueOrSemaphore: 要添加到队列集的队列或信号量的句柄(强制转换为QueueSetMemberHandle_t类型)。
• xQueueSet: 正在将该队列或信号量添加到的队列集的句柄。
xQueueRemoveFromSet
BaseType_t xQueueRemoveFromSet(QueueSetMemberHandle_t xQueueOrSemaphore,
QueueSetHandle_t xQueueSet)
从一个队列集中删除一个队列或信号量。只有当该队列或信号量为空时,才能从集合中删除该队列或信号量。
See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this function.
Return 如果从队列集中成功将队列或信号量删除,则返回pdPASS。
如果该队列不在该队列集中,或者该队列(或信号量)不为空,则返回pdFAIL。
Parameters
• xQueueOrSemaphore: 正在从队列集中删除的队列或信号量的句柄(强制转换为QueueSetMemberHandle_t类型)。
• xQueueSet: 包含该队列或信号量的队列集的句柄。
xQueueSelectFromSet
QueueSetMemberHandle_t xQueueSelectFromSet(QueueSetHandle_t xQueueSet,
const TickType_t xTicksToWait)
xQueueSelectFromSet()从队列集的成员中选择队列或包含数据(对于队列)或可供获取的(对于信号量)的信号量。
xQueueSelectFromSet()有效地允许任务同时阻塞队列集中所有队列和信号量的读取操作。
有关使用此函数的示例,请参见FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c。
注1:请参阅http://wwwFreeRTOS.org/RTOS-queue-sets.html上的文档,以了解为什么在实践中很少需要队列集,因为有更简单的方法来阻塞多个对象。
注2:阻止包含互斥体的队列集将不会导致互斥体保持器继承被阻止的任务的优先级。
注3:不能对队列集的成员执行接收(对于队列)或接收操作,除非调用xQueueSelect()首先向该集合成员返回了句柄。
Return xQueueSelectFromSet()将返回包含数据的队列集中包含的队列(转换为QueueSetMemberHandle_t类型)的句柄或包含的队列集的句柄(转换为QueueSetMemberHandle_t类型),或者如果在指定的块时间到期之前没有该队列或信号量,则返回NULL。
Parameters
• xQueueSet: 任务将(可能)阻止的队列集。
• xTicksToWait: 调用任务将保持在阻塞状态(其他任务正在执行)以等待队列集的成员准备好进行成功的队列读取或信号量采取操作的最长时间。
xQueueSelectFromSetFromISR
QueueSetMemberHandle_t xQueueSelectFromSetFromISR(QueueSetHandle_t xQueueSet)
可从ISR中使用的xQueue选择FromSet()的一个版本。
宏
xQueueCreate
xQueueCreate(uxQueueLength, uxItemSize)
创建一个新的队列实例。这将分配新队列所需的存储空间,并返回该队列的句柄。
Return 如果成功创建队列,则返回新创建队列的句柄。
如果无法创建队列,则返回0。
Parameters
• uxQueueLength: 队列可包含的最大项目数。
• uxItemSize: 队列中的每个项所需要的字节数。
项目按副本排队,而不是引用,因此这是每个发布的项目复制的字节数。
队列上的每个项的大小必须相同。
示例用法:
struct AMessage
{
char ucMessageID;
char ucData[ 20 ];
};
void vATask( void *pvParameters )
{
QueueHandle_t xQueue1, xQueue2;
// 创建一个能够包含10个uint32_t值的队列。
xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
if( xQueue1 == 0 )
{
// 未创建队列,也不能使用该队列。
}
// 创建一个能够包含10个指向AMessage结构的指针的队列。
// 这些数据应该通过指针传递,因为它们包含了大量的数据。
xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
if( xQueue2 == 0 )
{
// 未创建队列,也不能使用该队列。
}
// ... 其余的任务代码。
}
xQueueCreateStatic
xQueueCreateStatic(uxQueueLength,
uxItemSize,
pucQueueStorage,
pxQueueBuffer)
创建新队列实例,并返回一个可引用新队列的句柄。
在内部,在FreeRTOS实现中,队列使用两个内存块。
第一个块用于保存队列的数据结构。第二个块用于保存放置在队列中的项目。
如果使用xQueueCreate()创建队列,则在xQueueCreate()函数中自动动态分配两个内存块。
如果使用xQueueCreateStatic()创建队列,则应用程序必须提供该队列将使用的内存。
因此,xQueueCreateStatic()允许在没有使用任何动态内存分配的情况下创建队列。
Return 如果创建了队列,则返回已创建队列的句柄。如果pxQueue缓冲区为NULL,则返回NULL。
Parameters
• uxQueueLength: 队列可包含的最大项目数。
• uxItemSize: 队列中的每个项所需要的字节数。
项目按副本而不是引用排队,因此这是每个发布的项目复制的字节数。队列上的每个项的大小必须相同。
• pucQueueStorage: 如果uxItemSize不是零,则pucQueueStorageBuffer必须指向至少足够大的uint8_t数组,以容纳队列中的最大项数——即(uxQueueLength*uxItemsSize)字节。如果uxItemSize为零,则pucQueueStorageBuffer可以为空。
• pxQueueBuffer: 必须指向StaticQueue_t类型的变量,该变量将用于保存队列的数据结构。
示例用法:
struct AMessage
{
char ucMessageID;
char ucData[ 20 ];
};
#define QUEUE_LENGTH 10
#define ITEM_SIZE sizeof( uint32_t )
// xQueueBuffer 将保留该队列结构。
StaticQueue_t xQueueBuffer;
// ucQueueStorage 将保存发布到队列中的项目。
// 必须至少为(队列长度)*(队列项长度)字节长。
uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ];
void vATask( void *pvParameters )
{
QueueHandle_t xQueue1;
// 创建一个能够包含10个uint32_t值的队列。
xQueue1 = xQueueCreate( QUEUE_LENGTH, // 该队列可以保存的项目数。
ITEM_SIZE, // 队列中每个项的大小
&( ucQueueStorage[ 0 ] ), //将保存队列中项目的缓冲区。
&xQueueBuffer ); // 将保存队列结构的缓冲区。
// 因为不会使用动态内存分配, 保证能成功创建队列。因此,xQueue1现在是一个有效队列的句柄。
// ... 其余的任务代码.
}
xQueueSendToFront
xQueueSendToFront(xQueue,
pvItemToQueue,
xTicksToWait)
将项目发布到队列的前面。
该项目是通过副本来排队的,而不是通过引用来排队的。
不能从中断服务例程中调用此函数。有关ISR中使用的替代方案,请参阅xQueueSendFromISR()。
Return 如果数据已成功发送到队列,则为pdTRUE,否则为errQUEUE_FULL。
Parameters
• xQueue: 要发布项目的队列的句柄。
• pvItemToQueue: 指向要放置在队列中的项目的指针。
在创建队列时定义了队列将保留的项的大小,因此这许多字节将从pvItemToQueue复制到队列存储区域中。
• xTicksToWait: 如果队列已满,任务应阻止等待空间可用的最长时间。
如果将其设置为0且队列已满,则调用将立即返回。
时间在ticks周期中定义,因此如果需要,应使用常数portTICK_PERIOD_MS转换为实时。
示例用法:
struct AMessage
{
char ucMessageID;
char ucData[ 20 ];
} xMessage;
uint32_t ulVar = 10UL;
void vATask( void *pvParameters )
{
QueueHandle_t xQueue1, xQueue2;
struct AMessage *pxMessage;
// 创建一个能够包含10个uint32_t值的队列
xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
// 创建一个能够包含10个指向AMessage结构的指针的队列。
// 这些数据应该通过指针传递,因为它们包含了大量的数据。
xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
// ...
if( xQueue1 != 0 )
{
// 发送一个uint32_t。如有必要,等待10个ticks可用。
if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
{
// 即使在10ticks之后,也无法发出消息。
}
}
if( xQueue2 != 0 )
{
// 发送指向结构AMessage对象的指针。如果队列已满,则不要阻止。
pxMessage = & xMessage;
xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
}
// ... 其余的任务代码.
}
xQueueSendToBack
xQueueSendToBack(xQueue,
pvItemToQueue,
xTicksToWait)
这是一个调用xQueueGenericSend()的宏。
将项目发布到队列的后面。该项目是通过副本来排队的,而不是通过引用来排队的。
不能从中断服务例程中调用此函数。有关ISR中使用的替代方案,请参阅xQueueSendFromISR()。
Return 如果数据已成功发送到队列,则为pdTRUE,否则为errQUEUE_FULL。
Parameters
• xQueue: 要发布项目的队列的句柄。
• pvItemToQueue: 指向要放置在队列中的项目的指针。
在创建队列时定义了队列将保留的项的大小,因此这许多字节将从pvItemToQueue复制到队列存储区域中。
• xTicksToWait: 如果队列已满,任务应阻止等待空间可用的最长时间。
如果将其设置为0且队列已满,则调用将立即返回。
时间在ticks周期中定义,因此如果需要,应使用常数portTICK_PERIOD_MS转换为实时。
示例用法:
struct AMessage
{
char ucMessageID;
char ucData[ 20 ];
} xMessage;
uint32_t ulVar = 10UL;
void vATask( void *pvParameters )
{
QueueHandle_t xQueue1, xQueue2;
struct AMessage *pxMessage;
// 创建一个能够包含10个uint32_t值的队列
xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
// 创建一个能够包含10个指向AMessage结构的指针的队列。
// 这些数据应该通过指针传递,因为它们包含了大量的数据。
xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
// ...
if( xQueue1 != 0 )
{
// 发送一个uint32_t。如有必要,等待10个ticks可用。
if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
{
// 即使在10ticks之后,也无法发出消息。
}
}
if( xQueue2 != 0 )
{
// 发送指向结构AMessage对象的指针。如果队列已满,则不要阻止。
pxMessage = & xMessage;
xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
}
// ... 其余的任务代码.
}
xQueueSend
xQueueSend(xQueue,
pvItemToQueue,
xTicksToWait)
这是一个调用xQueueGenericSend()的宏。
它用于与不包括xQueueSendToFront()和xQueueSendToBack()宏的FreeRTOS.org版本进行向后兼容。它相当于xQueueSendToBack()。
在队列上发布一个项目。
该项目是通过副本来排队的,而不是通过引用来排队的。
不能从中断服务例程中调用此函数。有关ISR中使用的替代方案,请参阅xQueueSendFromISR()。
Return 如果项目成功发布时为pdTRUE,则为pdTRUE,否则为errQUEUE_FULL。
Parameters
• xQueue: 要发布项目的队列的句柄。
• pvItemToQueue: 指向要放置在队列中的项目的指针。
在创建队列时定义了队列将保留的项的大小,因此这许多字节将从pvItemToQueue复制到队列存储区域中。
• xTicksToWait: 如果队列已满,任务应阻止等待空间可用的最长时间。
如果将其设置为0且队列已满,则调用将立即返回。
时间在ticks周期中定义,因此如果需要,应使用常数portTICK_PERIOD_MS转换为实时。
示例用法:
struct AMessage
{
char ucMessageID;
char ucData[ 20 ];
} xMessage;
uint32_t ulVar = 10UL;
void vATask( void *pvParameters )
{
QueueHandle_t xQueue1, xQueue2;
struct AMessage *pxMessage;
// 创建一个能够包含10个uint32_t值的队列。
xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
// 创建一个能够包含10个指向AMessage结构的指针的队列。
// 这些数据应该通过指针传递,因为它们包含了大量的数据。
xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
// ...
if( xQueue1 != 0 )
{
// 发送一个uint32_t。如有必要,等待10个ticks可用。
if( xQueueSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
{
// 即使在10ticks之后,也无法发出消息。
}
}
if( xQueue2 != 0 )
{
// 发送指向结构AMessage对象的指针。如果队列已经满,则不要阻止。
pxMessage = & xMessage;
xQueueSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
}
// ... 其余的任务代码.
}
xQueueOverwrite
xQueueOverwrite(xQueue, pvItemToQueue)
仅用于长度为1的队列,因此队列为空或已满。
在队列上发布一个项目。如果队列已满,则覆盖队列中保留的值。该项目是通过副本来排队的,而不是通过引用来排队的。
不能从中断服务例程中调用此函数。有关可在ISR中使用的替代方案,请参阅xQueueOverwriteFromISR()。
Return xQueueOverwrite()是一个调用xQueueGenericSend()的宏,因此具有与xQueueSendToFront()相同的返回值。
但是,pdPASS是唯一可以返回的值,因为即使队列已经满,xQueueOverwrite()也会写入队列。
Parameters
• xQueue: 要发送数据的队列的句柄。
• pvItemToQueue: 指向要放置在队列中的项目的指针。
在创建队列时定义了队列将保留的项的大小,因此这许多字节将从pvItemToQueue复制到队列存储区域中。
示例用法:
void vFunction( void *pvParameters )
{
QueueHandle_t xQueue;
uint32_t ulVarToSend, ulValReceived;
// 创建一个包含一个uint32_t值的队列。
// 强烈建议*不要*在可以包含多个值的队列上使用xQueueOverwriteFromISR(),如果定义了配置ASSERT(),这样做将触发断言。
xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
// 使用xQueueOverwrite(),将10的值写入队列。
ulVarToSend = 10;
xQueueOverwrite( xQueue, &ulVarToSend );
// 窥视队列现在应该返回10,但将值10留在队列中。
ulValReceived = 0;
xQueuePeek( xQueue, &ulValReceived, 0 );
if( ulValReceived != 10 )
{
// 错误,除非被其他任务删除该项目。
}
// 队列任然是满的. 使用 xQueueOverwrite() 将100覆盖到列队中
ulVarToSend = 100;
xQueueOverwrite( xQueue, &ulVarToSend );
// 这次从队列中读取,使队列再次为空。
// 再次使用块时间0。
xQueueReceive( xQueue, &ulValReceived, 0 );
// 读取的值应该是最后一个写入的值,即使写入值时队列已满。
if( ulValReceived != 100 )
{
// 错误!
}
// ...
}
xQueueSendToFrontFromISR
xQueueSendToFrontFromISR(xQueue,
pvItemToQueue,
pxHigherPriorityTaskWoken)
这是一个调用xQueueGenericSendFromISR()的宏。
将项目发布到队列的前面。在中断服务例程中使用此宏是安全的。
项目由副本排队,而不是引用,所以最好只排队小项目,特别是当从ISR调用时。
在大多数情况下,最好存储一个指向正在排队的项目的指针。
Return 如果数据已成功发送到队列,则为pdTRUE,否则为errQUEUE_FULL。
Parameters
• xQueue: 要发布项目的队列的句柄。
• pvItemToQueue: 指向要放置在队列中的项目的指针。
在创建队列时定义了队列将保留的项的大小,因此这许多字节将从pvItemToQueue复制到队列存储区域中。
• [out] pxHigherPriorityTaskWoken: 如果发送到队列导致任务解除阻塞,并且未解除阻塞的任务的优先级高于当前正在运行的任务,则xQueueOverwriteFromISR()将pxHigherPriorityTaskWoken设置为pdTRUE。
如果xQueueOverwriteFromISR()将此值设置为pdTRUE,那么在退出中断之前应该请求一个上下文切换。
缓冲IO的使用示例(其中ISR每次调用可以获得多个值):
void vBufferISR( void )
{
char cIn;
BaseType_t xHigherPriorityTaskWoken;
// 我们在ISR开始时还没有唤醒任何任务。
xHigherPriorityTaskWoken = pdFALSE;
// 循环,直到缓冲区为空。
do
{
// 从缓冲区中获得一个字节。
cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
// 发布该字节。
xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
} while( portINPUT_BYTE( BUFFER_COUNT ) );
// 现在缓冲区是空的,我们可以在必要时切换上下文。
if( xHigherPriorityTaskWoken )
{
portYIELD_FROM_ISR ();
}
}
xQueueSendToBackFromISR
xQueueSendToBackFromISR(xQueue,
pvItemToQueue,
pxHigherPriorityTaskWoken)
这是一个调用xQueueGenericSendFromISR()的宏。
将项目发布到队列的后面。在中断服务例程中使用此宏是安全的。
项目由副本排队,而不是引用,所以最好只排队小项目,特别是当从ISR调用时。
在大多数情况下,最好存储一个指向正在排队的项目的指针。
Return 如果数据已成功发送到队列,则为pdTRUE,否则为errQUEUE_FULL。
Parameters
• xQueue: 要发布项目的队列的句柄。
• pvItemToQueue: 指向要放置在队列中的项目的指针。
在创建队列时定义了队列将保留的项的大小,因此这许多字节将从pvItemToQueue复制到队列存储区域中。
• [out] pxHigherPriorityTaskWoken: 如果发送到队列导致任务解除阻塞,并且未解除阻塞的任务的优先级高于当前正在运行的任务,则xQueueOverwriteFromISR()将pxHigherPriorityTaskWoken设置为pdTRUE。
如果xQueueOverwriteFromISR()将此值设置为pdTRUE,那么在退出中断之前应该请求一个上下文切换。
缓冲IO的使用示例(其中ISR每次调用可以获得多个值):
void vBufferISR( void )
{
char cIn;
BaseType_t xHigherPriorityTaskWoken;
// 我们在ISR开始时还没有唤醒任何任务。
xHigherPriorityTaskWoken = pdFALSE;
// 循环,直到缓冲区为空。
do
{
// 从缓冲区中获得一个字节。
cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
// 发布该字节。
xQueueSendToBackFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
} while( portINPUT_BYTE( BUFFER_COUNT ) );
// 现在缓冲区是空的,我们可以在必要时切换上下文。
if( xHigherPriorityTaskWoken )
{
portYIELD_FROM_ISR ();
}
}
xQueueOverwriteFromISR
xQueueOverwriteFromISR(xQueue,
pvItemToQueue,
pxHigherPriorityTaskWoken)
可在中断服务例行程(ISR)中使用的xQueueOverwrite()的一个版本。
仅用于可容纳单个项目的队列,因此队列为空或已满。
在队列上发布一个项目。如果队列已满,则覆盖队列中保留的值。该项目是通过副本来排队的,而不是通过引用来排队的。
Return xQueueOverwriteFromISR()是一个调用xQuequeGenerendFromISR()的宏,因此与xQuqueSeneSendToFrontFromISR()具有相同的返回值。
但是,pdPASS是唯一可以返回的值,因为即使队列已经满,xQueueOverwriteFromISR()也会写入队列。
Parameters
• xQueue: 要发布项目的队列的句柄。
• pvItemToQueue: 指向要放置在队列中的项目的指针。
在创建队列时定义了队列将保留的项的大小,因此这许多字节将从pvItemToQueue复制到队列存储区域中。
• [out] pxHigherPriorityTaskWoken: 如果发送到队列导致任务解除阻塞,并且未解除阻塞的任务的优先级高于当前正在运行的任务,则xQueueOverwriteFromISR()将pxHigherPriorityTaskWoken设置为pdTRUE。
如果xQueueOverwriteFromISR()将此值设置为pdTRUE,那么在退出中断之前应该请求一个上下文切换。
示例用法:
QueueHandle_t xQueue;
void vFunction( void *pvParameters )
{
// 创建一个包含一个uint32_t值的队列。
// 强烈建议*不要*在可以包含多个值的队列上使用xQueueOverwriteFromISR(),如果定义了配置ASSERT(),这样做将触发断言。
xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
}
void vAnInterruptHandler( void )
{
// xHigherPriorityTaskWoken 用之前必须设置为pdFALSE。
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
uint32_t ulVarToSend, ulValReceived;
// 使用xQueueOverwriteFromISR(),将10的值写入队列。
ulVarToSend = 10;
xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
// 队列已满,但再次调用xQueueOverwriteFromISR()仍将通过,因为队列中保留的值将被新值覆盖。
ulVarToSend = 100;
xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
// 从队列中读取,现在将返回100。
// ...
if( xHigherPrioritytaskWoken == pdTRUE )
{
// 写入队列会导致任务取消阻塞,并且取消阻塞任务的优先级高于或等于当前执行任务的优先级(此中断的任务)。
//执行上下文切换,以便此中断直接返回到未解除阻塞的任务。
portYIELD_FROM_ISR(); // 或portEND_SWITCHING_ISR(),具体取决于端口。
}
}
xQueueSendFromISR
xQueueSendFromISR(xQueue, pvItemToQueue, pxHigherPriorityTaskWoken)
这是一个调用xQueueGenericSendFromISR()的宏。
它的包括是为了与不包括xQueueSendBackToFromISR()和xQueueSendToFrontFromISR()宏的FreeRTOS.org版本进行向后兼容。
将项目发布到队列的后面。
在中断服务例行程中使用此函数是安全的。
项目由副本排队,而不是引用,所以最好只排队小项目,特别是当从ISR调用时。
在大多数情况下,最好存储一个指向正在排队的项目的指针。
Return 如果数据已成功发送到队列,则为pdTRUE,否则为errQUEUE_FULL。
Parameters
• xQueue: 要发布项目的队列的句柄。
• pvItemToQueue: 指向要放置在队列中的项目的指针。
在创建队列时定义了队列将保留的项的大小,因此这许多字节将从pvItemToQueue复制到队列存储区域中。
• [out] pxHigherPriorityTaskWoken: 如果发送到队列导致任务解除阻止,并且未解除阻止任务的优先级高于当前正在运行的任务, xQueueSendFromISR()将将*pxHigher任务设置为pdTRUE。如果xQueueSendFromISR()将此值设置为pdTRUE,则在退出中断之前应该请求一个上下文开关。
缓冲IO的使用示例(其中ISR每次调用可以获得多个值):
void vBufferISR( void )
{
char cIn;
BaseType_t xHigherPriorityTaskWoken;
// 我们在ISR开始时还没有唤醒任何任务。
xHigherPriorityTaskWoken = pdFALSE;
// 循环,直到缓冲区为空
do
{
// 从缓冲区中获得一个字节。
cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
// 发布该字节。
xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
} while( portINPUT_BYTE( BUFFER_COUNT ) );
// 现在缓冲区是空的,我们可以在必要时切换上下文。
if( xHigherPriorityTaskWoken )
{
// 此处使用的实际宏是特定于端口的。
portYIELD_FROM_ISR ();
}
}
xQueueReset
xQueueReset(xQueue)
将队列重置为其原始的空状态。返回值现在已过时,并且始终设置为pdPASS。