亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial Internet of Things >> 嵌入式

信号量:介绍和基本服务


查看 RTOS Revealed 系列

信号量在之前的文章中介绍过。它们的主要用途是控制对资源的访问。

使用信号量

在 Nucleus SE 中,信号量是在构建时配置的。一个应用程序最多可以配置 16 个信号量。如果未配置信号量,则应用程序中不包含属于信号量的数据结构或服务调用代码。

信号量只是一个 U8 类型的计数器 ,对其的访问受到控制,以便多个任务可以安全地使用它。一个任务可以减少(获得)一个信号量并增加(释放)它。尝试获取值为零的信号量可能会导致错误或任务暂停,具体取决于 API 调用中选择的选项和 Nucleus SE 配置。

配置信号量

信号量数量

与 Nucleus SE 的大多数方面一样,信号量的配置主要由 #define 控制 nuse_config.h 中的语句 .关键设置是 NUSE_SEMAPHORE_NUMBER ,它决定了为应用程序配置了多少信号量。默认设置为 0(即没有使用信号量),您可以将其设置为最多 16 的任何值。错误的值将导致编译时错误,这是由 nuse_config_check.h<中的测试生成的/b> (这包含在 nuse_config.c 中 因此使用此模块编译)导致 #error 正在编译的语句。

选择非零值是信号量的“主启用”。这会导致一些数据结构被相应地定义和调整大小,本文稍后会详细介绍。它还激活 API 启用设置。

API 启用

Nucleus SE 中的每个 API 函数(服务调用)都有一个启用 #define nuse_config.h 中的符号 .对于信号量,这些是:

NUSE_SEMAPHORE_OBTAIN
NUSE_SEMAPHORE_RELEASE
NUSE_SEMAPHORE_RESET
NUSE_SEMAPHORE_INFORMATION
NUSE_SEMAPHORE_COUNT

默认情况下,所有这些都设置为 FALSE ,从而禁用每个服务调用并禁止包含任何实现代码。要为应用程序配置信号量,您需要选择要使用的 API 调用并将其启用符号设置为 TRUE .

这是默认 nuse_config.h 的摘录 文件。

#define NUSE_SEMAPHORE_NUMBER 0 /* 系统中信号量的数量 - 0-16 */#define NUSE_SEMAPHORE_OBTAIN FALSE /* 服务调用使能 */#define NUSE_SEMAPHORE_RELEASE FALSE /* 服务调用使能 */#define NUSE_SEMAPHORE_RESET调用使能 */#define NUSE_SEMAPHORE_INFORMATION FALSE /* 服务调用使能 */#define NUSE_SEMAPHORE_COUNT FALSE /* 服务调用使能 */

如果启用了信号量 API 功能并且未配置信号量(NUSE_Semaphore_Count() 除外),则会导致编译时错误 这总是被允许的)。如果您的代码使用未启用的 API 调用,则会导致链接时间错误,因为应用程序中不会包含任何实现代码。

信号量服务调用

Nucleus RTOS 支持八个属于信号量的服务调用,提供以下功能:

  • 获取信号量。由 NUSE_Semaphore_Obtain() 实现 在 Nucleus SE 中。

  • 释放信号量。由 NUSE_Semaphore_Release() 实现 在 Nucleus SE 中。

  • 将信号量恢复到未使用状态,没有暂停(重置)任务。由 NUSE_Semaphore_Reset() 实现 在 Nucleus SE 中。

  • 提供有关指定信号量的信息。由 NUSE_Semaphore_Information() 实现 在 Nucleus SE 中。

  • 返回为应用程序(当前)配置了多少信号量的计数。由 NUSE_Semaphore_Count() 实现 在 Nucleus SE 中。

  • 向应用程序添加一个新的信号量(创建)。未在 Nucleus SE 中实现。

  • 从应用程序中移除一个信号量(删除)。未在 Nucleus SE 中实现。

  • 返回指向应用程序中所有信号量(当前)的指针。未在 Nucleus SE 中实现。

详细检查了每个服务调用的实现。

信号量获取和释放服务

可以对信号量执行的基本操作是获取(递减)和释放(递增)它。 Nucleus RTOS 和 Nucleus SE 分别为这些操作提供了两个基本的 API 调用,这里将对其进行讨论。

获取信号量

用于获取信号量的 Nucleus RTOS API 调用非常灵活,如果操作无法立即完成,您可以无限期挂起或超时挂起;即,您尝试获取当前值为 0 的信号量。 Nucleus SE 提供相同的服务,只是任务挂起是可选的,并且没有实现超时。

用于获取信号量的 Nucleus RTOS API 调用

服务调用原型:

状态 NU_Obtain_Semaphore(NU_SEMAPHORE *semaphore,
未签名挂起);

参数:

信号量 – 指向用户提供的信号量控制块的指针

暂停 – 任务暂停规范;可能是 NU_NO_SUSPENDNU_SUSPEND 或超时值

退货:

NU_SUCCESS – 通话成功

NU_UNAVAILABLE – 信号量的值为零

NU_INVALID_SEMAPHORE – 信号量指针无效

NU_INVALID_SUSPEND – 尝试从非任务挂起

NU_SEMAPHORE_WAS_RESET – 任务挂起时信号量被重置

用于获取信号量的 Nucleus SE API 调用

此 API 调用支持 Nucleus RTOS API 的关键功能。

服务调用原型:

STATUS NUSE_Semaphore_Obtain(NUSE_SEMAPHORE 信号量,
U8暂停);

参数:

信号量 – 要使用的信号量的索引(ID)

暂停 – 任务暂停规范;可能是 NUSE_NO_SUSPENDNUSE_SUSPEND

退货:

NUSE_SUCCESS – 通话成功

NUSE_UNAVAILABLE – 信号量的值为零

NUSE_INVALID_SEMAPHORE – 信号量索引无效

NUSE_INVALID_SUSPEND – 尝试从非任务线程挂起或未启用阻塞 API 调用

NUSE_SEMAPHORE_WAS_RESET – 任务挂起时信号量被重置

Nucleus SE 实现获取信号量

NUSE_Semaphore_Obtain() 的大部分代码 API 函数 - 参数检查后 - 由条件编译选择,取决于是否启用了对阻塞(任务挂起)API 调用的支持。我们将在此处分别查看这两种变体。

如果没有开启阻塞,这个 API 调用的逻辑很简单:

if (NUSE_Semaphore_Counter[semaphore] !=0) /* 信号量可用 */{ NUSE_Semaphore_Counter[semaphore]--; return_value =NUSE_SUCCESS;}else /* 信号量不可用 */{ return_value =NUSE_UNAVAILABLE;}

测试信号量值,如果非零,则递减。

启用阻塞后,逻辑变得更加复杂:

do{ if (NUSE_Semaphore_Counter[semaphore] !=0) /* 信号量可用 */ { NUSE_Semaphore_Counter[semaphore]--; return_value =NUSE_SUCCESS;暂停 =NUSE_NO_SUSPEND; } else /* 信号量不可用 */ { if (suspend ==NUSE_NO_SUSPEND) { return_value =NUSE_UNAVAILABLE; } else { /* 阻塞任务 */ NUSE_Semaphore_Blocking_Count[semaphore]++; NUSE_Suspend_Task(NUSE_Task_Active, 信号量 <<4) | NUSE_SEMAPHORE_SUSPEND); return_value =NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value !=NUSE_SUCCESS) { 暂停 =NUSE_NO_SUSPEND; } } }} while (suspend ==NUSE_SUSPEND);

对代码的一些解释可能有用:

代码包含在 do...while 中 循环,在参数 suspend 时继续 具有值 NUSE_SUSPEND .

如果信号量非零,则递减。 暂停 变量设置为 NUSE_NO_SUSPEND 并且 API 调用以 NUSE_SUCCESS 退出 .

如果信号量为零并且挂起 设置为 NUSE_NO_SUSPEND ,API 调用以 NUSE_UNAVAILBLE 退出 .如果挂起设置为 NUSE_SUSPEND ,任务暂停。返回时(即任务被唤醒时),如果返回值为 NUSE_SUCCESS ,表示任务被唤醒,因为信号量已经释放(相对于信号量的重置)代码循环回到顶部。

释放信号量

用于释放信号量的 Nucleus RTOS API 调用非常简单;信号量增加并报告成功。 Nucleus SE 提供相同的服务,只是执行了溢出检查。

用于释放信号量的 Nucleus RTOS API 调用

服务调用原型:

状态 NU_Release_Semaphore(NU_SEMAPHORE *semaphore);

参数:

信号量 – 指向用户提供的信号量控制块的指针

退货:

NU_SUCCESS – 通话成功

NU_INVALID_SEMAPHORE – 信号量指针无效

用于释放信号量的 Nucleus SE API 调用

此 API 调用支持 Nucleus RTOS API 的关键功能。

服务调用原型:

状态 NUSE_Semaphore_Release(NUSE_SEMAPHORE 信号量);

参数:

信号量 – 要释放的信号量的索引(ID)

退货:

NUSE_SUCCESS – 通话成功

NUSE_INVALID_SEMAPHORE – 信号量索引无效

NUSE_UNAVAILABLE – 信号量的值为 255 且不能递增

Nucleus SE 发布信号量的实现

NUSE_Semaphore_Release() 的初始代码 API 函数 - 参数检查后 - 是通用的,无论是否启用任务阻塞。检查信号量的值,如果小于 255,则递减。

如果启用了对阻塞(任务挂起)API 调用的支持,则通过条件编译选择更多代码:

NUSE_CS_Enter();if (NUSE_Semaphore_Counter[semaphore] <255){ NUSE_Semaphore_Counter[semaphore]++; return_value =NUSE_SUCCESS; #if NUSE_BLOCKING_ENABLE if (NUSE_Semaphore_Blocking_Count[semaphore] !=0) { U8 index; /* 检查一个任务是否被阻塞 */ /* 在这个信号量上 */ NUSE_Semaphore_Blocking_Count[semaphore]--; for (index=0; index 

如果有任何任务在这个信号量上被挂起,第一个就会被唤醒。

下一篇文章将介绍一些与事件标志组相关的其他 API 调用,以及相关的数据结构。


Colin Walls 在电子行业拥有超过 30 年的经验,主要致力于嵌入式软件。 Colin 经常出席会议和研讨会,并撰写了大量技术文章和两本有关嵌入式软件的书籍,他是 Mentor Embedded [Mentor Graphics 嵌入式软件部门] 的嵌入式软件技术专家,常驻英国。他的常规博客位于:http://blogs.mentor.com/colinwalls。他可以通过电子邮件联系到 [email protected]


嵌入式

  1. 凸轮锁及其工作原理简介
  2. 吊环螺钉及其工作原理简介
  3. 不锈钢简介及其制造方法
  4. C# 基本输入和输出
  5. 什么是汽车服务编写者以及他们做什么?
  6. 邮箱:介绍和基本服务
  7. 信号量:实用服务和数据结构
  8. 事件标志组:实用服务和数据结构
  9. 事件标志组:介绍和基本服务
  10. 队列:介绍和基本服务
  11. 英国大学和学院招生服务中心与 Infosys 续签合同以推动自动化
  12. 表面磨削服务:工艺和精度