freertos笔记-队列

news/2024/12/2 19:42:36/

红叶何时落水

队列结构体

typedef struct QueueDefinition
{int8_t *pcHead;                    /*< Points to the beginning of the queue storage area. */int8_t *pcTail;                    /*< Points to the byte at the end of the queue storage area.  Once more byte is allocated than necessary to store the queue items, this is used as a marker. */int8_t *pcWriteTo;                /*< Points to the free next place in the storage area. */union                            /* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */{int8_t *pcReadFrom;            /*< Points to the last place that a queued item was read from when the structure is used as a queue. */UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */} 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. */volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */UBaseType_t uxLength;            /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */UBaseType_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 queueUNLOCKED 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 queueUNLOCKED when the queue is not locked. */#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )uint8_t ucStaticallyAllocated;    /*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */#endif#if ( configUSE_QUEUE_SETS == 1 )struct QueueDefinition *pxQueueSetContainer;#endif#if ( configUSE_TRACE_FACILITY == 1 )UBaseType_t uxQueueNumber;uint8_t ucQueueType;#endif} xQUEUE;

pcHead -> 44
pcTail -> 48
pcWriteTo -> 44
pcReadFrom -> 47
xTasksWaitingToSend(入队阻塞列表)
xTasksWaitingToReceive(出队阻塞列表)
uxMessagesWaiting=0
uxLength=4
uxItemSize=32
cRxLock=queueUNLOCKED
cTxLock=queueUNLOCKED
其他成员变量
队列项目一(32字节)
队列项目二(32字节)
队列项目三(32字节)
队列项目四(32字节)


动态创建队列
 

QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType )
{Queue_t *pxNewQueue;size_t xQueueSizeInBytes;uint8_t *pucQueueStorage;if( uxItemSize == ( UBaseType_t ) 0 )//队列大小为0{xQueueSizeInBytes = ( size_t ) 0;}else{xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*否则队列要分配一块空间lint !e961 MISRA exception as the casts are only redundant for some ports. */}pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );//占用的总空间等于结构体+储存体if( pxNewQueue != NULL ){pucQueueStorage = ( ( uint8_t * ) pxNewQueue ) + sizeof( Queue_t );//让该指针指向分配到的储存体地址以上内容为分配空间,下面的是初始化结构体prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );//初始化队列}return pxNewQueue;//返回句柄,也就是结构体首地址
}
初始化队列prvInitialiseNewQueue
static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue )
{( void ) ucQueueType;if( uxItemSize == ( UBaseType_t ) 0 ){pxNewQueue->pcHead = ( int8_t * ) pxNewQueue;//pcHead不能为NULL,如果为NULL的话,代表他是一个mutex互斥}else{pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage;//指向储存体首地址}pxNewQueue->uxLength = uxQueueLength;//更新长度和大小pxNewQueue->uxItemSize = uxItemSize;( void ) xQueueGenericReset( pxNewQueue, pdTRUE );traceQUEUE_CREATE( pxNewQueue );
}
xQueueGenericReset
BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue )
{Queue_t * const pxQueue = ( Queue_t * ) xQueue;taskENTER_CRITICAL();{pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize );//pcTail指向储存体尾部pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U;pxQueue->pcWriteTo = pxQueue->pcHead;//一开始pcWriteTo指向头部pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( UBaseType_t ) 1U ) * pxQueue->uxItemSize );pxQueue->cRxLock = queueUNLOCKED;pxQueue->cTxLock = queueUNLOCKED;if( xNewQueue == pdFALSE ){if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ){if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )//下一次复位该队列,代表着,该队列清空,那么之前因为队列满而阻塞的任务,要被释放{queueYIELD_IF_USING_PREEMPTION();}else{mtCOVERAGE_TEST_MARKER();}}else{mtCOVERAGE_TEST_MARKER();}}else{   //初始化时执行这里vListInitialise( &( pxQueue->xTasksWaitingToSend ) );vListInitialise( &( pxQueue->xTasksWaitingToReceive ) );}}taskEXIT_CRITICAL();return pdPASS;
}
xTaskRemoveFromEventList
BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
{TCB_t *pxUnblockedTCB;BaseType_t xReturn;pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );//获取下一个要解除的任务的句柄( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );//将该任务的事件列表项移除if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )//如果调度器正常工作{( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );//移除状态列表项prvAddTaskToReadyList( pxUnblockedTCB );//添加到就绪列表中,同时,这意味着,堵塞不能嵌套}else{vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );//添加到xPendingReadyList,等到调度器开始工作后,再添加到就绪列表中}if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )//判断要不要切换任务{xReturn = pdTRUE;xYieldPending = pdTRUE;}else{xReturn = pdFALSE;}return xReturn;
}


