freertos通讯---信号量与队列

哈喽,又见面了.

一.信号量

1.1创建二进制信号量

#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )

上篇队列已经提到,信号量也是用队列实现的.这里semSEMAPHORE_QUEUE_ITEM_LENGTH是0,最后一个参数queueQUEUE_TYPE_BINARY_SEMAPHORE其实没有使用.

1.2创建计数信号量

#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )

freertos通讯---信号量与队列

计数信号量和二进制其实一样

 

1.3创建互斥锁

#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )

freertos通讯---信号量与队列

freertos通讯---信号量与队列

互斥锁创建稍有不同.其中uxQueueType是一个宏定义,本质上是pchead.用NULL指针来区分信号量和互斥锁.

freertos通讯---信号量与队列

freertos通讯---信号量与队列

亲爱的观众朋友们,是不是特别眼熟,不是脸盲(美女我还是认得清楚,哈哈)

这不是就是队列发送的套路吗?

为什么要在这里释放一次了?秘密就在prvCopyDataToQueue函数,来再看一眼

freertos通讯---信号量与队列

这里我截取了互斥锁的操作.

freertos通讯---信号量与队列

优先级反转恢复.

互斥锁只能用于任务,中断中不能使用.互斥锁必须获取后再释放.必须形成一个闭环的操作.而信号量不需要,信号量只是单身狗,

注定是要孤独一辈子的.

 

2.1信号量释放

#define xSemaphoreGive( xSemaphore )        xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )

熟悉吗?互斥锁创建时也释放了一次,因为uxMessagesWaiting是0,任务要获取锁成功,所以创建时必须主动释放.

 

3.2信号量获取

#define xSemaphoreTake( xSemaphore, xBlockTime )        xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) )

freertos通讯---信号量与队列

freertos通讯---信号量与队列

freertos通讯---信号量与队列

哈哈,脸熟,脸盲.

就是多了互斥锁的一些操作,其他和队列的获取基本一致.

来看看互斥锁多了哪些操作

1.首先当前任务pxCurrentTCB->uxMutexesHeld加1.表明当前任务在使用互斥锁了

2.如果阻塞等待,判断是否需要优先级继承.函数xTaskPriorityInherit处理这部分

3.如果获取到互斥锁的任务发生了优先级继承,此时另外一个任务等待超时后,仍然没有获取到锁,那么恢复获取到互斥锁任务的优先级到初始的优先级.

freertos通讯---信号量与队列

freertos通讯---信号量与队列

以上就是继承和反继承的代码.逻辑还是很清晰的

 

4.思考与总结

信号量和互斥量作为任务通讯的方式,由于使用队列实现,效率不高

所以作者推荐使用任务通知的方式实现简单信号量和互斥锁的功能

下一章讲解任务的通知