Freertos——使用队列集优化数据传输
队列集通常在实际的产品设计中我们对硬件的原始数据队列和参与操作的软件数据队列应该是分开设计这样能保证我们的业务逻辑能更加清晰独立并且硬件读取逻辑可以再不同产品中复用会导致一个问题我们需要在每个硬件读取后进行相应的数据转化任务如果硬件过多会导致任务栈占据过多的内存且使任务切换过于频繁污染了时间片因此我们可以使用到队列集使得写入同一个业务的软件队列的原始数据队列转换达成统一使得任务数量减少并且更容易修改移植我们的代码业务逻辑红外遥控器驱动程序里它只应该把键值记录下来、写入某个队列它不应该把键值转换为游戏的控制键。在红外遥控器的驱动程序里不应该有游戏相关的代码这样切换使用场景时这个驱动程序还可以继续使用。把红外遥控器的按键转换为游戏的控制键应该在游戏的任务里实现。要支持多个输入设备时我们需要实现一个“InputTask”它读取各个设备的队列得到数据后再分别转换为游戏的控制键。队列集的本质也是队列只不过里面存放的是“队列句柄”。使用过程如下创建队列A它的长度是n1创建队列B它的长度是n2创建队列集S它的长度是“n1n2”把队列A、B加入队列集S这样写队列A的时候会顺便把队列A的句柄写入队列集S这样写队列B的时候会顺便把队列B的句柄写入队列集SInputTask先读取队列集S它的返回值是一个队列句柄这样就可以知道哪个队列有有数据了然后InputTask再读取这个队列句柄得到数据。内部机制每当在一个队列写入数据系统自动在这个队列在的队列集的队列中写入一个此队列句柄当队列集读取时就会依次返回出他的队列中存放的句柄然后再凭借返回的句柄操作对应的队列创建队列集QueueSetHandle_txQueueCreateSet(constUBaseType_t uxEventQueueLength)uxQueueLength队列集长度可存放的队列句柄数返回值非0成功返回句柄以后使用句柄来操作队列NULL失败因为内存不足加入队列BaseType_txQueueAddToSet(QueueSetMemberHandle_t xQueueOrSemaphore,QueueSetHandle_t xQueueSet);xQueueOrSemaphore队列句柄要放入的队列xQueueSet队列集句柄返回值pdTRUE成功pdFALSE失败读取非空队列QueueSetMemberHandle_txQueueSelectFromSet(QueueSetHandle_t xQueueSet,TickType_tconstxTicksToWait);xQueueSet队列集句柄xTicksToWait如果队列集空则无法读出数据可以让任务进入阻塞状态如果被设为0无法读出数据时函数会立刻返回如果被设为portMAX_DELAY则会一直阻塞直到有数据可写返回值NULL失败队列句柄成功从队列集移除成员BaseType_txQueueRemoveFromSet(QueueSetMemberHandle_t xQueueOrSemaphore,QueueSetHandle_t xQueueSet);xQueueOrSemaphore队列句柄要放入的队列xQueueSet队列集句柄返回值pdTRUE失败pdFALSE成功删除队列集voidvQueueDeleteSet(QueueSetHandle_t xQueueSet);xQueueSet队列集句柄注意需先移除所有成员否则可能导致内存泄漏简单程序示例// 1. 创建队列和队列集QueueHandle_t xKeyQueuexQueueCreate(5,sizeof(uint8_t));// 按键队列QueueHandle_t xUartQueuexQueueCreate(3,sizeof(char));// 串口队列QueueSetHandle_t xInputSetxQueueCreateSet(53);// 队列集// 2. 将队列加入队列集xQueueAddToSet(xKeyQueue,xInputSet);xQueueAddToSet(xUartQueue,xInputSet);// 3. 数据写入任务例如按键中断、串口中断voidvWriteTask(void*pvParameters){uint8_tkey0x01;xQueueSend(xKeyQueue,key,0);// 写入按键队列自动触发队列集}// 4. InputTask统一处理voidvInputTask(void*pvParameters){QueueSetMemberHandle_t xActivatedMember;uint8_tkeyData;charuartData;while(1){// 等待队列集有数据xActivatedMemberxQueueSelectFromSet(xInputSet,portMAX_DELAY);// 判断是哪个队列有数据if(xActivatedMemberxKeyQueue){xQueueReceive(xKeyQueue,keyData,0);// 处理按键数据如转换为游戏控制键}elseif(xActivatedMemberxUartQueue){xQueueReceive(xUartQueue,uartData,0);// 处理串口数据}}}注意事项队列集长度的设置队列集长度需 ≥ 所有成员队列的总长度或信号量的最大计数值之和。例如队列 A 长度为 5队列 B 长度为 3则队列集长度应 ≥ 8最坏情况下两个队列同时满队列集需存放 8 个句柄成员的 “独占性”队列 / 信号量加入队列集后不应再直接读写否则会导致队列集状态不同步。需通过队列集机制间接访问先xQueueSelectFromSet() 获取句柄再读写对应队列这个函数类似于xQueueReceive()的阻塞机制中断中使用队列集若在中断中操作队列集成员需使用中断安全的队列读取函数 xQueueSendFromISR()
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2571226.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!