FreeRTOS消息队列、信号量、互斥量、递归互斥量实现步骤

消息队列

消息队列结构

由消息队列控制块+消息存储buffer组成,是全局变量,结构如下
在这里插入图片描述
消息队列控制块中的链表

	List_t xTasksWaitingToSend;	//记录发送阻塞的TCB
	List_t xTasksWaitingToReceive;//记录接收阻塞的TCB
读队列步骤
 step1.关中断 
 step2.如果buffer中有数据,goto step3
       如果buffer中没数据,
          如果xTicksToWait=0,开中断,返回ERR
          如果xTicksToWait!=0,
              把当前TCB记录到xTasksWaitingToReceive
              把当前TCB从xReadyTasksLists移调到xDelayedTaskList让当前任务休眠
 step3.从环形buffer拷贝数据
       把xTasksWaitingToSend列表上的第一个TCB移除
       把xTasksWaitingToSend列表上的第一个TCB从xDelayedTaskList移调到xReadyTasksLists唤醒需要发送的任务
 step4.开中断
写队列步骤
 step1.关中断 
 step2.如果buffer中还能写数据,goto step3
       如果buffer中数据满了,
          如果xTicksToWait=0,开中断,返回ERR
          如果xTicksToWait!=0,
              把当前TCB记录到xTasksWaitingToSend
              把当前TCB从xReadyTasksLists移调到xDelayedTaskList让当前任务休眠
 step3.拷贝数据到环形buffer
       把xTasksWaitingToReceive列表上的第一个TCB移除
       把xTasksWaitingToReceive列表上的第一个TCB从xDelayedTaskList移调到xReadyTasksLists唤醒需要发送的任务
 step4.开中断

注意,上述是有任务主控发送接收导致对端唤醒,还有一种方式是延时时间到了由tick中断来唤醒

作用

常用于任务间数据传递

信号量

信号量结构

信号量借用的消息队列数据结构,用uxMessagesWaiting来代指资源个数,二值信号量就是这个值只能是0和1,且没有后面的buffer,如下,所以发送接收和队列基本相同
在这里插入图片描述

获取信号量
 step1.关中断 
 step2.如果uxMessagesWaiting>0goto step3
       如果uxMessagesWaiting=0,
          如果xTicksToWait=0,开中断,返回ERR
          如果xTicksToWait!=0,
              把当前TCB记录到xTasksWaitingToReceive
              把当前TCB从xReadyTasksLists移调到xDelayedTaskList让当前任务休眠
 step3.uxMessagesWaiting--
       把xTasksWaitingToSend列表上的第一个TCB移除
       把xTasksWaitingToSend列表上的第一个TCB从xDelayedTaskList移调到xReadyTasksLists唤醒需要发送的任务
 step4.开中断
释放信号量
 step1.关中断 
 step2.如果uxMessagesWaiting已经是最大值,开中断,返回ERR
 step3.uxMessagesWaiting++
       把xTasksWaitingToReceive列表上的第一个TCB移除
       把xTasksWaitingToReceive列表上的第一个TCB从xDelayedTaskList移调到xReadyTasksLists唤醒需要发送的任务
 step4.开中断

注,二值信号量存在优先级翻转问题,就是高优先级任务因为低优先级任务占用了资源且低优先级任务被高于他优先级任务抢占导致不能运行,这样高优先级就一直阻塞住了,为了解决此问题(减小影响)设计了互斥量

互斥量(锁)

互斥量结构

互斥量就是二值信号量+优先级继承,xMutexHolder保存拿到此资源的TCB,TCB中还有一个uxBasePriority用于保存此任务创建时的优先级
在这里插入图片描述

获取互斥量
 step1.关中断 
 step2.如果uxMessagesWaiting>0,xMutexHolder记录TCB,goto step3
       如果uxMessagesWaiting=0,
          如果xTicksToWait=0,开中断,返回ERR
          如果xTicksToWait!=0,
              用当前任务优先级改写xMutexHolder任务优先级
              把当前TCB记录到xTasksWaitingToReceive
              把当前TCB从xReadyTasksLists移调到xDelayedTaskList让当前任务休眠
 step3.uxMessagesWaiting--
       把xTasksWaitingToSend列表上的第一个TCB移除
       把xTasksWaitingToSend列表上的第一个TCB从xDelayedTaskList移调到xReadyTasksLists唤醒需要发送的任务
 step4.开中断
释放互斥量
 step1.关中断 
 step2.如果uxMessagesWaiting已经是最大值,开中断,返回ERR
 step3.uxMessagesWaiting++
       用uxBasePriority来恢复自身优先级
       把xTasksWaitingToReceive列表上的第一个TCB移除
       把xTasksWaitingToReceive列表上的第一个TCB从xDelayedTaskList移调到xReadyTasksLists唤醒需要发送的任务
 step4.开中断

注,FreeRTOS没有实现谁take谁give的限制,所以一个task take,另一个task give在代码上是能跑通的,要注意这点
还有死锁问题,一个任务先take后再次take,此任务就被阻塞了,无法唤醒,自我死锁,此时需要用递归互斥量

递归互斥量(递归锁)

递归互斥量和临界区嵌套设计方式一样,uxRecursiveCallCount来记录递归次数,且递归互斥量实现了谁take谁give的限制。

获取递归互斥量
如果xMutexHolder == 当前TCB,uxRecursiveCallCount++,返回
如果xMutexHolder != 当前TCB,调用互斥量take,返回
释放递归互斥量
如果xMutexHolder == 当前TCB,uxRecursiveCallCount--,
      如果uxRecursiveCallCount==0,调用互斥量give
如果xMutexHolder != 当前TCB,返回
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值