Bootstrap

FreeRTOS之信号量

概述

  • 信号量本质上也是一个队列,只不过不涉及数据传输,只涉及数据个数的加加减减,换句话说就是传递状态。使用信号量效率更高、更节省内存
  • 分类
    • 计数型信号量(Counting Semaphores):量没有限制
    • 二进制信号量(Binary Semaphores):量只有 0、1 两个取值
  • 支持的动作:
    • "give"给出资源,计数值加 1
    • "take"获得资源,计数值减 1

队列和信号量对比

队列信号量
可以容纳多个数据,
创建队列时有2部分内存:队列结构体、存储数据的空间
只有计数值,无法容纳其他数据。
创建信号量时,只需要分配信号量结构体
生产者:没有空间存入数据时可以阻塞生产者:不阻塞,计数值已经达到最大时返回失败
消费者:没有数据时可以阻塞消费者:没有资源时可以阻塞

信号量函数

  • 使用信号量时,先创建、然后去添加资源、获得资源。使用句柄来表示一个信号量。

创建

二进制信号量计数型信号量
动态创建xSemaphoreCreateBinary
计数值初始值为 0
xSemaphoreCreateCounting
静态创建xSemaphoreCreateBinaryStaticxSemaphoreCreateCountingStatic
/* 创建一个二进制信号量,返回它的句柄。
* 此函数内部会分配信号量结构体
* 返回值: 返回句柄,非 NULL 表示成功
*/
SemaphoreHandle_t xSemaphoreCreateBinary( void );
/* 创建一个二进制信号量,返回它的句柄。
* 此函数无需动态分配内存,所以需要先有一个 StaticSemaphore_t 结构体,并传入它的
指针
* 返回值: 返回句柄,非 NULL 表示成功
*/
SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuf
fer );
/* 创建一个计数型信号量,返回它的句柄。
* 此函数内部会分配信号量结构体
* uxMaxCount: 最大计数值
* uxInitialCount: 初始计数值
* 返回值: 返回句柄,非 NULL 表示成功
*/
SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount, UBaseType_t
uxInitialCount);
/* 创建一个计数型信号量,返回它的句柄。
* 此函数无需动态分配内存,所以需要先有一个 StaticSemaphore_t 结构体,并传入它的
指针
* uxMaxCount: 最大计数值
* uxInitialCount: 初始计数值
* pxSemaphoreBuffer: StaticSemaphore_t 结构体指针
* 返回值: 返回句柄,非 NULL 表示成功
*/
SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphore
Buffer );

删除

对于动态创建的信号量,不再需要它们时,可以删除它们以回收内存

/*
* xSemaphore: 信号量句柄,你要删除哪个信号量
*/
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );

give/take

在任务中使用在ISR中使用
givexSemaphoreGivexSemaphoreGiveFromISR
takexSemaphoreTakexSemaphoreTakeFromISR
  • xSemaphoreGive的函数原型如下:
BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );
参数说明
xSemaphore信号量句柄,用于指定释放哪个信号量
返回值pdTRUE 表示成功。
如果二进制信号量的计数值已经是 1,再次调用此函数则返回失败;
如果计数型信号量的计数值已经是最大值,再次调用此函数则返回失败
  • pxHigherPriorityTaskWoken的函数原型如下:
BaseType_t xSemaphoreGiveFromISR(
SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken
);
参数说明
xSemaphore信号量句柄,用于指定释放哪个信号量
pxHigherPriorityTaskWoken如果释放信号量导致更高优先级的任务变为就绪态,则*pxHigherPriorityTaskWoken = pdTRUE
返回值pdTRUE 表示成功。如果二进制信号量的计数值已经是 1,再次调用此函数则返回失败;如果计数型信号量的计数值已经是最大值,再次调用此函数则返回失败
  • xSemaphoreTake的函数原型如下
BaseType_t xSemaphoreTake(
SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait
);
参数说明
xSemaphore信号量句柄,用于指定获取哪个信号量
xTicksToWait若无法立即获取信号量,设置阻塞方式:
0:不阻塞,立即返回
portMAX_DELAY:一直阻塞直至获取成功
其他值:阻塞的Tick个数,可使用pdMS_TO_TICKS()将阻塞时间指定为若干ms
返回值pdTRUE 表示获取信号量成功
  • xSemaphoreTakeFromISR的函数原型如下
BaseType_t xSemaphoreTakeFromISR(
SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken
);
参数说明
xSemaphore信号量句柄,用于指定获取哪个信号量
pxHigherPriorityTaskWoken若获取信号量导致更高优先级的任务变为就绪态,则*pxHigherPriorityTaskWoken = pdTRUE
返回值pdTRUE表示成功