1.5 获取信号量
获取信号量也有两个函数,如表 14.2.5.1 所示:
同释放信号量的 API 函数一样,不管是二值信号量、计数型信号量还是互斥信号量,它们 都使用表 14.2.5.1 中的函数获取信号量。
1 、函数 xSemaphoreTake()
此函数用于获取二值信号量、计数型信号量或互斥信号量,此函数是一个宏,真正获取信 号量的过程是由函数 xQueueGenericReceive ()来完成的,函数原型如下:
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore,
TickType_t xBlockTime)
参数:
xSemaphore :要获取的信号量句柄。
xBlockTime: 阻塞时间。
返回值:
pdTRUE: 获取信号量成功。
pdFALSE: 超时,获取信号量失败。
再来看一下函数 xSemaphoreTake ()的具体内容,此函数在文件 semphr.h 中有如下定义:
#define xSemaphoreTake( xSemaphore, xBlockTime ) \
xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), \
NULL, \
( xBlockTime ), \
pdFALSE ) \
获取信号量的过程其实就是读取队列的过程,只是这里并不是为了读取队列中的消息。在 第十三章讲解函数 xQueueGenericReceive()的时候说过如果队列为空并且阻塞时间为 0 的话就 立即返回 errQUEUE_EMPTY,表示队列满。如果队列为空并且阻塞时间不为 0 的话就将任务 添加到延时列表中。如果队列不为空的话就从队列中读取数据(获取信号量不执行这一步),数 据读取完成以后还需要将队列结构体成员变量 uxMessagesWaiting 减一,然后解除某些因为入 队而阻塞的任务,最后返回 pdPASS 表示出对成功。互斥信号量涉及到优先级继承,处理方式 不同,后面讲解互斥信号量的时候在详细的讲解。
2 、函数 xSemaphoreTakeFromISR ()
此函数用于在中断服务函数中获取信号量,此函数用于获取二值信号量和计数型信号量, 绝 对 不 能 使 用 此 函 数 来 获 取 互 斥 信 号 量 ! 此 函 数 是 一 个 宏 , 真 正 执 行 的 是 函 数
xQueueReceiveFromISR (),此函数原型如下:
BaseType_t xSemaphoreTakeFromISR(SemaphoreHandle_t xSemaphore,
BaseType_t * pxHigherPriorityTaskWoken)
参数:
xSemaphore: 要获取的信号量句柄。
pxHigherPriorityTaskWoken: 标记退出此函数以后是否进行任务切换,这个变量的值由这
三个函数来设置的,用户不用进行设置,用户只需要提供一 个变量来保存这个值就行了。当此值为 pdTRUE 的时候在退
出中断服务函数之前一定要进行一次任务切换。
返回值:
pdPASS: 获取信号量成功。
pdFALSE: 获取信号量失败。
在中断中获取信号量真正使用的是函数 xQueueReceiveFromISR (),这个函数就是中断级 出队函数!当队列不为空的时候就拷贝队列中的数据(用于信号量的时候不需要这一步),然后 将队列结构体中的成员变量 uxMessagesWaiting 减一,如果有任务因为入队而阻塞的话就解除 阻塞态,当解除阻塞的任务拥有更高优先级的话就将参数pxHigherPriorityTaskWoken 设置为 pdTRUE,最后返回 pdPASS 表示出队成功。如果队列为空的话就直接返回 pdFAIL 表示出队失 败!这个函数还是很简单的。
|