news 2026/8/31 23:09:04

半导体设备EAP系统开发实战:SECS-GEM协议从入门到Python完整实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
半导体设备EAP系统开发实战:SECS-GEM协议从入门到Python完整实现

如果你在Fab负责设备集成,最先要搞懂的就是SECS-GEM。这个协议是半导体设备的"普通话"——不管是哪家的机台(Applied、Lam、TEL、ASML),只要接入Fab的自动化网络,就必须讲SECS-GEM。搞懂了这个协议,设备集成的工作就完成了一半。

本文用一个完整的Python实现,带你从协议原理走到真实代码。看完这篇,你至少能自己写一个简单的SECS消息收发工具,调试设备通信问题的时候不用再完全依赖厂商工程师。

一、SECS-II协议基础

SECS-II是半导体行业标准(SEMI E5),定义了主机(Host,通常是MES/EAP)和设备(Equipment)之间的二进制消息格式。每条消息由两部分组成:Header(10字节)和Body(变长)。Header里包含设备ID、消息ID、消息长度等元数据,Body里是实际的业务数据。

SECS-II的数据类型系统很有特色:用单字符标识数据类型,比如A是ASCII字符串,B是1字节整数,I2是2字节整数,R4是4字节浮点数。List用方括号表示,可以嵌套任意层级。这套格式设计得很紧凑,适合低带宽的串口通信(RS-232)。

二、Python实现:消息解析器

下面是一个精简的SECS消息编码/解码实现,包含了核心的数据类型处理逻辑。理解了这段代码,SECS-II的二进制格式就不神秘了。

import struct
from typing import Any, List, Union

class SecsMessage:
def __init__(self, device_id, stream, function, system, data=None, wbit=False):
self.device = device_id
self.s = stream
self.f = function
self.system = system
self.wbit = wbit # wait bit, True = need reply
self.data = data or []

@staticmethod
def encode(msg) -> bytes:
body = _encode_data(msg.data)
header = struct.pack('>HH', msg.device, msg.system)
header += bytes([msg.s, msg.f | (0x80 if msg.wbit else 0)])
header += struct.pack('>I', len(body))[1:] # 3-byte length
return header + body

@staticmethod
def decode(raw: bytes):
device, system = struct.unpack('>HH', raw[:4])
s, f = raw[4], raw[5]
data, _ = _decode_data(raw[10:])
return SecsMessage(device, s, f & 0x7F, system, data, wbit=bool(f & 0x80))

def _encode_data(item) -> bytes:
if isinstance(item, str):
encoded = item.encode('ascii')
return bytes([0xA0]) + struct.pack('>H', len(encoded)) + encoded
elif isinstance(item, int):
return bytes([0xB1]) + struct.pack('>b', item) # I1
elif isinstance(item, float):
return bytes([0xD0]) + struct.pack('>f', item)
elif isinstance(item, list):
parts = b''.join(_encode_data(x) for x in item)
count_bytes = struct.pack('>I', len(item))
return bytes([0x01]) + count_bytes[1:] + parts
return b''

def _decode_data(bs) -> tuple:
if not bs: return None, bs
fmt = bs[0]
if fmt == 0xA0:
length = struct.unpack('>H', bs[1:3])[0]
return bs[3:3+length].decode('ascii'), bs[3+length:]
elif fmt == 0xB1:
return struct.unpack('>b', bs[1:2])[0], bs[2:]
elif fmt == 0xD0:
return struct.unpack('>f', bs[1:5])[0], bs[5:]
elif fmt == 0x01: # List
count = struct.unpack('>I', b'\x00' + bs[1:4])[0]
items, rest = [], bs[4:]
for _ in range(count):
it, rest = _decode_data(rest)
items.append(it)
return items, rest
return None, bs

三、GEM状态机实战

GEM在SECS-II基础上定义了设备的状态机。最核心的两个概念:Equipment State(物理状态:Running/Idle/Down/Paused)和Communication State(通信状态:COMMUNICATING/LOCALLY CONTROLLED/ATTEMPTING OFFLINE)。这两个状态必须始终同步,Fab里的状态看板就是靠GEM上报的这些状态来驱动的。

状态转换有严格规范:设备开机后进入ATTEMPTING OFFLINE,握手成功后进入COMMUNICATING,收到S1F1(Are You There)后回复S1F2表示在线,收到S2F37远程控制命令时执行START/STOP/PAUSE/RESUME。任何非规范的状态转换都会被MES报警。

四、TCP通信客户端实现

现代Fab的SECS通信几乎全部走TCP/IP(HSMS协议),不再用老旧的RS-232串口。下面的代码是一个完整的HSMS/TCP客户端实现,支持连接管理、消息收发、等待回复超时控制:

import socket
import struct
import time
from_secs_msg = SecsMessage.encode

class SecsTCPClient:
def __init__(self, host, port, device_id=0):
self.host = host
self.port = port
self.device_id = device_id
self.sock = None

