FreeRTOS消息队列ESP32使用

更新时间:2023-06-30 10:08:45 阅读: 评论:0

FreeRTOS消息队列ESP32使⽤
FreeRTOS消息队列 & ESP32实战
FreeRTOS消息队列
FreeRTOS的消息队列和操作系统课中讲的消息队列⼤差不差,都是为了有序的、安全的在多任务间在发送信息。下⾯是其⼀些特性。
1. 多任务访问
  队列不是属于某个特别指定的任务的,任何任务都可以向队列中发送消息,或者从队列中提取消息。
beelzebub
2. 原始值传递
  队列中的消息内容不是引⽤,即不是把内容的地址传递,⽽是将数据的内容直接拷贝到消息队列中,这样做的好处有两个,第⼀是在传递完后,消息缓冲区可⽴即进⾏更改不需要等到消息完成传递后再更改,第⼆是不会因为局部变量变化⽽导致消息混乱,将某个函数的局部变量作为消息传递的时候,当函数运⾏完成并返回,这个局部变量就会被销毁,这样就导致传递到队列⾥的地址就是⼀个垃圾地址,内容并没有什么⽤处。当然也可以直接将地址作为内容传递过去,这样就实现了引⽤传递。
3. 出队阻塞tiffany什么意思
  当任务想从队列中读取消息时可以将⾃⼰阻塞起来等待数据到达,当然可以不等待获取,也可以等待⼀定时间获取,更可以永久等待。
goodluck什么意思4. ⼊队阻塞
  当任务想向队列中传递消息时发现队列已经满了,就可以选择将⾃⼰阻塞起来等待队列有空位置再将消息传递进去。当然也有三种阻塞模式,不阻塞、阻塞⼀段时间、永久阻塞。
