信号
在这个 RTOS Revealed 中,我将看看信号,这是 Nucleus SE 支持的最简单的任务间通信方法。它们提供了一种在任务之间传递简单消息的成本非常低的方法。
使用信号
信号不同于所有其他类型的内核对象,因为它们不是自治的——信号与任务相关联,没有独立存在。如果为应用程序配置了信号,则每个任务都有一组八个信号标志。
任何任务都可以设置另一个任务的信号。只有所有者任务可以读取信号。读取是破坏性的——即信号被读取过程清除。没有其他任务可以读取或清除任务的信号。
Nucleus RTOS 中有一项功能,可让任务指定在另一个任务设置其一个或多个信号标志时运行的函数。这有点类似于中断服务程序。 Nucleus SE 不支持此功能;任务需要明确询问他们的信号标志。
配置信号
与 Nucleus SE 的大多数方面一样,信号的配置主要由 #define 控制 nuse_config.h 中的语句 .关键设置是 NUSE_SIGNAL_SUPPORT , 启用工具(用于应用程序中的所有任务)。没有指定信号数量的问题——应用程序中的每个任务只有一组八个标志。
设置此使能参数是信号的“主使能”。这会导致相应地定义和调整数据结构的大小,本文稍后将详细介绍。它还激活 API 启用设置。
API 启用
Nucleus SE 中的每个 API 函数(服务调用)都有一个启用 #define nuse_config.h 中的符号 .对于信号,这些是:
NUSE_SIGNALS_SENDNUSE_SIGNALS_RECEIVE
默认情况下,这两个都设置为 FALSE ,从而禁用每个服务调用并禁止包含任何实现代码。要为应用程序配置信号,您需要选择要使用的 API 调用并将其启用符号设置为 TRUE .
这是默认 nuse_config.h 的摘录 文件:
#define NUSE_SIGNAL_SUPPORT FALSE /* 启用对信号的支持 */#define NUSE_SIGNALS_SEND FALSE /* 服务调用使能 */#define NUSE_SIGNALS_RECEIVE FALSE /* 服务调用使能 */
如果启用了信号 API 功能而未启用信号设施,则会导致编译时错误。如果您的代码使用尚未启用的 API 调用,则会导致链接时间错误,因为应用程序中不会包含任何实现代码。当然,启用这两个 API 函数有点多余,因为启用信号支持和不提供这些 API 是没有意义的。包含启用是为了与其他 Nucleus SE 功能兼容。
信号服务调用
Nucleus RTOS 支持四个属于信号的服务调用,提供以下功能:
向指定任务发送信号。由 NUSE_Signals_Send() 实现 在 Nucleus SE 中。
接收信号。由 NUSE_Signals_Receive() 实现 在 Nucleus SE 中。
注册一个信号处理程序。未在 Nucleus SE 中实现。
启用/禁用(控制)信号。未在 Nucleus SE 中实现。
详细检查了每个服务调用的实现。
信号发送和接收服务
可以对任务的一组信号执行的基本操作是向它发送数据(这可能由任何任务完成)并从中读取数据(从而清除数据,这可能只能由所有者完成) . Nucleus RTOS 和 Nucleus SE 分别为这些操作提供了两个基本的 API 调用,将在此处讨论。
由于信号标志是位,因此最好将它们可视化为二进制数。由于标准 C 历来不支持二进制常量的表示(仅八进制和十六进制),Nucleus SE 发行版包含一个有用的头文件 - nuse_binary.h – 包含 #define b01010101 形式的符号 对于所有 256 个 8 位值。这是 nuse_binary.h 的摘录 文件:
#define b00000000 ((U8) 0x00)#define b00000001 ((U8) 0x01)#define b00000010 ((U8) 0x02)#define b00000011 ((U8) 0x03)#define b00001 ((U8) 0x01)#define b0000 b00000101 ((U8) 0x05)
发送信号
任何任务都可以向应用程序中的任何其他任务发送信号。发送信号涉及设置一个或多个信号标志。这是一个 OR 操作,对之前设置的标志没有影响。
用于发送信号的 Nucleus RTOS API 调用
服务调用原型:
STATUS NU_Send_Signals(NU_TASK *task, UNSIGNED 信号);
参数:
任务 – 指向拥有要设置的信号标志的任务的控制块的指针
信号 – 要设置的信号标志的值
退货:
NU_SUCCESS – 通话成功
NU_INVALID_TASK – 任务指针无效
用于发送信号的 Nucleus SE API 调用
此 API 调用支持 Nucleus RTOS API 的关键功能。
服务调用原型:
STATUS NUSE_Signals_Send(NUSE_TASK 任务,U8 信号);
参数:
任务 – 拥有要设置的信号标志的任务的索引(ID)
信号 – 要设置的信号标志的值
退货:
NUSE_SUCCESS – 通话成功
NUSE_INVALID_TASK – 任务索引无效
Nucleus SE 发送信号的实现
这是 NUSE_Signals_Send() 的完整代码 功能:
STATUS NUSE_Signals_Send(NUSE_TASK 任务,U8 信号){ #if NUSE_API_PARAMETER_CHECKING if (task>=NUSE_TASK_NUMBER) { return NUSE_INVALID_TASK; #endif NUSE_CS_Enter(); NUSE_Task_Signal_Flags[任务] |=信号; NUSE_CS_Exit();返回 NUSE_SUCCESS;}
代码非常简单。在任何参数检查之后,信号值被 ORed 到指定任务的信号标志中。任务阻塞与信号无关。
接收信号
一个任务只能读取它自己的一组信号标志。阅读它们的过程是破坏性的;即它也会导致标志被清除。
用于接收信号的 Nucleus RTOS API 调用
服务调用原型:
未签名的 NU_Receive_Signals(VOID);
参数:无
返回:信号标志值
用于接收信号的 Nucleus SE API 调用
此 API 调用支持 Nucleus RTOS API 的关键功能。
服务调用原型:
U8 NUSE_Signals_Receive(void);
参数:无
返回:信号标志值
Nucleus SE 接收信号的实现
这是 NUSE_Signals_Receive() 的完整代码 功能:
U8 NUSE_Signals_Receive(void){ U8 信号; NUSE_CS_Enter();信号 =NUSE_Task_Signal_Flags[NUSE_Task_Active]; NUSE_Task_Signal_Flags[NUSE_Task_Active] =0; NUSE_CS_Exit();返回信号;}
代码非常简单。标志值被复制,原始值被清除并由 API 函数返回副本。任务阻塞与信号无关。
嵌入式