引言如果你在做半导体制造信息化SECS/GEM是绕不开的协议。从晶圆制造到封测产线上几乎每台设备都要求支持SECS/GEM通信。但很多工程师对这个协议的理解停留在能用库发消息就行的层面遇到状态机异常、事件丢失、报告配置不生效等问题时就无从下手。本文从协议规范到代码实现系统拆解SECS/GEM的核心概念帮你真正理解设备通信的底层逻辑。文章也会结合益普科技EAPSiFactory在多个封测项目中的SECS/GEM联调经验标注实际工程中容易踩坑的地方。一、SECS协议族全景1.1 协议层级关系SECS不是一个单独的协议而是一套协议族SEMI标准 功能层 说明 ────────────────────────────────────────── E30 (GEM) │ 应用行为层 │ 设备状态机、采集事件、远程命令 E5 (SECS-II) │ 数据格式层 │ 消息类型定义、数据项结构 E37 (HSMS) │ 传输控制层 │ TCP/IP通信控制、会话管理 E4 (SECS-I) │ 传输控制层 │ 串口通信已逐步被HSMS替代理解这个层级关系很重要HSMS管怎么传SECS-II管传什么格式GEM管传什么内容。1.2 Stream和FunctionSECS-II用Stream和Function两个维度来标识消息类型Stream消息的大类如Stream 1是设备状态查询Stream 2是设备控制Stream 5是报警管理Stream 6是事件报告Function大类下的具体操作奇数为请求偶数为响应常用的消息类型StreamFunction方向名称用途S1F1-Host→EqAre You There Request查询设备是否在线S1F2-Eq→HostAre You There Data设备在线响应S1F3-Host→EqSelected Status Request查询设备状态S1F4-Eq→HostSelected Status Data返回状态参数S2F11-Host→EqVariable Attribute Request查询变量值S2F12-Eq→HostVariable Attribute Data返回变量值S2F17-Host→EqDate and Time Request查询设备时间S2F31-Host→EqDate and Time Set Request设置设备时间S5F1-Eq→HostAlarm Send报警上报S6F11-Eq→HostEvent Report Send事件报告上报S6F12-Host→EqEvent Report Acknowledge事件报告确认S7F1-Host→EqProcess Job Load Inquire请求加载工单S7F3-Host→EqProcess Job Start启动工单处理二、HSMS通信机制2.1 会话状态机HSMS定义了4个会话状态NOT_CONNECTED → SELECTING → SELECTED → DELSECTING ↑ │ └────────────────────────────────────┘ (断线后回到NOT_CONNECTED)NOT_CONNECTEDTCP连接未建立SELECTING已建立TCP连接正在发送Select.req等待Select.rspSELECTEDHSMS会话已建立可以收发数据消息DESELECTING正在关闭会话在SELECTED状态下还需要通过Linktest心跳维持会话活性。如果连续多次Linktest超时会话回退到NOT_CONNECTED。2.2 报文格式HSMS报文由10字节消息头变长消息体组成import struct def parse_hsms_message(data): 解析HSMS报文 if len(data) 10: raise ValueError(报文长度不足10字节) # 消息头10字节 # Byte 0-3: 消息长度4字节大端 # Byte 4: Device ID 高字节 # Byte 5: Device ID 低字节 # Byte 6: Stream # Byte 7: Function (bit0R bit) # Byte 8: 系统/控制标志 (PType, SType) # - System Bytes: 0x00 Data Message # - Control Bytes: 0x01-0x09 Control Message # Byte 9: 系统/控制标志续 msg_length struct.unpack(I, data[0:4])[0] device_id struct.unpack(H, data[4:6])[0] stream data[6] function data[7] 0x7F # 去掉W-bit w_bit (data[7] 0x80) 7 system_bytes data[8:10] msg_type Control if stream 0 else Data return { length: msg_length, device_id: device_id, stream: stream, function: function, w_bit: w_bit, # 1 需要回复 system_bytes: system_bytes, type: msg_type, body: data[10:10msg_length-10] if msg_type Data else data[10:] } def build_hsms_data_message(stream, function, w_bit, device_id, system_bytes, body): 构建HSMS数据消息 func_byte (function 0x7F) | (0x80 if w_bit else 0x00) msg_length 10 len(body) header struct.pack(I, msg_length) # 长度 header struct.pack(H, device_id) # Device ID header bytes([stream, func_byte]) # Stream Function header system_bytes # System Bytes return header body三、SECS-II数据结构3.1 数据项类型SECS-II用层级化的数据项来组织信息。常见数据项类型格式代码类型说明LList有序列表包含子数据项AASCII字符串BBinary二进制U1Unsigned 11字节无符号整数U2Unsigned 22字节无符号整数U4Unsigned 44字节无符号整数BooleanBoolean布尔值3.2 消息体示例以S6F11事件报告发送为例设备上报的SECS-II数据结构S6F11 W L [3] U4 [1] DATAID -- 数据ID U4 [1] CEID -- 采集事件ID L [1] -- 报告列表 L [2] -- 单个报告 U4 [1] RPTID -- 报告ID L [3] -- 变量值列表 A [8] W0012345 -- WaferID U2 [1] 15 -- PassCount U2 [1] 3 -- FailCount 这个结构表达的是设备上报了采集事件CEID关联了报告RPTID报告中包含WaferID、PassCount、FailCount三个变量的值。3.3 使用Python secsgem库解析from secsgem.secs.variables import Variables from secsgem.secs.data_items import DataItems from secsgem.common import SessionSettings from secsgem.hsms import HsmsSettings # secsgem库简化了SECS/GEM通信 # 以下是事件报告回调的示例 async def on_event_report(handler, data): S6F11事件报告回调 # data.data_value 是SECS-II数据结构 data_id data.data_value[0] ceid data.data_value[1] print(f收到事件报告: DATAID{data_id}, CEID{ceid}) # 遍历报告列表 for report in ceid[2]: rpt_id report[0] print(f 报告ID: {rpt_id}) for i, value in enumerate(report[1]): print(f 变量[{i}]: {value}) # 返回S6F12确认 return 0 # 0 Acknowledge # 注册回调 handler.events.data_received on_event_report四、GEM设备行为模型4.1 设备状态机GEM定义了5个设备控制状态┌──────────┐ ┌────────→│ ON-LINE │←────────┐ │ │ (Remote) │ │ │ └──────────┘ │ │ │ │ │ ┌──────────┐ │ │ │ ON-LINE │ │ ├────────→│ (Local) │←────────┤ │ └──────────┘ │ │ │ │ │ ┌──────────┐ │ ├────────→│OFF-LINE │←────────┤ │ │(Attempt) │ │ │ └──────────┘ │ │ │ │ │ ┌──────────┐ │ └────────→│ OFF-LINE │─────────┘ └──────────┘OFF-LINE设备离线Host无法控制OFF-LINE (Attempt On-Line)设备正在尝试上线ON-LINE (Local)设备在线但只能本地操作ON-LINE (Remote)设备在线且可被Host远程控制Host通过S2F17/S2F31等命令在Remote和Local之间切换但OFF-LINE到ON-LINE的切换通常需要在设备端物理操作。4.2 采集事件配置要让设备主动上报事件Host需要先配置报告和事件步骤1: 定义报告 (S2F33) Host → 设备: 创建报告RPTID1001包含变量[WaferID, PassCount, FailCount] 步骤2: 关联事件 (S2F35) Host → 设备: 将采集事件CEID2001关联到报告RPTID1001 步骤3: 启用事件 (S2F37) Host → 设备: 启用采集事件CEID2001配置完成后设备每次触发CEID2001事件时就会自动发送S6F11消息包含RPTID1001报告中的变量值。async def setup_event_collection(handler): 配置采集事件 # 1. 定义报告 await handler.send_and_wait( handler.stream_function(0x02, 0x33), # S2F33 [ 0, # DATAID [ [1001, [1001, 1002, 1003]] # RPTID, [VID列表] ] ] ) # 2. 关联事件到报告 await handler.send_and_wait( handler.stream_function(0x02, 0x35), # S2F35 [ 0, # DATAID [ [2001, [1001]] # CEID, [RPTID列表] ] ] ) # 3. 启用事件 await handler.send_and_wait( handler.stream_function(0x02, 0x37), # S2F37 [True, [2001]] # CEEDEnable, [CEID列表] )五、调试技巧5.1 抓包分析使用Wireshark配合SECS-II dissector插件可以可视化解析HSMS报文。关键过滤规则# 过滤特定设备的HSMS流量 tcp.port 5000 ip.addr 192.168.1.100 # 过滤S6F11事件报告 data[6:1] 06 data[7:1] 0b5.2 常见问题排查现象可能原因排查方法连接建立后立即断开Device ID不匹配检查Host和设备的Device ID配置S6F11收不到事件未启用或报告未配置发S2F37检查事件启用状态变量值为空VID不存在或未赋值发S1F11查询设备支持的VID列表报警不上报报警未启用发S5F3查询报警启用状态工单无法启动设备不在Remote状态发S1F3查询控制状态六、选型建议SECS/GEM协议栈的开发和维护门槛较高如果团队没有专门的设备通信开发人员建议选择有成熟EAP产品的半导体mes厂家进行合作。在选型时需要重点考察几个维度一是EAP模块支持的设备品牌覆盖度——封测产线上往往混用多品牌设备EAP的设备驱动库越全联调周期越短二是SECS/GEM协议的实现完整度——状态机、事件采集、远程命令是否全部支持有些厂家的实现只覆盖了基本消息收发缺少报告配置和事件启用的完整流程三是断线重连和异常恢复机制是否健壮。以益普科技的EAPSiFactory为例其SECS/GEM协议栈实现了HSMS-SS/HSMS-GS双模式、GEM完整状态机、S6F11事件报告全流程配置已在中微高科、盛元半导体等封测产线上完成数十种设备的联机对接支持即插即用的设备驱动配置。相比自研协议栈使用成熟EAP产品可以将设备联调周期从数月压缩到数周。更多半导体mes厂家的方案对比和选型维度可以参考这个半导体mes厂家选型页面。七、总结SECS/GEM协议看似复杂但核心逻辑可以归纳为三层HSMS层管TCP连接和会话控制4个状态Linktest心跳SECS-II层管数据格式List和基本数据项的层级嵌套GEM层管设备行为状态机采集事件远程命令理解了这三层大部分设备通信问题都能找到排查方向。关键是要多抓包、多看实际报文而不是只看文档描述。对于正在评估半导体mes厂家的团队SECS/GEM协议的实现深度是衡量厂家技术实力的硬指标——能讲清楚状态机、事件配置、报告流转的厂家通常在设备联机这块有真正的工程积累。如果有具体的SECS/GEM开发问题欢迎在评论区讨论。