FreeRTOS源码阅读笔记(二)------队列、信号量

 历史文章: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队列解锁,恢复调度器,进行任务切换

  • 34
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值