https://blog.csdn.net/zhzht19861011/article/details/50920336
FreeRTOS的信号量包括二进制信号量、计数信号量、互斥信号量(以后简称互斥量)和递归互斥信号量(以后简称递归互斥量)。我们可以把互斥量和递归互斥量看成特殊的信号量。
信号量API函数实际上都是宏,它使用现有的队列机制。这些宏定义在semphr.h文件中。如果使用信号量或者互斥量,需要包含semphr.h头文件。
二进制信号量、计数信号量和互斥量信号量的创建API函数是独立的,但是获取和释放API函数都是相同的;递归互斥信号量的创建、获取和释放API函数都是独立的。
1创建二进制信号量
1.1函数描述
SemaphoreHandle_t xSemaphoreCreateBinary( void );
这个函数用于创建一个二进制信号量。二进制信号量要么有效要么无效,这也是为什么叫做二进制的原因。
新创建的信号量处于无效状态,这意味着使用API函数xSemaphoreTake()获取信号之前,需要先给出信号。
二进制信号量和互斥量非常相似,但也有细微的区别:互斥量具有优先级继承机制,二进制信号量没有这个机制。这使得二进制信号量更适合用于同步(任务之间或者任务和中断之间),互斥量更适合互锁。
一旦获得二进制信号量后不需要恢复,一个任务或中断不断的产生信号,而另一个任务不断的取走这个信号,通过这样的方式来实现同步。
低优先级任务Task1拥有互斥量的时候,如果另一个高优先级任务Task2也企图获取这个信号量,则低优先级任务 Task1的优先级会被临时提高,提高到和高优先级任务 Task2相同的优先级(这就是操作系统中的优先级翻转), 这样Task1 就不会被 Task2 抢断,否则高优先级任务 Task2将永远不能获取这个互斥量,并且那个拥有互斥量的低优先级任务 Task1 也永远不会被调度.。
互斥量和二进制信号量都是SemaphoreHandle_t类型,并且可以用于任何具有这类参数的API函数中。
1.1.2返回值
NULL:创建信号量失败,因为FreeRTOS堆栈不足。
其它值:信号量创建成功。这个返回值存储着信号量句柄。
1.1.3用法举例
SemaphoreHandle_t xSemaphore;
voidvATask(voidvoid* pvParameters )
{
/* 创建信号量 */
xSemaphore = xSemaphoreCreateBinary();
if( xSemaphore ==NULL)
{
/* 因堆栈不足,信号量创建失败,这里进行失败处理*/
}
else
{
/* 信号量可以使用。信号量句柄存储在变量xSemahore中。
如果在这里调用API函数xSemahoreTake()来获取信号量,
则必然是失败的,因为创建的信号量初始是无效(空)的。*/
}
}
2创建计数信号量
2.1函数描述
SemaphoreHandle_t xSemaphoreCreateCounting ( UBaseType_t uxMaxCount,
UBaseType_t uxInitialCount )
创建计数信号量,计数信号量通常用于以下两种情况:
事件计数:在这种应用场合,每当事件发生,事件处理程序会“产生”一个信号量(信号量计数值会递增),每当处理任务处理事件,会取走一个信号量(信号量计数值会递减)。因此,事件发生或者事件被处理后,计数值是会变化的。
资源管理:在这种应用场合下,计数值表示有效资源的数目。为了获得资源,任务首先要获得一个信号量---递减信号量计数值。当计数值为0时,表示没有可用的资源。当占有资源的任务完成,它会释放这个资源,相应的信号量计数值会增一。计数值达到初始值(最大值)表示所有资源都可用。
2.2参数描述
uxMaxCount:最大计数值,当信号到达这个值后,就不再增长了。
uxInitialCount:创建信号量时的初始值。
2.3返回值
NULL表示信号量创建失败,否则返回信号量句柄。
2.4用法举例
voidvATask(voidvoid* pvParameters )
{
xSemaphoreHandle xSemaphore;