FreeRTOS学习笔记 & 信号量
信号量 (Sempher)
信号量概述
- 信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务之间同步
二值信号量 (Binary)
- 二值信号量既可以用于临界资源访问也可以用于同步功能
- 用作同步时,信号量在创建后应被置为空,任务 1 获取信号量而进入阻塞,任务 2 在某种条件发生后,释放信号量,于是任务 1 获得信号量得以进入就绪态,如果任务 1 的优先级是最高的,那么就会立即切换任务,从而达到了两个任务间的同步。同样的,在中断服务函数中释放信号量,任务 1 也会得到信号量,从而达到任务与中断间的同步
- 可以将二值信号量看作只有一个消息的队列,因此这个队列只能为空或满(因此称为二值),我们在运用的时候只需要知道队列中是否有消息即可,而无需关注消息是什么
二值信号量 API 函数
xSemaphoreCreateBinary() //创建一个二值信号量
xSemaphoreGive( xSemaphore ) //释放二值信号量 (任务中使用)
xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) (中断中使用)
xSemaphoreTake( xSemaphore, xBlockTime ) //获取二值信号量 (任务中使用)
xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) (中断中使用)
要使 xSemaphoreCreateBinary() 此 RTOS API 函数可用:
configSUPPORT_DYNAMIC_ALLOCATION 必须在 FreeRTOSConfig.h 中设置为 1
RTOS 源文件 FreeRTOS/source/Sempher.h 必须包含在工程中
SemaphoreHandle_t Semaphore_test = NULL ;//创建二值信号量句柄
void Task_Semaphore_Give(void const * argument)
{
/* 调用创建二值信号量API,创建成功返回信号量句柄,失败返回NULL. */
Semaphore_test = xSemaphoreCreateBinary();
/* 判断句柄,确认是否创建成功? */
if( Semaphore_test == NULL )
{
/* 创建失败执行内部代码. */
}
else
{
/* 创建成功执行内部代码. */
xSemaphoreGive( Semaphore_test );
}
}
void Task_Semaphore_Take(void const * argument)
{
for(;;;)
{
/* 调用获取二值信号量API,获取不到信号量任务进入阻塞态,获取成功程序往下运行. */
xSemaphoreTake( Semaphore_test , portMAX_DELAY);
}
}
void IRQ_Handle(void)
{
BaseType_t xTaskWokenByReceive = pdFALSE;
xSemaphoreGiveFromISR( Semaphore_test , &xTaskWokenByReceive );
portYIELD_FROM_ISR( xTaskWokenByReceive );
xSemaphoreTakeFromISR( Semaphore_test , &xTaskWokenByReceive );
portYIELD_FROM_ISR( xTaskWokenByReceive );
}
计数信号量 (Counting)
- 二进制信号量可以被认为是长度为 1 的队列,而计数信号量则可以被认为长度大于 1 的队列,信号量使用者依然不必关心存储在队列中的消息,只需关心队列是否有消息即可
计数信号量 API 函数
SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount,UBaseType_t uxInitialCount); //创建一个计数信号量
参数:
uxMaxCount 可以达到的最大计数值。 当信号量达到此