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

Nucleus SE队列:介绍与核心服务调用

Nucleus SE队列:介绍与核心服务调用
查看RTOS Revealed系列

队列在早期文章引入。它们比邮箱提供更灵活的任务间简单消息传递手段。

使用队列

在Nucleus SE中,队列在构建时配置。应用最多可定义16个队列。若无队列配置,RTOS省略所有队列相关数据结构和API代码,保持二进制精简。

队列简单是存储槽数组,每槽足以容纳单个ADDR数据项。访问同步化使多任务可安全入队和出队消息。任务可写入队列直到所有槽满,按先进先出(FIFO)顺序从队列读取。发送到满队列或从空队列接收尝试触发错误或任务挂起,取决于API选项和Nucleus SE配置。

队列 vs 管道

Nucleus SE也支持管道,主要区别在于消息大小。队列传输单个ADDR(通常为指针);管道传输可变长度字节块;块大小配置时固定。管道将在后续文章深入探讨。

配置队列

队列数量

队列配置由nuse_config.h中#define语句控制。关键设置NUSE_QUEUE_NUMBER决定启用队列数。默认0(无队列)。可设0到16任意值;超范围值触发nuse_config_check.h产生的编译时#error。

设NUSE_QUEUE_NUMBER为非零值激活队列子系统,分配必要数据结构并启用关联API调用。

API启用

每个队列API函数在nuse_config.h有启用#define符号:

NUSE_QUEUE_SEND NUSE_QUEUE_RECEIVE NUSE_QUEUE_JAM NUSE_QUEUE_RESET NUSE_QUEUE_INFORMATION NUSE_QUEUE_COUNT 

默认全设为FALSE,禁用对应服务调用。使用特定API需将其符号设为TRUE。无队列配置时启用API(除NUSE_Queue_Count()始终允许)导致编译时错误。代码中调用未启用API因实现省略导致链接时错误。

#define NUSE_QUEUE_NUMBER 0 /* 系统队列数量 – 0‑16 */ /* 服务调用启用器 */ #define NUSE_QUEUE_SEND FALSE #define NUSE_QUEUE_RECEIVE FALSE #define NUSE_QUEUE_JAM FALSE #define NUSE_QUEUE_RESET FALSE #define NUSE_QUEUE_INFORMATION FALSE #define NUSE_QUEUE_COUNT FALSE 

队列服务调用

Nucleus RTOS提供十个队列相关服务调用,其中六个在Nucleus SE实现。提供以下功能:

各API实现详见后续章节。

写入与读取服务

队列核心操作是写入(发送)和读取(接收)。写入队列前端称塞入。Nucleus RTOS和Nucleus SE各暴露三个基本API调用执行这些动作。

写入队列

RTOS API NU_Send_To_Queue()高度灵活,允许队列满时无限挂起或超时。Nucleus SE提供相同功能但挂起可选、不支持超时。RTOS也支持广播操作,SE无。

RTOS API: NU_Send_To_Queue()

原型:

STATUS NU_Send_To_Queue(NU_QUEUE *queue, VOID *message, UNSIGNED size, UNSIGNED suspend); 

参数:

返回码含NU_SUCCESS、NU_QUEUE_FULL、NU_TIMEOUT及各类无效指针或队列状态错误码。

SE API: NUSE_Queue_Send()

原型:

STATUS NUSE_Queue_Send(NUSE_QUEUE queue, ADDR *message, U8 suspend); 

参数:

返回值镜像RTOS函数但反映SE有限阻塞行为。

实现概览

禁用阻塞时,例程仅检查空间并写入值或返回NUSE_QUEUE_FULL。启用阻塞时,函数循环,队列满时挂起任务直到有空间或重置发生。实现用NUSE_Queue_Blocking_Count追踪阻塞任务、NUSE_Task_Blocking_Return在槽位空出时恢复它们。

if (NUSE_Queue_Items[queue] == NUSE_Queue_Size[queue]) { return_value = NUSE_QUEUE_FULL; } else { NUSE_Queue_Data[queue][NUSE_Queue_Head[queue]++] = *message; if (NUSE_Queue_Head[queue] == NUSE_Queue_Size[queue]) NUSE_Queue_Head[queue] = 0; NUSE_Queue_Items[queue]++; return_value = NUSE_SUCCESS; } 
do { if (NUSE_Queue_Items[queue] == NUSE_Queue_Size[queue]) { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_QUEUE_FULL; } else { NUSE_Queue_Blocking_Count[queue]++; NUSE_Suspend_Task(NUSE_Task_Active, (queue << 4) | NUSE_QUEUE_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) suspend = NUSE_NO_SUSPEND; } } else { NUSE_Queue_Data[queue][NUSE_Queue_Head[queue]++] = *message; if (NUSE_Queue_Head[queue] == NUSE_Queue_Size[queue]) NUSE_Queue_Head[queue] = 0; NUSE_Queue_Items[queue]++; if (NUSE_Queue_Blocking_Count[queue] != 0) { U8 index; NUSE_Queue_Blocking_Count[queue]--; for (index = 0; index < NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_QUEUE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == queue)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; } } while (suspend == NUSE_SUSPEND); 

循环持续直到消息成功入队或任务被重置解除阻塞。实现确保线程安全访问和高效唤醒阻塞消费者。

嵌入式

  1. 精密平面磨削服务:微米级平面度与表面质量的专业交付
  2. 加工中心与车削中心:专家对比选型指南
  3. 凸轮锁详解:如何隐蔽锁固柜体
  4. 什么是环眼螺丝?设计与用途专业指南
  5. 深入了解垫圈:类型、用途及如何保护您的设备
  6. 不锈钢详解:成分、生产与全球影响
  7. Nucleus SE邮箱:配置与使用实战指南
  8. Nucleus RTOS信号量:实用服务与数据结构
  9. Nucleus SE信号量:概览、配置与API要点
  10. 掌握事件标志组:Nucleus RTOS/SE实用服务与数据结构
  11. Nucleus SE事件标志组:配置与API使用入门指南
  12. C# 基础:输入输出核心技巧完全指南