RTOS2:通用入队函数xQueueGenericSend


大概记录下这个函数的过程以便于继续分析,类似于伪代码

xQueue: 队列句柄,指明要向哪个队列发送数据,创建队列成功以后会返回此队列的 队列句柄。

pvItemToQueue:指向要发送的消息,发送的过程中会将这个消息拷贝到队列中。

xTicksToWait : 阻塞时间。

xCopyPosition: 入队方式

有三种入队方式:

queueSEND_TO_BACK: 后向入队

queueSEND_TO_FRONT: 前向入队

queueOVERWRITE: 覆写入队。

队列结构体主要部分(省略了队列集):

 

 进入临界段后:

uxMessagesWaiting<uxLength 判断队列是否满,(或覆写入队不考虑这个,但是一般不用覆写入队)

1 若队列满,且没有阻塞时间,直接退出临界段返回队列满。

2 若队列未满,则写memcpy入队,分为前入队  后入队  覆写入队 (deemo用的back)

后:写入位置:pcWriteTo //初始化为队列起始pcHead。 随后更新pcWriteTo

前:写入位置:u.pcReadFrom //初始化为队列末尾pcTail(-1)。随后更新u.pcReadFrom

覆写:写入位置:u.pcReadFrom //初始化为队列末尾 ,随后更新u.pcReadFrom并uxMessagesWaiting-- 因为覆写不会改变长度

最后更新uxMessagesWaiting。当前队列中消息数

入队之后,相当于更新了队列,需要判断等待消息阻塞列表 list中 ,有没有在等消息的任务,

有的话,因为刚刚消息已经入队了,可以将其移除并放到就绪任务列表中,判断移除的任务与当前任务的优先级,是否进行任务切换。

(若需要,则立即进行任务切换pendSV,与xTaskIncrementTick不同,这个是执行完之后再切换)

假如此时调度器上锁,则不判断优先级并将其放到挂起就绪列表。//uxSchedulerSuspended判断是否上锁

以上涉及到的几个list:

xTasksWaitingToReceivexTimerQueue成员)//等待消息阻塞列表 ,或称等待接受消息的任务列表

pxReadyTasksLists(全局)// 就绪列表,注意是加到对应优先级的就绪列表

xPendingReadyList(全局)//挂起就绪列表

从列表中移除任务的过程:先获取TCB,( (&( ( xTasksWaitingToSend )->xListEnd ))->pxNext->pvOwner )

然后链表操作,删除TCB中的事件列表项 xEventListItem(列表项知道自己在那个列表,调度过程中会判断是否在等待某个事件,删除为NULL)

(列表按照升值排列列表项)

在这里退出临界段。

3 若队列满,且设置了阻塞时间,阻塞时间为最大值

任务挂起vTaskSuspendAll,队列上锁,将状态列表项 pxCurrentTCB->xGenericListItem挂到挂起列表xSuspendedTaskList  队列上锁

4若队列满,且设置了阻塞时间,阻塞时间为某个值

任务挂起vTaskSuspendAll,队列上锁,将状态列表项 pxCurrentTCB->xGenericListItem挂到延时列表pxDelayedTaskList 队列上锁并开始等待

 有关延时列表和溢出延时列表暂不展开

等待:检测队列是否满,检测是否到达预定阻塞时间

计时方式:

获取当前xTickCount 以及xNumOfOverflows

判断当前时间是否达到预计时间, 若达到解锁队列,恢复调度器xTaskResumeAll

预计时间xTicksToWait会在每次获取xTickCount 后更新减少。因为后续会会在新的xTickCount 的基础上计算xTimeToWake

xTickCount 是系统滴答定时器会在中断服务里递增。(xTaskIncrementTick

若在等待的过程中,队列有空闲,解锁队列,恢复调度器(每次进入 入队函数会尝试发送,try again)

以上涉及到的list

挂起列表xSuspendedTaskList

延时列表pxDelayedTaskList

 

溢出延时列表pxOverflowDelayedTaskList


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM