使用 Arduino 的 FreeRTOS 中的信号量和互斥量

Semaphore 和 Mutex 是在 FreeRTOS 中实现任务之间同步的工具/机制。通常,两个任务需要共享一个资源,或者一个任务需要告诉另一个任务它处于空闲/等待状态。信号量和互斥锁在这里有帮助。在本文中,我们将了解信号量和互斥量的概念。

信号

信号量是任务之间的同步机制。更具体地说,它是一种信号机制。处于等待状态的任务可能会收到一个信号量,它告诉它做一些工作。一旦任务完成了这项工作,它将返回信号量。实际上,这是由整数维护的。有两种类型的信号量:二进制信号量和计数信号量。

二进制信号量

这类似于长度为 1 的队列。它只能取 0 和 1 作为整数值。假设有两个任务:任务 A 和任务 B。如果任务 A 需要向任务 B 发送一些定期通信(比如数据交换),那么它使用这个二进制信号量进行通信。当数据可用时,它将信号量值设置为 1(任务 A 在这里“给出”信号量)。持续监视信号量的任务 B 将在值为 1 时读取数据。然后将队列的值设置回 0(任务 B,因此,“获取”信号量),并再次等待数据可用。这样,任务 A 和 B 之间就实现了同步。

计数信号量

在这种情况下,队列的长度没有限制。这用于事件管理。每次事件发生时,事件处理程序都会通过增加计数值来“给出”信号量。每次任务处理事件时,它都会通过递减计数来表明它已经“获取”了信号量。任何给定时间点的计数显示发生的事件数与处理的事件数之间的差异。

互斥体

互斥(互斥)是一种锁定机制,可防止共享资源损坏。假设您有一个被多个任务访问的 SD 卡。如果多个任务同时访问它,则有可能损坏 SD 卡内的数据(可能两者都写入同一个内存区域,导致垃圾)。

为了避免这种情况,我们使用了互斥锁。它就像一个令牌。如果任务具有此令牌,则只有该任务可以访问特定资源。其他任务必须等到该任务释放令牌。如果您有多个资源(如 OLED 屏幕、SD 卡、串口等)需要保护,您可以使用多个令牌,每个资源一个。

实际上,Mutex 使用与二进制信号量相同的 API 函数。唯一的区别是互斥体具有优先继承权。FreeRTOS文档将其描述为 -

“如果高优先级任务在尝试获取当前由较低优先级任务持有的互斥锁(令牌)时阻塞,那么持有令牌的任务的优先级会暂时提高到阻塞任务的优先级。这种机制旨在确保较高优先级的任务在尽可能短的时间内保持阻塞状态,从而最大限度地减少已经发生的‘优先级反转’。”

为了了解信号量和互斥锁的实际实现,您可以查看 FreeRTOS 库附带的以下示例:互斥锁、AnalogRead_DigitalRead、中断。