历史文章:FreeRTOS源码阅读笔记(一)------任务、列表
队列相关源码
1)创建队列 xQueueCreate 实际是xQueueGenericCreate
1.申请内存 pvPortMalloc(sizeof(Queue_t) + xQueueSizeInBytes)
2.判断内存是否申请成功
3.调用prvInitialiseNewQueue初始化队列
初始化队列结构体成员变量
调用xQueueGenericReset复位队列
进入临界区,初始化队列结构体其他成员变量
如果是新创建的,复位xTasksWaitingToSend和xTasksWaitingToReceive两个列表
退出临界区
2)往队列写数据 xQueueSend 实际是xQueueGenericSend
1.进入临界区
2.如果队列有空闲位置 pxQueue->uxMessagesWaiting < pxQueue->uxLength
prvCopyDataToQueue 将待写入消息按指定写入方式拷贝到队列中,队列项目个数加1
如果有因为读不到消息而阻塞的任务,xTaskRemoveFromEventList解除阻塞
如果调度器没有挂起
移除等待接收列表xTasksWaitingToReceive的第一个任务
prvAddTaskToReadyList添加任务到就绪列表
如果调度器被挂起
将事件列表项添加到等待就绪列表xPendingReadyList
如果解除阻塞的任务优先级大于当前任务优先级,则设置任务切换标志
退出临界区
3.如果没有位置
阻塞时间不为0,vTaskInternalSetTimeOutState 记录系统节拍和溢出次数
4.退出临界区
5.挂起调度器
6.prvLockQueue队列上锁,仍然需要阻塞
vTaskPlaceOnEventList 将任务事件列表项添加到等待发送列表xTasksWaitingToSend
prvAddCurrentTaskToDelayedList 将任务状态列表项添加到阻塞列表中进行阻塞
prvUnlockQueue队列解锁,恢复调度器,进行任务切换
3)往队列读数据 xQueueReceive
1.进入临界区
2.如果队列有数据 uxMessagesWaiting > 0
prvCopyDataFromQueue 从队列中拷贝数据,队列项目个数减1
如果有因为发送不了消息而阻塞的任务,xTaskRemoveFromEventList解除阻塞
如果调度器没有挂起
移除等待发送列表xTasksWaitingToSend的第一个任务
prvAddTaskToReadyList添加任务到就绪列表
如果调度器被挂起
将事件列表项添加到等待就绪列表xPendingReadyList
如果解除阻塞的任务优先级大于当前任务优先级,则设置任务切换标志
退出临界区
3.如果没有数据
阻塞时间不为0,vTaskInternalSetTimeOutState 记录系统节拍和溢出次数
4.退出临界区
5.挂起调度器
6.prvLockQueue队列上锁,仍然需要阻塞
vTaskPlaceOnEventList 将任务事件列表项添加到等待接收列表xTasksWaitingToReceive
prvAddCurrentTaskToDelayedList 将任务状态列表项添加到阻塞列表中进行阻塞
prvUnlockQueue队列解锁,恢复调度器,进行任务切换
信号量相关源码
1)创建二值信号量 xSemaphoreCreateBinary 实际是xQueueGenericCreate (信号量只有队列头,没有缓冲区。uxMessagesWaiting就是信号量的值)
1.实际调用的是xQueueGenericCreate(1,0,queueQUEUE_TYPE_BINARY_SEMAPHORE)
2.由于uxItemSize为0,申请的内存仅是信号量结构体大小
3.调用prvInitialiseNewQueue初始化队列
初始化队列结构体成员变量
调用xQueueGenericReset复位队列
2)创建计数型信号量 xSemaphoreCreateCounting 实际是xQueueCreateCountingSemaphore
1.调用xQueueGenericCreate(uxMaxCount,0,queueQUEUE_TYPE_COUNTING_SEMAPHORE);
2.uxMessagesWaiting是计数型信号量的初始值 xHandle->uxMessagesWaiting = uxInitialCount
3)创建互斥信号量 xSemaphoreCreateMutex 实际是xQueueCreateMutex
1.调用xQueueGenericCreate(1,0,queueQUEUE_TYPE_MUTEX);
2.prvInitialiseMutex初始化互斥量
主动释放一次互斥量
4)释放信号量 xSemaphoreGive 实际是xQueueGenericSend(xSemaphore,NULL,0,queueSEND_TO_BACK)
1.进入临界区
2.如果计数值为0
调用prvCopyDataToQueue计数值加1 pxQueue->uxMessagesWaiting = uxMessagesWaiting + 1
如果是互斥信号量,调用xTaskPriorityDisinherit改变任务优先级
当前任务互斥量的持有次数减1
先把持有者移除就绪列表,恢复持有者的优先级,再添加到就绪列表
如果有因为获取不了信号量而阻塞的任务,xTaskRemoveFromEventList解除阻塞
如果调度器没有挂起
移除等待接收列表xTasksWaitingToReceive的第一个任务
prvAddTaskToReadyList添加任务到就绪列表
如果调度器被挂起
将事件列表项添加到等待就绪列表xPendingReadyList
如果解除阻塞的任务优先级大于当前任务优先级,则设置任务切换标志
退出临界区
3.如果计数值最大,退出临界区,返回失败
5)获取信号量 xSemaphoreTake 实际是xQueueSemaphoreTake
1.进入临界区
2.如果计数值大于0,计数值减1
如果是互斥信号量,pvTaskIncrementMutexHeldCount 当前任务互斥量的持有次数加1
如果有因为释放不了信号而阻塞的任务,xTaskRemoveFromEventList解除阻塞
退出临界区,返回成功
3.如果计数值为0
阻塞时间不为0,vTaskInternalSetTimeOutState 记录系统节拍和溢出次数
4.退出临界区
5.挂起调度器
6.prvLockQueue队列上锁,仍然需要阻塞
如果是互斥信号量,调用xTaskPriorityInherit改变任务优先级
如果互斥量持有者的任务优先级小于当前任务优先级,且持有者任务在就绪列表
先把持有者移除就绪列表,提高持有者的优先级至当前优先级,再添加到就绪列表
vTaskPlaceOnEventList 将任务事件列表项添加到等待接收列表xTasksWaitingToReceive
prvAddCurrentTaskToDelayedList 将任务状态列表项添加到阻塞列表中进行阻塞
prvUnlockQueue队列解锁,恢复调度器,进行任务切换