def connect(self, timeout=10):
self.sock = socket.create_connection((self.host, self.port), timeout=timeout)
# HSMS Active Passive Select procedure
# 发送S1F1 Are You There
req = SecsMessage(self.device_id, 1, 1, 0, wbit=True)
self.send(req)
rep = self.recv(timeout=5)
print(f'Device online: {rep is not None}')
return rep is not None

def send(self, msg: SecsMessage):
data = SecsMessage.encode(msg)
self.sock.sendall(data)

def recv(self, timeout=5):
self.sock.settimeout(timeout)
header = self.sock.recv(10) # 固定10字节header
if not header: return None
length = struct.unpack('>I', b'\x00' + header[6:9])[0]
body = b''
while len(body) < length:
body += self.sock.recv(length - len(body))
raw = header + body
return SecsMessage.decode(raw)

五、常见问题与排错思路

问题一:设备不响应S1F1

最常见的问题是TCP连接建立了,但设备不回复S1F2。先确认设备的IP和端口配置正确(很多设备默认监听特定端口),再确认设备的防火墙没有阻断入站连接。最笨但最有效的方法:用Wireshark抓包,看TCP三次握手是否成功,看设备有没有发送任何数据。

问题二:消息格式错误

SECS-II的二进制格式很容易出错,特别是在处理List嵌套和长度字段的时候。强烈建议在调试阶段把每条发送的消息打印成十六进制,同时在接收端也打印出来,两边对比。特别注意:List的长度字段是4字节但第一个字节固定为0,实际有效长度只有3字节(24位)。

问题三:超时和重试

网络超时是最难调试的一类问题。SECS-II的W-bit(Wait bit)机制:发送方在等待回复时设置W-bit,如果超时未收到回复,需要重发。但很多设备不允许消息重复发送(幂等性),重发会导致设备报警。正确做法是:先确认设备是否支持消息重试,再设置合理的超时时间(一般建议3-5秒),最后在重试前先查设备状态。

EAP开发没有捷径,只有多抓包、多看日志、多和设备工程师沟通。但一旦这条路走通了,你会发现Fab里所有的设备集成问题在你面前都是透明的——这也是为什么EAP工程师在Fab里这么稀缺。

获取更多实战案例和技术资料:https://www.yezhihui.cn

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/31 23:06:09

AI工程化实践:从SDLC方法论到DeepSeek视觉API集成指南

这次我们来看两个来自AI领域头部公司的重磅发布&#xff1a;Anthropic的《AI原生SDLC手册》和DeepSeek的视觉API开放。前者不是代码库&#xff0c;而是一套指导企业如何将AI深度融入软件开发全生命周期的实践框架&#xff1b;后者则是一个能让开发者直接调用、处理图像理解任务…

作者头像 李华
网站建设 2026/8/31 23:03:27

模型服务的超时隔离

模型服务的超时隔离先确定问题 模型服务的超时隔离的讨论先落在服务边界、配置版本和回退路径。不要用一段笼统的经验替代前提&#xff1a;输入从哪里来、谁负责确认、失败后怎样停止&#xff0c;都应在开始前写清。 沿着一条路径检查 围绕模型服务的超时隔离做云原生工程实践时…

作者头像 李华
网站建设 2026/8/31 23:02:32

数据处理的资源取舍

数据处理的资源取舍先确定问题 数据处理的资源取舍的讨论先落在数据口径、样本范围和确认人。不要用一段笼统的经验替代前提&#xff1a;输入从哪里来、谁负责确认、失败后怎样停止&#xff0c;都应在开始前写清。 沿着一条路径检查 围绕数据处理的资源取舍做数据分析实践时&am…

作者头像 李华
网站建设 2026/8/31 23:02:04

Nucleo板载ST-LINK妙用:SWD接线调试外部STM32芯片

手里只剩一块Nucleo-U083RC开发板&#xff0c;外置ST-LINK又被同事借走&#xff0c;可此刻真正要调的是另一颗还没上板的STM32G030F6P6。大多数人会把Nucleo板当成"一块能跑示例的板子"&#xff0c;但它最值钱的部分未必是板载那颗MCU&#xff0c;而是左上角那套独立…

作者头像 李华
网站建设 2026/8/31 23:01:47

《易学・革䷰|道影子新解 049》

摘要革卦&#xff08;䷰&#xff09;承接井卦 "井养不穷、修井养人" 之后&#xff0c;揭示当系统井养到一定程度、旧的格局已经不适应新的发展、需要变革、革命、革新时&#xff0c;便进入 "泽火革、二女同居其志不相得" 的革故力场。其本质是泽火革、水火…

作者头像 李华
网站建设 2026/8/31 23:01:42

存储系统第一版该保留哪些核心能力

存储系统第一版该保留哪些核心能力一、功能画饼与交付失控的陷阱 向量化扫描适合处理结构稳定的日志或指标字段&#xff1b;异常检测可以先从可解释的统计方法开始。第一版不需要同时解决全部指令集、日志格式和根因推断问题。 先限定支持的 CPU 特性、输入格式和算子&#xff…

作者头像 李华