十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SECS/GEM协议实战:基于secsgem源码的半导体EAP通信开发指南

SECS/GEM协议实战:基于secsgem源码的半导体EAP通信开发指南 简介这份资源是面向半导体设备自动化领域开发者的 SECS/GEM 协议源码包适合从事 EAP 系统开发、设备通信对接的工程师以及希望深入理解 SEMI 标准的进阶学习者。它解决了半导体设备与上层系统之间通信协议实现的问题涵盖 GEM、SECS 与 HSMS 三大核心模块并配有完整的测试用例与文档参考。压缩包共 97 个文件约 158KB以 46 个 Python 源码文件为主体辅以 38 个 rst 文档、若干 yml 与 sh 脚本以及 Makefile、setup 配置和 LICENSE 等工程文件目录结构清晰便于按模块检索与二次开发。目前已有 791 人学习下载说明该源码在半导体 EAP 圈内具备一定参考价值。读者可从中获取协议栈的完整实现思路、设备端与主机端示例代码、通信日志处理方式及单元测试组织方法适合作为协议学习与项目迭代的起点。1. 从一份 secsgem-master.zip 说起半导体 EAP 通信为什么绕不开 SECS/GEM半导体产线上一台刻蚀机、一台量测机台、一台 CMP 设备背后都挂着一个 EAPEquipment Automation Program。EAP 要做的核心事情只有一件让 MES 和设备之间能对话。而设备侧说的“语言”就是 SEMI 组织定义的 SECS/GEM 协议族。你手上这份secsgem-master.zip正是一套用 Python 实现的 SECS/GEM 通信库源码覆盖了 SECS-II 消息编解码、HSMS 传输层、GEM 状态机等关键模块。很多人第一次接触半导体协议会以为它和普通 TCP 上位机差不多写个 socket 收发字符串就完事。真正上手才发现SECS-II 是二进制流格式消息体按 item 树递归编码HSMS 有独立的会话状态机GEM 又规定了设备必须响应哪些标准消息。这份源码的价值就在于把这三层都拆开摆在你面前让你能直接读实现、改参数、跑联调。适合谁做设备自动化、MES 对接、机台数据采集的工程师以及需要自研 EAP 或做协议网关的团队。2. SECS-II 消息编解码item 树、格式码与 secsgem 的解析入口2.1 为什么 SECS-II 不能当字符串处理SECS-II 消息体是一棵 item 树。每个 item 由三部分组成格式码Format Code、长度字节数Length Bytes、实际数据。格式码占 1 字节高 6 位表示数据类型低 2 位表示长度占几个字节。比如0x21表示 2 字节长度的 Binary0xA1表示 2 字节长度的 ASCII。如果你用普通字符串去解析遇到长度字节数变化、列表嵌套、有符号整数补码立刻就会错位。secsgem里对应的模块是secsgem/secs/variables.py和secsgem/secs/functions.py。前者定义了各种 item 类型Array、Binary、Boolean、U1~U8、I1~I8、F4/F8、A、JIS8等后者负责把消息函数号Stream/Function和 item 树组装成完整报文。读源码时建议从functions.py的encode方法入手它会把LList递归展开。2.2 用源码跑一次消息编码下面这段代码演示如何构造一条 S1F1Are You There并编码成字节流直接调用库里的类from secsgem.secs.functions import SecsS01F01 from secsgem.secs.variables import Array, U1 # S1F1 通常无消息体这里演示带一个 U1 列表的构造方式 msg SecsS01F01() # 手动塞一个 Array 进去观察编码结果 msg.data Array(U1, [1, 2, 3]) encoded msg.encode() print(encoded.hex()) # 输出形如010100000003010203 # 01 01 是 S1F100 00 是后续长度占位03 是列表长度01 02 03 是三个 U1逻辑说明SecsS01F01继承自SecsStreamFunctionencode()会先写 Stream/Function 字节再写消息体长度最后递归写 item。参数说明Array(U1, [...])的第一个参数是元素类型第二个是 Python 列表换成U4时每个元素占 4 字节长度字段也会随之变化。常见坑是长度字节数选错——当数据超过 255 字节时必须用 2 字节长度否则接收端解析直接崩。2.3 解码时最容易踩的三个坑坑点现象处理方式长度字节数判断报文错位后续 item 全乱读格式码低 2 位决定读 1/2/3 字节长度List 嵌套深度递归解析栈溢出或漏读用递归函数遇到L格式码继续展开有符号整数I1/I2/I4 出现负数异常按补码解释不要当无符号读secsgem的variables.py里每个类型都有decode类方法直接复用比自己手写稳。如果你要对接非 Python 的 EAP建议把这份解码逻辑当参考实现逐字段对照 SEMI E5 标准文档验证。3. HSMS 传输层连接状态机、Select 流程与 secsgem 的会话管理3.1 HSMS 和 SECS-I 的区别以及为什么现在都用 HSMSSECS-I 走串口速率低、布线麻烦一条线只能挂一台设备。HSMSHigh-Speed SECS Message Services走 TCP支持多会话、高吞吐是现在 EAP 对接的主流。HSMS 有自己的控制消息Select.req、Select.rsp、Deselect.req、Linktest.req 等。设备侧和主机侧必须先完成 Select 握手才能发数据消息。secsgem里 HSMS 相关代码在secsgem/hsms/目录核心是connection.py和packets.py。packets.py定义了 HSMS 报文头10 字节2 字节会话 ID、1 字节流、1 字节功能、1 字节 PType、1 字节 SType、4 字节系统字节connection.py维护状态机NOT_CONNECTED→CONNECTED→SELECTED。3.2 用源码起一个 HSMS 被动端下面演示如何用库里的HsmsPassiveConnection监听端口等待主机 Selectfrom secsgem.hsms import HsmsPassiveConnection # 被动端设备侧监听 5000 端口 conn HsmsPassiveConnection(address0.0.0.0, port5000) # 注册 Select 请求回调握手成功后打印 conn.events.select def on_select(session_id): print(fsession {session_id} selected) conn.start() # 保持运行等待主机连接 input(按回车退出\n) conn.stop()逻辑说明HsmsPassiveConnection内部会先 accept TCP再等对端发 Select.req收到后回 Select.rsp 并触发select事件。参数说明address填本机监听地址port默认 5000实际项目里按设备手册改session_id用于区分同一 TCP 上的多个会话通常设备侧固定为 0 或 0xFFFF。常见坑是防火墙没放行端口或者主机侧 T3回复超时设得太短Select.rsp 还没发出去就判超时。3.3 Linktest 与超时参数怎么设HSMS 用 Linktest 保活防止 TCP 假连接。secsgem的HsmsConnection支持配置T3、T5、T6、T7、T8等定时器。T3 是等待回复的时间T5 是连接分离后的重连间隔T6 是 Linktest 间隔T7 是未 Select 时的超时T8 是网络字符间超时。半导体现场常见做法是 T3 设 45 秒、T5 设 10 秒、T6 设 30 秒、T7 设 10 秒、T8 设 5 秒但具体要看设备手册不能照搬。提示T3 设太小会导致正常但稍慢的设备频繁超时重发设太大则故障发现慢。联调阶段建议先用默认值稳定后再按现场网络质量微调。4. GEM 状态机与标准消息secsgem 里设备行为怎么落地4.1 GEM 不是协议是行为规范GEMGeneric Equipment Model规定了设备在什么状态下该响应什么消息。比如设备必须支持 S1F1Are You There、S1F13Establish Communications、S2F17Date and Time Request、S5F1Alarm Report等。EAP 侧要做的是维护设备状态模型Control State设备控制权在谁手里、Processing State是否在跑片、Communication State通信是否正常。secsgem的secsgem/gem/目录下有Equipment和Host两个类分别对应设备侧和主机侧。Equipment类里内置了标准消息的默认处理你只需要覆盖需要自定义的部分。比如 S1F13 默认回 S1F14S2F17 默认回当前时间。4.2 自定义一条 S2F17 时间响应下面演示如何覆盖默认的时间响应返回固定格式from secsgem.gem import Equipment from secsgem.secs.functions import SecsS02F17, SecsS02F18 from secsgem.secs.variables import A class MyEquipment(Equipment): def _on_s02f17(self, handler, message): # 自定义时间格式YYYYMMDDhhmmss import datetime now datetime.datetime.now().strftime(%Y%m%d%H%M%S) return SecsS02F18(A(now)) eq MyEquipment() eq.enable()逻辑说明_on_s02f17是库预留的钩子收到 S2F17 时被调用返回值会被自动编码成 S2F18 发回。参数说明A(now)构造一个 ASCII item长度自动计算如果要返回多个字段用Array包起来。常见坑是时间格式和设备侧期望不一致导致 MES 解析失败联调时务必和对方确认格式。4.3 事件与报警上报的写法GEM 要求设备主动上报事件S6F11和报警S5F1。secsgem里通过trigger_event和send_alarm触发。事件需要预先定义 CEIDCollection Event ID和关联的 VIDVariable ID这些在Equipment初始化时注册。报警则要指定 ALCDAlarm Code和 ALIDAlarm ID。实际项目里CEID 和 ALID 由 MES 侧统一下发EAP 不能自己乱编。注意S6F11 的消息体结构复杂包含 Data ID、CEID、Report 列表每个 Report 又含 VID 和值。用secsgem的Reports类组装比手写字节流可靠得多。5. 联调排错与二次开发从日志、抓包到自定义 Stream/Function5.1 打开 secsgem 的日志看报文联调时最有效的手段是看原始报文。secsgem用 Python 标准 logging把secsgemlogger 级别调到 DEBUG就能看到每条收发的十六进制和解析结果import logging logging.basicConfig(levellogging.DEBUG) logging.getLogger(secsgem).setLevel(logging.DEBUG)日志里会打印Sent: 010100000000这类内容对照 SEMI E5 文档逐字节核对。如果解析报错先看格式码和长度字节再看 item 嵌套层级。常见错误是设备侧发了非标准格式码库不认识直接抛异常这时需要扩展variables.py里的类型映射。5.2 用 Wireshark 抓 HSMS 报文HSMS 走 TCPWireshark 能直接抓。过滤条件用tcp.port 5000然后 Follow TCP Stream。HSMS 报文头固定 10 字节前 4 字节是长度接着是会话 ID 和 Stream/Function。如果 Wireshark 没解析成 HSMS可以手动按偏移看第 5 字节是 PType第 6 字节是 STypeSType1 是 Select.reqSType2 是 Select.rspSType9 是 Linktest.req。5.3 自定义一条非标准 Stream/Function有些设备厂商会扩展私有消息比如 S64F1。secsgem支持自定义from secsgem.secs.functions import SecsStreamFunction from secsgem.secs.variables import U4 class SecsS64F01(SecsStreamFunction): _stream 64 _function 1 _data_format [U4] # 消息体是一个 U4 # 注册到设备侧处理 class MyEquipment(Equipment): def _on_s64f01(self, handler, message): value message.data[0].get() print(f收到私有消息值{value}) return None逻辑说明_stream和_function定义消息号_data_format定义消息体结构。参数说明U4表示 4 字节无符号整数多个字段用列表按顺序排列。注册后收到 S64F1 会自动调用_on_s64f01。常见坑是私有消息的格式码和标准冲突建议先和对方确认字节布局再用variables.py里的类型拼装。5.4 性能与稳定性上的几个经验值高吞吐场景下HSMS 单连接每秒几百条消息很常见。secsgem默认单线程处理如果消息量大建议把耗时逻辑如数据库写入放到独立线程避免阻塞收发。另外TCP 的 Nagle 算法会攒小包联调时如果发现延迟高可以在 socket 上设TCP_NODELAY。secsgem的HsmsConnection里可以找到对应设置点按需打开。最后长时间运行要关注内存item 树递归解析如果遇到畸形报文可能爆栈建议在解码入口加深度限制。本文还有配套的精品资源点击获取
返回列表