FreeRTOS的学习系列文章目录
FreeRTOS的学习(一)——STM32上的移植问题
FreeRTOS的学习(二)——任务优先级问题
FreeRTOS的学习(三)——中断机制
FreeRTOS的学习(四)——列表
FreeRTOS的学习(五)——系统延时
FreeRTOS的学习(六)——系统时钟
FreeRTOS的学习(七)——1.队列概念
FreeRTOS的学习(七)——2.队列入队源码分析
FreeRTOS的学习(七)——3.队列出队源码分析
FreeRTOS的学习(八)——1.二值信号量
FreeRTOS的学习(八)——2.计数型信号量
FreeRTOS的学习(八)——3.优先级翻转问题
FreeRTOS的学习(八)——4.互斥信号量
FreeRTOS的学习(九)——软件定时器
FreeRTOS的学习(十)——事件标志组
FreeRTOS的学习(十一)——任务通知
前言
信号量可以认为是队列的一种表达形式,他的存在给予了任务和任务,任务和中断之间的资源访问形式。
- 信号量常被用于控制对共享资源的访问和任务同步,可以对资源的变化进行计数,或者判断是否使用某资源等。
- 另外信号量还常用于任务同步,用于任务于任务或者中断与任务之间的同步。
FreeRTOS中具有非常多的信号量,比如计数信号量,二值信号量,互斥信号量和递归互斥信号量,其存在在某些情况下亦可以用队列的功能去替换。
1 计数型信号量简介
有些资料中也将计数型信号量叫做数值信号量,二值信号量相当于长度为 1 的队列,那么
计数型信号量就是长度大于 1 的队列。同二值信号量一样,用户不需要关心队列中存储了什么
数据,只需要关心队列是否为空即可。计数型信号量通常用于如下两个场合:
- 事件计数
在这个场合中,每次事件发生的时候就在事件处理函数中释放信号量(增加信号量的计数值),其他任务会获取信号量(信号量计数值减一,信号量值就是队列结构体成员变量uxMessagesWaiting)来处理事件。在这种场合中创建的计数型信号量初始计数值为 0。- 资源管理
在这个场合中,信号量值代表当前资源的可用数量,一个任务要想获得资源的使用权,首先必须获取信号量,信号量获取成功以后信号量值就会减一。当信号量值为 0 的时候说明没有资源了。当一个任务使用完资源以后一定要释放信号量,释放信号量以后信号量值会加一。在这个场合中创建的计数型信号量初始值应该是资源的数量,
2 二值信号量的创建
二值信号量的创建函数如下:
- xSemaphoreCreateCounting(),使用动态方法创建计数型信号量。
- xSemaphoreCreateCountingStatic(),使用静态方法创建计数型信号量
函数的定义如下:
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
#endif
可以发现,真正干事的是xQueueCreateCountingSemaphore函数,这与二值信号量的创建函数不同,该函数在queue中定义如下:
#if ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
const UBaseType_t uxInitialCount )
{
QueueHandle_t xHandle = NULL;
if( ( uxMaxCount != 0 ) &&
( uxInitialCount <= uxMaxCount ) )
{
xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
if( xHandle != NULL )
{
( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;
traceCREATE_COUNTING_SEMAPHORE();
}
else
{
traceCREATE_COUNTING_SEMAPHORE_FAILED();
}
}
else
{
configASSERT( xHandle );
mtCOVERAGE_TEST_MARKER();
}
return xHandle;
}
#endif
该函数首先对函数的形参做了判断,也就是要求( uxMaxCount != 0 ) && ( uxInitialCount <= uxMaxCount ),相比于旧版的函数(没有这个判断)显然多了一重保障。
其次,调用了队列的创建函数xQueueGenericCreate,并给定队列的长度(uxMaxCount)以及队列生成的类型(queueQUEUE_TYPE_COUNTING_SEMAPHORE),其中信号量队列项的长度选择默认0(queueSEMAPHORE_QUEUE_ITEM_LENGTH)。
最后将初始计数值uxInitialCount赋值给uxMessagesWaiting,队列结构体的成员变量 uxMessagesWaiting 用于计数型信号量的计数。
3 信号量的释放和获取
释放和获取计数型信号量的方式与二值信号量相同,这里不再赘述。