FreeRTOS_信号量
FreeRTOS(4)信号量
信号量API函数实际上都是宏,它使用现有的队列机制。这些宏定义在semphr.h文件中。如果使用信号量或者互斥量,需要包含semphr.h头文件。
一、创建信号量
- ==二进制信号量==创建实际上是直接使用通用队列创建函数xQueueGenericCreate()。创建二进制信号量API接口实际上是一个宏,定义如下:
1 |
2.==计数信号量==的创建间接使用通用队列创建函数xQueueGenericCreate()。创建计数信号量API接口同样是个宏定义:
1 |
创建计数信号量API接口有两个参数,含义如下:
- uxMaxCount:最大计数值,当信号到达这个值后,就不再增长了。
- uxInitialCount:创建信号量时的初始值。
二、释放信号量
- xSemaphoreGive()
用于释放一个信号量,不带中断保护。被释放的信号量可以是二进制信号量、计数信号量和互斥量。注意递归互斥量并不能使用这个API函数释放。其实信号量释放是一个宏,真正调用的函数是xQueueGenericSend(),宏定义如下:
1 |
可以看出释放信号量实际上是一次入队操作,并且阻塞时间为0(由宏semGIVE_BLOCK_TIME定义)。
对于二进制信号量和计数信号量,根据上一章的内容可以总结出,释放一个信号量的过程实际上可以简化为两种情况:第一,如果队列未满,队列结构体成员uxMessageWaiting加1,判断是否有阻塞的任务,有的话解除阻塞,然后返回成功信息(pdPASS);第二,如果队列满,返回错误代码(err_QUEUE_FULL),表示队列满。
xSemaphoreGiveFromISR()
用于释放一个信号量,带中断保护。被释放的信号量可以是**二进制信号量**和**计数信号量**。和普通版本的释放信号量API函数不同,它不能释放互斥量,这是因为互斥量不可以在中断中使用!互斥量的优先级继承机制只能在任务中起作用,在中断中毫无意义。带中断保护的信号量释放其实也是一个宏,真正调用的函数是xQueueGiveFromISR (),宏定义如下:
1 | definexSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) \ |
三、获取信号量
无论二进制信号量、计数信号量还是互斥量,它们都使用相同的获取和释放API函数。
在收到信号量之前,任务一直处于阻塞态并开始计时。
- 若时间到了还没收到信号,会自动执行后边的语句并返回pdFALSE,如果收到了信号返回PDTRUE
- 阻塞时间是xBlockTime
如果为0,则阻塞0ms,相当于一直在while循环,==如果有N个信号量,会被一瞬间消耗完==
如果阻塞HAL_MAXDELAY,则任务一直在阻塞态,if后边的语句将不会执行。
获取信号量分为不带中断保护和带中断保护两个版本。
xSemaphoreTake()
用于获取信号量,==该函数运行后,指定的信号量的队列长度-1==.不带中断保护。获取的信号量可以是二进制信号量、计数信号量和互斥量。注意递归互斥量并不能使用这个API函数获取。其实获取信号量是一个宏,真正调用的函数是xQueueGenericReceive (),宏定义如下:
1 | definexSemaphoreTake( xSemaphore, xBlockTime ) \ |
xSemaphoreTakeFromISR()
用于获取信号量,带中断保护。获取的信号量可以是二进制信号量和计数信号量。和普通版本的获取信号量API函数不同,它不能获取互斥量,这是因为互斥量不可以在中断中使用!互斥量的优先级继承机制只能在任务中起作用,在中断中毫无意义。带中断保护的获取信号量其实也是一个宏,真正调用的函数是xQueueReceiveFromISR (),宏定义如下:
1 | definexSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) \ |
四、得到指定信号量中队列长度
1 |
- 如果xSemaphore是一个计数信号量,则返回它当前总的信号量个数
- 如果xSemaphore是一个二值信号量,则它只会返回0或1
五、例子
1 | /* .h信号量全局定义 */ |
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.