FreeRTOS消息队列结构体源码分析
/*
* Definition of the queue ud by the scheduler.
* Items are queued by copy, not reference.  See the following link for the
* rationale: www.freertos/Embedded-RTOS-Queues.html
*/
typedef struct QueueDefinition  /* The old naming convention is ud to prevent breaking kernel aware debuggers. */
{
int8_t *pcHead;/*< 指向队列头部的指针 */
int8_t *pcWriteTo;/*< 指向队列下个空闲位置的指针 */
union
{
托福词汇串讲QueuePointers_t xQueue;/*< 这个应该是指的当作为队列使⽤时的句柄,指向创建的队列 */
SemaphoreData_t xSemaphore;/*< 这个应该是指的当作为信号量使⽤时的句柄,指向创建的信号量  */
} u;
List_t xTasksWaitingToSend;/*等待发送任务列表,⼊队阻塞列表*/
/*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */
List_t xTasksWaitingToReceive;/*等待接收任务列表,出队阻塞列表*/
/*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */牛仔裤的夏天1
volatile UBaType_t uxMessagesWaiting;/*< The number of items currently in the queue. */
UBaType_t uxLength;/*< The length of the queue defined as the number of items it will hold, not the number of bytes.队列内容长度,按消息数量计算不是按字节计算 */
UBaType_t uxItemSize;/*< The size of each items that the queue will hold. 消息内容最⼤长度*/
volatile int8_t cRxLock;/*< Stores the number of items received from the queue (removed from the queue) while the queue was locked.  Set to queueUNL OCKED when the queue is not locked. */
volatile int8_t cTxLock;/*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked.  Set to queueUNLOCK ED when the queue is not locked. */
#if(( configSUPPORT_STATIC_ALLOCATION == 1 )&&( configSUPPORT_DYNAMIC_ALLOCATION == 1 ))
uint8_t ucStaticallyAllocated;/*< Set to pdTRUE if the memory ud by the queue was statically allocated to ensure no attempt is made to free the memor y. */
#endif
#if( configUSE_QUEUE_SETS == 1 )
struct QueueDefinition *pxQueueSetContainer;
#endif
#if( configUSE_TRACE_FACILITY == 1 )
UBaType_t uxQueueNumber;
uint8_t ucQueueType;
#endif
portMUX_TYPE mux;//Mutex required due to SMP
} xQUEUE;
/* The old xQUEUE name is maintained above then typedefed to the new Queue_t
name below to enable the u of older kernel aware debuggers. */
typedef xQUEUE Queue_t;
FreeRTOS API分析
1. xQueueCreate();
QueueHandle_t xQueueGenericCreate(const UBaType_t uxQueueLength,const UBaType_t uxItemSize,const uint8_t ucQueueType )
{
Queue_t *pxNewQueue;
size_t xQueueSizeInBytes;
uint8_t *pucQueueStorage;
configASSERT( uxQueueLength >( UBaType_t )0);
if( uxItemSize ==( UBaType_t )0)
takuya
{
ptember的缩写/* There is not going to be a queue storage area. */
xQueueSizeInBytes =( size_t )0;
}
el
{
/* Allocate enough space to hold the maximum number of items that
can be in the queue at any time. */
xQueueSizeInBytes =( size_t )( uxQueueLength * uxItemSize );
/*lint !e961 MISRA exception as the casts are only redundant for some ports. *///队列长度*消息⼤⼩=最⼤
}
中国梦我的梦演讲稿/* Check for multiplication overflow. */
configASSERT(( uxItemSize ==0)||( uxQueueLength ==( xQueueSizeInBytes / uxItemSize )));
/* Check for addition overflow. */
configASSERT((sizeof( Queue_t )+ xQueueSizeInBytes )>  xQueueSizeInBytes );
/* Allocate the queue and storage area.  Justification for MISRA
deviation as follows:  pvPortMalloc() always ensures returned memory
blocks are aligned per the requirements of the MCU stack.  In this ca
pvPortMalloc() must return a pointer that is guaranteed to meet the
alignment requirements of the Queue_t structure - which in this ca
is an int8_t *.  Therefore, whenever the stack alignment requirements
are greater than or equal to the pointer to char requirements the cast
is safe.  In other cas alignment requirements are not strict (one or
two bytes). *//*这⾥意思应该是malloc申请的区域应该符合MISRA的标准对齐。*/
pxNewQueue =( Queue_t *)pvPortMalloc(sizeof( Queue_t )+ xQueueSizeInBytes );//队列结构体⼤⼩+缓冲区⼤⼩
if( pxNewQueue !=NULL)
{
/* Jump past the queue structure to find the location of the queue
storage area. */
pucQueueStorage =( uint8_t *) pxNewQueue;
pucQueueStorage +=sizeof( Queue_t );/*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. *///指针偏移直接跳过队列结构体⼤⼩到缓冲区。
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
{
/* Queues can be created either statically or dynamically, so
note this task was created dynamically in ca it is later
deleted. */
pxNewQueue->ucStaticallyAllocated = pdFALSE;
}
#endif/* configSUPPORT_STATIC_ALLOCATION */
prvInitialiNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
}
el
{
traceQUEUE_CREATE_FAILED( ucQueueType );
mtCOVERAGE_TEST_MARKER();
}unforgettable
return pxNewQueue;//返回队列指针。
}
创建完成⽰意图 :
2. xQueueSend() & xQueueSendFromISR()
发送消息到队列尾部(后向⼊队),这两个函数是⼀样的,FromISR⽤于中断服务函数。
源码太过冗长,主要实现的功能就是⼊队和⼊队时间记录⽅便实现阻塞操作,这⾥就不再具体分析,想看的话可以留⾔我单独发⼀期。
#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait )
参数:
xQueue: 队列句柄,指明要向哪个队列发送数据,创建队列成功以后会返回此队列的队列句柄。
pvltemToQueue: 指向要发送的消息,发送时候会将这个消息拷贝到队列中。
xTicksToWait:阻塞时间,此参数指⽰当队列满的时候任务进⼊阻塞态等待队列空闲的最⼤
时间。如果为0的话当队列满的时候就⽴即返回;当为 portMAX_DELAY的话就会⼀直等待,直到队列有空闲的队列项,也就是死等,但是宏INCLUDE_vTaskSuspend必须为1。
3. xQueueSendToFront() & xQueueSendToFrontFromISR()
xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait )
发送消息到队列头(前向⼊队),FromISR⽤于中断服务函数。
参数:
xQueue: 队列句柄,指明要向哪个队列发送数据,创建队列成功以后会返回此队列的队列句柄。
pvltemToQueue: 指向要发送的消息,发送时候会将这个消息拷贝到队列中。
xTicksToWait:阻塞时间,此参数指⽰当队列满的时候任务进⼊阻塞态等待队列空闲的最⼤
时间。如果为0的话当队列满的时候就⽴即返回;当为 portMAX_DELAY的话就会⼀直等待,直到队列有空闲的队列项,也就是死等,但是宏INCLUDE_vTaskSuspend必须为1。
4. xQueueOverwrite() & xQueueOverwriteFromISR()
发送消息到队列,带覆写功能,当队列满了以后⾃动覆盖掉旧的消息,所以也不存在满员等待的情况,FromISR⽤于中断服务函数。
xQueue: 队列句柄,指明要向哪个队列发送数据,创建队列成功以后会返回此队列的队列句柄。prime rate
pvltemToQueue: 指向要发送的消息,发送时候会将这个消息拷贝到队列中。
xQueueOverwrite( xQueue, pvItemToQueue )
5. xQueueReceive() & xQueueReceiveFromISR()
BaType_t xQueueReceive( QueueHandle_t xQueue,void*const pvBuffer, TickType_t xTicksToWait )
从队列中读取队列项消息,并且读取完以后删除掉队列项(消息)。
参数:
xQueue: 队列句柄,指明要读取哪个队列的数据,创建队列成功以后会返回此队列的队列句柄。
pvBuffer: 保存数据的缓冲区,读取队列的过程中会将读取到的数据拷贝到这个缓冲区中。
xTicksToWait: 阻塞时间,此参数指⽰当队列空的时候任务进⼊阻塞态等待队列有数据的最⼤时间。如果为0的话当队列空的时候就⽴即返回;当为portMAX_DELAY的话就会⼀直等待,直到队列有数据,也就是死等,但是宏INCLUDE_vTaskSuspend必须为1。
6. xQueuePeek() & xQueuePeekFroemISR ()
BaType_t xQueuePeek( QueueHandle_t xQueue,void*const pvBuffer, TickType_t xTicksToWait )
从队列中读取队列项消息,并且读取完以后不删除队列项(消息)。
参数:
xQueue: 队列句柄,指明要读取哪个队列的数据,创建队列成功以后会返回此队列的队列句柄。
pvBuffer: 保存数据的缓冲区,读取队列的过程中会将读取到的数据拷贝到这个缓冲区中。
xTicksToWait: 阻塞时间,此参数指⽰当队列空的时候任务进⼊阻塞态等待队列有数据的最⼤时间。如果为0的话当队列空的时候就⽴即返回;当为portMAX_DELAY的话就会⼀直等待,直到队列有数据,也就是死等,但是宏INCLUDE_vTaskSuspend必须为1。
ESP32使⽤
样例:设计⼀个接⼝,每当按键按下的时候向指定队列发送⼀次消息,没有消息则永久等待,当两个线程都获取到了信息再将这个信息消除具体框图如下。
程序框架:
此实验⽬的为了T12烙铁信息传递部分,因为⽹络接⼝还没实现,⽹络数据刷新⽤⼀个屏幕显⽰线程替代。
最后代码如下
外部中断配置部分

本文发布于:2023-06-30 10:08:45,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/90/162480.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:队列   消息   阻塞   等待   数据
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图