免费招聘网站建设英文网站外链查询
采用二值信号量同步
二值信号量可以在某个特殊的中断发生时,让任务解除阻塞,相当于让任务与中断
 同步。这样就可以让中断事件处理量大的工作在同步任务中完成,中断服务例程(ISR)
 中只是快速处理少部份工作。如此,中断处理可以说是被”推迟(deferred)”到一个”处理
 (handler)”任务。
 如果某个中断处理要求特别紧急,其延迟处理任务的优先级可以设为最高,以保证
 延迟处理任务随时都抢占系统中的其它任务。这样,延迟处理任务就成为其对应的 ISR
 退出后第一个执行的任务,在时间上紧接着 ISR 执行,相当于所有的处理都在 ISR 中
 完成一样。这种方案在图 图 26 中展现。

延迟处理任务对一个信号量进行带阻塞性质的”take”调用,意思是进入阻塞态以等
 待事件发生。当事件发生后,ISR 对同一个信号量进行”give”操作,使得延迟处理任务
 解除阻塞,从而事件在延迟处理任务中得到相应的处理。
 “获取(Taking,带走,按通常的说法译为获取)”和”给出(Giving)”信号量从概念上讲,
不同的应用场合有不同的含义。在经典的信号量术语中,获取信号量等同于一个 P()
 操作,而给出信号量等同于一个 V()操作。
在这种中断同步的情形下,信号量可以看作是一个深度为 1 的队列。这个队列由于
 最多只能保存一个数据单元,所以其不为空则为满(所谓”二值”)。延迟处理任务调用
 xSemaphoreTake()时,等效于带阻塞时间地读取队列,如果队列为空的话任务则进入
 阻塞态。当事件发生后,ISR 简单地通过调用 xSemaphoreGiveFromISR()放置一个令
 牌(信号量)到队列中,使得队列成为满状态。这也使得延迟处理任务切出阻塞态,并移
 除令牌,使得队列再次成为空。当任务完成处理后,再次读取队列,发现队列为空,又
 进入阻塞态,等待下一次事件发生。整个流程在图 图 27 中有所展现。
 如图 图 27 所示,中断给出信号量,甚至是在信号量第一次被获取之前就给出;而任
 务在获取信号量之后再也不给回来。这就是为什么说这种情况与读写队列相似。这也经
 常会给大家造成迷惑,因为这种情形和其它信号量的使用场合大不相同。在其它场合下,
 任务获得(Take)了信号量之后,必须得给(Give)回来——如同第四章描述一样。
vSemaphoreCreateBinary() API 函数
 FreeRTOS 中各种信号量的句柄都存储在 xSemaphoreHandle 类型的变量中。
 在 使 用 信 号 量 之 前 , 必 须 先 创 建 它 。 创 建 二 值 信 号 量 使 用
 vSemaphoreCreateBinary()API 函数
 void vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore );
xSemaphore 创建的信号量
 需要说明的是 vSemaphoreCreateBinary()在实现上是一个宏,所以
 信号量变量应当直接传入,而不是传址。本章中包含本函数调用的示
 例可用于参考进行复制。

xSemaphoreTake() API 函数
 “带走(Taking)”一个信号量意为”获取(Obtain)”或”接收(Receive)”信号量。只有当信
 号量有效的时候才可以被获取。在经典信号量术中,xSemaphoreTake()等同于一次 P()
 操作。
 除互斥信号量(Recursive Semaphore,直译为递归信号量,按通常的说法译为互
 斥信号量)外,所有类型的信号量都可以调用函数 xSemaphoreTake()来获取。
 但 xSemaphoreTake()不能在中断服务例程中调用。
portBASE_TYPE xSemaphoreTake( xSemaphoreHandle xSemaphore, portTickType xTicksToWait );
xSemaphore 获取得到的信号量
 信号量由定义为 xSemaphoreHandle 类型的变量引用。信号量在使
 用前必须先创建。
 xTicksToWait 阻塞超时时间。任务进入阻塞态以等待信号量有效的最长时间。
 如果 xTicksToWait 为 0,则 xSemaphoreTake()在信号量无效时会
 立即返回。
 阻塞时间是以系统心跳周期为单位的,所以绝对时间取决于系统心
 跳频率。常量 portTICK_RATE_MS 可以用来把心跳时间单位转换
 为毫秒时间单位。
 如 果 把 xTicksToWait 设 置 为 portMAX_DELAY , 并 且 在
 FreeRTOSConig.h 中设定 INCLUDE_vTaskSuspend 为 1,那么阻
 塞等待将没有超时限制。
返回值 有两个可能的返回值:
 1. pdPASS
 只有一种情况会返回 pdPASS,那就是成功获得信号量。
 如果设定了阻塞超时时间(xTicksToWait 非 0),在函数返回之前任务
 将被转移到阻塞态以等待信号量有效。如果在超时到来前信号量变
 为有效,亦可被成功获取,返回 pdPASS。
 2. pdFALSE
 未能获得信号量。
 如果设定了阻塞超时时间(xTicksToWait 非 0),在函数返回之前任
 务将被转移到阻塞态以等待信号量有效。但直到超时信号量也没有
 变为有效,所以不会获得信号量,返回 pdFALSE。
xSemaphoreGiveFromISR() API 函数
 除互斥信号量外,FreeRTOS 支持的其它类型的信号量都可以通过调用
 xSemaphoreGiveFromISR()给出。
 xSemaphoreGiveFromISR()是 xSemaphoreGive()的特殊形式,专门用于中断服务
 例程中。
 portBASE_TYPE xSemaphoreGiveFromISR( xSemaphoreHandle xSemaphore,
 portBASE_TYPE *pxHigherPriorityTaskWoken );
xSemaphore 给出的信号量
 信号量由定义为 xSemaphoreHandle 类型的变量引用。
 信号量在使用前必须先创建。
 pxHigherPriorityTaskWoken 对某个信号量而言,可能有不止一个任务处于阻塞态在
 等待其有效。调用 xSemaphoreGiveFromISR()会让信
 号量变为有效,所以会让其中一个等待任务切出阻塞
 态。如果调用 xSemaphoreGiveFromISR()使得一个任
 务解除阻塞,并且这个任务的优先级高于当前任务(也就
 是被中断的任务),那么 xSemaphoreGiveFromISR()会
 在 函 数 内 部 将 *pxHigherPriorityTaskWoken 设 为
 pdTRUE。
 如 果 xSemaphoreGiveFromISR() 将 此 值 设 为
 pdTRUE,则在中断退出前应当进行一次上下文切换。
 这样才能保证中断直接返回到就绪态任务中优先级最
 高的任务中。
 返回值 有两个可能的返回值:
 1. pdPASS
 xSemaphoreGiveFromISR()调用成功。
 2. pdFAIL
 如果信号量已经有效,无法给出,则返回 pdFAIL。