发送信息到队列xQueueGenericSend
1.开启一个死循环 关中断
2.判断队列是否可以写入
    2.true.1 复制队列中的信息prvCopyDataToQueue 
        2.true.1.1 获取当前队列uxMessagesWaiting值
        2.true.1.2 判断是不是互斥队列 是的话xTaskPriorityDisinherit 优先级操作
                   不是的话判断是将信息插到哪里,是队头还是队尾
                   具体操作一致 memcpy-指针移动-判断队列满没满
        2.true.1.2 uxMessagesWaiting++; 
    2.true.2 队列集相关操作
    2.true.3 检查有没有任务正在堵塞,等待消息
            2.true.3.true xTaskRemoveFromEventList释放该任务
    2.false.1 队列满了的话,判断xTicksToWait是否要等待
            xTicksToWait = 0; return 退出函数
            xTicksToWait != 0 
            设置堵塞时间 vTaskSetTimeOutState 初始化时间结构体 记录当前的系统时钟节拍计数器的值 xTickCount 和溢出次数 xNumOfOverflows。
            void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
            {
                pxTimeOut->xOverflowCount = xNumOfOverflows;
                pxTimeOut->xTimeOnEntering = xTickCount;
            }
3.挂起调度器 并且队列上锁prvLockQueue 这里主要是防止中断程序对该队列有操作
4.检查有没有任务溢出xTaskCheckForTimeOut
   

 BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ){BaseType_t xReturn;taskENTER_CRITICAL();{const TickType_t xConstTickCount = xTickCount;if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */{/* The tick count is greater than the time at whichvTaskSetTimeout() was called, but has also overflowed sincevTaskSetTimeOut() was called.  It must have wrapped all the wayaround and gone past again. This passed since vTaskSetTimeout()was called. */xReturn = pdTRUE;}else if( ( ( TickType_t ) ( xConstTickCount - pxTimeOut->xTimeOnEntering ) ) < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */{/* Not a genuine timeout. Adjust parameters for time remaining. */*pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );vTaskSetTimeOutState( pxTimeOut );xReturn = pdFALSE;}else{xReturn = pdTRUE;}}taskEXIT_CRITICAL();return xReturn;}


http://www.ppmy.cn/news/133550.html

相关文章

1微型投影仪

神画小媚智能投影仪 光米 连了网络就可以看电影&#xff0c;手机下个软件就可以同步手机&#xff0c;映像清晰&#xff0c;如果是幕布的话效果应该会更好&#xff0c;操作完全简单易懂&#xff0c;完全可以轻易搞定&#xff0c;比连接ps4神马的简单多了。公司开会也可以自带设备…

oracle智能便携投影机,目前最好的便携投影仪,这几款便携投影仪不容错过

原标题&#xff1a;目前最好的便携投影仪&#xff0c;这几款便携投影仪不容错过 近几年投影仪迅速发展&#xff0c;投影仪的分类也越来越多元化&#xff0c;鉴于家用投影仪只能在家摆放使用&#xff0c;迷你投影仪也因此孕育而生。不但可以满足家用&#xff0c;还可以携带&…

html写的代码投屏到LED屏,会议室小间距LED屏可以实现笔记本电脑的无线投屏显示吗?...

原标题&#xff1a;会议室小间距LED屏可以实现笔记本电脑的无线投屏显示吗&#xff1f; 今天小编要给大家介绍一款针对会议室应用的商用级产品,它不仅能给您带来整洁的桌面&#xff0c;稳定的表现&#xff0c;笔记本电脑用户只需将USB按键连接至电脑USB端口&#xff0c;就能分享…

字符串的常用方法

一、操作方法 我们也可将字符串常用的操作方法归纳为增、删、改、查&#xff0c;需要知道字符串的特点是一旦创建了&#xff0c;就不可变。 增 &#x1f355;&#x1f355;并不是说直接增添内容&#xff0c;而是创建字符串的一个副本&#xff0c;再进行操作。除了常用的 以…

Hi3516A开发--视频接口

参看&#xff1a;视频传输端口 参看&#xff1a;几种常用的视频接口 扩展&#xff1a;音视频接口介绍 我们经常在家里的电视机、各种播放器上&#xff0c;视频会议产品和监控产品的编解码器的视频输入输出接口上看到很多视频接口&#xff0c;这些视频接口哪些是模拟接口、哪些…

两个usb摄像头通过hub连接电脑怎么同时独立显示_把电脑装进口袋是什么感觉?华硕VivoStick TS10多角度体验...

自英特尔提出Compute Stick“计算棒”概念后&#xff0c;可谓开创了一个新的电脑形态。它仅比口红略大的身材&#xff0c;在连接显示器等外设之后&#xff0c;“计算棒”就能为用户带来完整的PC体验&#xff0c;对轻办公和对电脑性能要求不高的行业用户来说&#xff0c;计算棒可…

《调色师手册:电影和视频调色专业技法(第2版)》——配置调色影院

本节书摘来自异步社区《调色师手册:电影和视频调色专业技法(第2版)》一书中的第2章,配置调色影院,作者 【美】Alexis Van Hurkman(阿列克谢凡赫克曼),译者 高铭,陈华,更多章节内容可以访问云栖社区“异步社区”公众号查看。 配置调色影院 调色影院的目的是创建一个理…

【SSM分布式架构电商项目-11】后台系统开发接口返回商品类目数据

功能 构造数据 category.getDataService({"data": [{"u": "/products/1.html","n": "<a href/products/1.html>图书、音像、电子书刊</a>","i": [{"u": "/products/2.html",&quo…