ARTICLE DETAIL

资讯详情

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

SEMI E87协议精讲:从状态机到搬运联调避坑指南

SEMI E87协议精讲:从状态机到搬运联调避坑指南 简介SEMI E87-0301 是半导体 GEM300 标准体系中的一项暂行规范聚焦运载器管理系统Carrier Management System面向半导体设备自动化工程师、制造执行系统集成人员以及晶圆厂自动化运维人员。它明确了主机与生产设备在自动化及手动载具传输过程中于协调、执行、完成各阶段的状态交互与通信要求为载具身份识别、负载端口关联和传输可靠性提供统一依据。这份 PDF 为英文原版标准文件总数 1 个大小约 542KB内容涵盖目的、范围、限制条件、引用标准以及详细的状态模型和场景定义。目前已有 2123 人学习/下载是实施 GEM300 或进行 SEMI E15.1 负载端口对接验证时常备的原版参考资料。文档重点描述了运载器传输管理、设备与负载端口的访问模式切换、载具与负载端口关联、载具身份验证与槽位映射验证并列出暂行标准后续需解决的议题便于工程师对照协议细节、排查集成问题并规划功能落地。1. 为什么饭圈都在千兆网速产线通信还抱着 SEMI E87 不放半导体产线里设备之间要传的不是电影和图片而是晶圆盒的“交接班记录”哪个批次、哪台设备、什么时间点、Cassette 放到哪个 Port、是准备加工还是已经完成。这套规则行业里叫“机台对机台”的物料搬运协议。SEMI E87 -0301 就是这一协议的规范版本后跟“-0301”指它是 2001 年 3 月发布的修订版到现在仍被多数 300mm 晶圆厂的 OHT高空起重运输车和 EFEM设备前端模块做联机标准的基准。简单说E87 解决的是一句话当一批晶圆从上一台设备搬到下一台设备时两台设备怎么知道彼此交接成功、何时允许取下、异常时怎么恢复现场。没有这套规则设备 A 把 Cassette 放下就说“好了”设备 B 却可能刚好在换配方拿到一半物料导致批次混批。E87 的价值不是你开车多快而是把“交接”这件易扯皮的事变成机器可读、可校验、可恢复的固定语言。这篇文章适合搞设备自动化SECS/GEM的工程师、MES 开发以及刚接手工厂自动化项目的同行我会把协议里的核心状态机、搬运流程、参数配置和最常见的坑一次讲清楚。2. 先把 E87 的“状态机”骨架立起来消息、交接状态和搬运状态2.1 一套协议里藏了三层状态模型、消息字段和时序E87 并不只是一张消息列表它的核心是把物料搬运过程拆成“状态 事件 消息”。不理解状态机直接上去看报文很容易被一堆C1、S1F13、S2F41绕晕。规规矩矩的逻辑是这样的状态模型每台支持 E87 的设备需要维护两个维度——运载工具状态Carrier Status和加工状态Process State。事件报告每发生一次状态迁移比如 Carrier 从 READY 变成 PROCESSING设备要主动向 Host 发送事件。消息交互处理事件的请求确认、Carrier 的取放控制都用 SEMI 标准消息完成。习惯上把 Carrier 状态分成CARRIER ID READY、CARRIER READY、PROCESSING、PROCESS COMPLETE、CARRIER REMOVABLE等一串每个状态都有对应可达转移。例如加工完成后必须先发PROCESS COMPLETE再等 Host 确认之后才能进入CARRIER REMOVABLE。这一取消顺序就是为了防呆设备自己不能因为加工完就立刻把 Carrier 放出必须等人机界面或 Host 明确给出可移走信号。实际项目里给设备写 E87 状态机时我习惯先用表格列出每个状态下“允许做什么、禁止做什么、能迁到哪个状态”再谈消息序。原因很简单E87 的报文收发只是载体真正的契约全在状态转移规则里。表格式的状态定义是能和设备厂商坐下来对齐的东西比一上来就啃协议文本高效得多。状态名含义可接收的事件可迁移到的状态CARRIER ID READY已识别 Carrier ID但工艺数据未绑定Carrier 放入CARRIER READYCARRIER READY工艺配方/批次已绑定可开始加工STARTPROCESSINGPROCESSING加工中PROCESS COMPLETEPROCESS COMPLETEPROCESS COMPLETE加工完成等待 Host 确认确认移走CARRIER REMOVABLECARRIER REMOVABLE可被搬运系统取走Carrier 取出CARRIER ID READY2.2 最小消息闭环从“识别 ID”到“可搬运”只需要四步常见的 E87 消息闭环不需要把协议里所有消息都用上。一套能跑起来的搬运交接最少需要的消息是这样一组设备 - Host : S1F13 建立通信请求建立连接 Host - 设备 : S1F14 建立通信确认连接建立成功 设备 - Host : S2F41 发送事件报告Carrier 放置完成状态 CARRIER ID READY Host - 设备 : S6F11 事件通知Host 侧数据绑定完成处理完毕这段伪序列把它展开到真实报文层时需要注意 S2F41 中带上DATA_ID与CEID事件 ID。事件 ID 不是随便编的需要在设备的配置里预先定义Host 端也要有对应映射表。很多第一次对接的工程师直接复制别家项目的事件 ID结果设备侧根本没有对应定义Host 收到事件后只能判成“未知事件”。这是我在多个现场看到的第一大坑。消息格式上E87 使用 SECS-II 的列表结构。以一个Carrier Placed事件为例常见报文体大致写成这样L2 U4 1001 // CEID事件 ID1001 代表 Carrier 已放置 L2 L2 U4 1 // 数据项编号 A CR1001 // Carrier ID 值 L2 U4 2 // 数据项编号 A PORT1 // Port 名识别放置位置 数据项编号 1 和 2 不是拍脑袋定的分别对应协议里定义的Carrier ID与Port ID。这里我可以给你一个实际经验凡是在事件里带上 Port ID 的项目后期做 traceability追溯都会轻松很多。只发 Carrier ID、不发 Port ID 的方案一旦产线有同型号设备多台查批次流向时你需要靠 OHT 的路径日志反推麻烦得多。2.3 一轮完整的搬运流程长什么样从 Host 下发到设备回报把状态机、事件和消息拼起来就是设备端日常跑的搬运循环。下面用一个带设备端和 Host 端的交互序列展示典型流程里每个动作对应到哪个 E87 事件步骤动作报文/事件说明1OHT 小车把 Carrier 放到设备 Port设备检测到 Carrier 放置完成触发硬件互锁信号设备准备上报2设备识别 Carrier ID读取 Carrier 条码或 RFID识别失败时可进入人工干预流程3设备上报放置完成S2F41 携带 CEIDCarrier PlacedHost 记录 Carrier 已到达4Host 进行配方与批次绑定下发加工控制消息绑定结果可以主动回报也可直接进下一步5设备开始加工CEIDProcessing Started通知 Host 当前 Carrier 进入加工6设备加工完成CEIDProcess CompleteHost 更新其数据库状态7Host 确认可搬离下发 Carrier Remove 请求视设备实现设备收到后才允许搬运系统取件8设备检测到 Carrier 移走CEIDCarrier Removed整个交接闭环完成设备回到空 Port 状态很多设备厂商默认省略了第 7 步加工完自动允许取走。这在研发测试环境没问题但量产线如果出现“上批加工完还没确认下一批已经被 OHT 送来放在同一个 Port”就可能造成数据错位。所以进量产前我会强制检查一件事设备端是否真的在 PROCESS COMPLETE 后多做一个 Host 确认动作才释放 Carrier。这一步非常关键也是后面“避坑”一节里重点展开的内容。3. 落地时先摸清两种对接模式透明模式与 Peer-to-Peer 模式3.1 透明模式中间加一层 MES 网关设备端改动最小透明模式是早期很多工厂 E87 实施的默认方案。设备不直接跟搬运系统对话而是在中间加一个 MES/调度层。搬运系统比如 OHT还是做自己的物理搬运动作但它不直接跟设备协商 Carrier 状态而是先告诉 MES“我把 Carrier 放到了 3 号设备的 Port2”再由 MES 向设备发起状态核对和确认。这种模式的好处有两个一是设备端只需要实现自己跟 MES 的那一段 E87不需要理解 OHT 的调度命令二是 MES 层可以做防错比如检查 Port 是否空闲、批次是否匹配、设备是否有告警满足条件后再回复搬运系统。缺点是每一次交接多一次网络往返节拍稍慢并且在 MES 宕机时整个搬运衔接也会停摆。我常见的做法是在透明模式下设备侧不需要关心消息是 MES 发的还是 OHT 发的只要把 E87 状态机实现完整照常发事件、收确认即可。真正要改的是 MES 侧的流程编排它要把 E87 事件和 OHT 任务状态关联起来。以下是一个典型的映射关系表OHT 任务状态E87 事件MES 动作搬运中无等待 Carrier 到达已放置在 PortCarrier Placed确认 Carrier ID绑定批次请求取走Carrier Removable通知 OHT 可以取货已移走Carrier Removed关闭工单释放 Port这套映射跑顺之后产线上每一次搬运你都能在 MES 里看到一条完整的生命周期记录这给后面的良率分析、设备利用率统计都留了原始数据。3.2 Peer-to-Peer 模式设备与搬运系统直连适合自动化岛在自动化程度更高的车间尤其是局部 small lot 产线或设备岛内部会直接用 Peer-to-Peer 模式。设备和 OHT/搬运系统之间直接走 E87 消息不经过 MES 中转调度逻辑由搬运系统内置。这种模式真正的复杂度在于设备端口的状态管理和安全互锁。直连时搬运系统需要知道设备“当前是否可以接收 Carrier”和“是否允许取走 Carrier”这两个信息完全来自设备端 E87 状态。如果设备处于维护模式、报警状态、Port 被禁用搬运系统必须能及时收到状态变化否则就会出现“小车傻乎乎把货放到一台报警停机的设备前”。Peer-to-Peer 模式下设备端状态变化必须又能推又能拉推每当设备状态变化主动向搬运系统发送事件。拉搬运系统在调度前先询问设备当前状态确定 Port 可用再出发。实际项目里我会保持“搬运系统每次放片前主动拉一次 Port 状态”的兜底逻辑不要只依赖事件推送。原因很朴素网络断线或设备状态更新延迟时靠事件推送很可能漏掉一次关键变化而拉取是请求应答式至少当次任务能看到最新状态。3.3 两种模式的选型判据节拍、系统耦合度和异常恢复能力判断该用哪种模式不要只看系统链路图要问三件事节拍要求单次交换允许 300ms 的额外时延吗透明模式一次交接多 1~2 次消息往返如果是超高速设备连续搬运时延可能成为瓶颈。系统耦合度现有 MES 是否已经深度嵌入 OHT 调度若是直接改造成透明模式成本更低。异常恢复MES 宕机时现场能否继续生产透明模式在 MES 故障时几乎瘫痪而 Peer-to-Peer 至少设备与搬运系统还能在降级模式下人工介入。我见过的实际工厂里早期多采用透明模式后来为了降本增效、提升节拍新厂大多在设备岛内改用 Peer-to-Peer。老厂在改造时比较麻烦的是旧设备的 SECS/GEM 软件包里往往没有实现全套 E87只有部分事件此时建议先补测状态机完整性再上 Peer-to-Peer避免带病上线。4. 用 SEMI E87-0301 搭建最小可运行环境模拟器、配置和联调步骤4.1 选型模拟设备端用什么模拟 Host 用什么没有真实设备时E87 的消息调试一般靠两类工具组合一个是模拟 Host 端一个是模拟设备端。常见做法是用支持 SECS-II 的开发包比如开源的 secs4java、GEM300 模拟器跑两端。计算环境里没有硬件资源时也可以用两个 Python 程序分别扮演 Host 和 Equipment通过 TCP 通信模拟整套消息流程。这是很多工程师第一次接触 SECS/GEM 时最大的迷惑点他们以为必须有台真实设备才能开始写 E87。事实不是这样协议本身是纯文本消息通过网口就能收发。只要实现一个最小消息集就能完成从通信建立到搬运闭环的验证。4.2 最小设备端代码骨架用 Python 实现 Event 发送我一般会先把设备端 E87 的 Event 发送逻辑搭出来。下面这段代码是一个简化的设备端程序框架不包括完整的状态机管理但足以让你看到 E87 消息如何打包发送。import socket import struct # 简单的 SECS-II 编码把字符串变成一个头 数据体 def encode_secs_message(stream, function, body: bytes): # SECS-I 长度头共 4 字节这里简化处理 length 4 len(body) # 方向位 0 表示从 Host 到 Equipment1 表示从 Equipment 到 Host header struct.pack(HHBB, 0, 0, stream, function) bytes([0, 0]) return header body def send_event_to_host(host_ip, host_port, event_id, carrier_id, port_id): # 组装一个简化版 S2F41 报文 message_body b\x01\x01\x0a # 简化编码仅示意 raw_msg encode_secs_message(2, 41, message_body) with socket.create_connection((host_ip, host_port), timeout5) as sock: sock.sendall(raw_msg) print(fSend event {event_id} to host, carrier{carrier_id}, port{port_id}) # 模拟检测到 Carrier 放置后调用 send_event_to_host(127.0.0.1, 9000, 1001, CR1001, PORT1)这段代码只演示消息发送实际项目里要把事件与设备状态机挂钩。建议你在设备端实现一个状态表只有CARRIER ID READY状态才允许发送Carrier Placed事件状态不对就不允许发送并且记录到日志里。这样做的好处是后续排错时你一眼能看出设备是在哪个状态下做了非法动作而不是只能看到一串 Raw Data。参数说明host_ip与host_port指向你的 Host 模拟器event_id要与 Host 映射一致carrier_id是条码值port_id是物理端口名。这些参数一定不要硬编码建议放到配置文件或数据库里。产线上设备编号、端口编号是会变的硬编码改一次哭一次。4.3 最小 Host 端代码骨架接收事件与状态更新Host 端要能接收设备的事件解析事件 ID 和携带的数据项并更新自身状态记录。这里给出一段简化的接收端程序便于你跑通两端完整的收发流程。import socket def handle_event(device_ip, data): # 简化解析假定事件 ID 是某个偏移位置取 4 字节 event_id int.from_bytes(data[8:12], big) # 实际报文解析要按 SECS-II 的格式逐层拆这里只是演示 if event_id 1001: print(fCarrier placed event from {device_ip}: update carrier table) elif event_id 1002: print(fProcess started event from {device_ip}: start timer) else: print(fUnknown event: {event_id}) # 建立 TCP Server等待设备连接 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((0.0.0.0, 9000)) s.listen() print(Host listening on port 9000) conn, addr s.accept() with conn: while True: data conn.recv(4096) if not data: break handle_event(addr[0], data)这个程序只实现了接收与打印真实 Host 端需要把事件映射到业务数据结构。例如用一张表保存 Carrier ID 当前状态、所属设备、Port、时间戳供后续追溯界面查询。接收端最容易踩的坑是粘包和拆包SECS 消息是多个 TCP 包拼在一起或者一个包里有多条消息不能简单按 recv 一次当成一条。正解是解析消息头部里的 Length 字段按长度切包。4.4 联调序列先建立通信、再测正常流程、最后测异常流拿到两端之后不要上来就全流程跑通。我的习惯是分三步联调每步都有明确通过标准。第一步通信测试按下设备端初始化按钮观察 Host 端是否收到 S1F13 建立通信请求。Host 回应 S1F14 后设备端应显示通信已建立。通过标准两端日志都出现通信建立记录且没有超时重试。第二步正常流程测试用模拟器模拟一次 Carrier 放置。观察 Host 是否收到 Carrier Placed 事件。手动在 Host 端确认接着触发搬运系统取走动作。通过标准完整经过 ID READY 到 REMOVABLE 再到 REMOVED所有状态都能在 Host 数据库里查到。第三步异常流程测试Carrier 未正确读取 ID 时设备应报告识别失败而不是进入 READY。Host 端如果在 Carrier 放置后迟迟不确认设备不得自行放出 Carrier。网络断线再恢复时设备与 Host 要能重新建立通信且之前未完成的状态能通过查询恢复。第三步往往能暴露真实项目里最麻烦的问题。下面这一节就把我在现场常遇到的坑逐一列出你可以直接对号入座。5. E87 联调排障五个反复踩的坑附原因和解决方案5.1 坑一事件 ID 对不上接收端报 Unknown Event现象设备端明明发送了 Carrier Placed 事件Host 日志却显示Unknown event id。原因设备端配置的事件 ID 与 Host 端的映射表不一致。很多时候设备供应商出厂配置是 1001 代表放置完成但 Host 端沿用上一个项目的映射表1001 代表的是“搬运请求”。解决用配置表管理事件 ID而不是写死在代码里。联调第一步就让设备端导出一份事件列表Host 端逐个核对含义。每次设备端软件升级后也要重新核对一次不能默认不变。5.2 坑二设备加工完成直接放行 Carrier跳过 Host 确认现象生产过程中上一批还没被 Host 在数据库里标记完成下一批已经被 OHT 放到同一个 Port。原因设备端没有实现 PROCESS COMPLETE 到 CARRIER REMOVABLE 之间的控制门。设备厂商默认开放丢失了 E87 定义的确认动作。解决在设备端补上这一控制逻辑——只有收到 Host 的明确确认可能是 S2F41 的回复也可能是专用指令才允许搬运系统取件。若设备端无法改造就在 MES 层强制介入MES 必须先从设备收到状态再通知 OHT 放行。现场实施时记得检查上游设备、下游设备两端的确认机制只改一端仍然可能产生漏单。5.3 坑三Port ID 不随事件上报追溯全靠猜现象查批次历史时只知道某一批在某台设备上加工过但当台设备有 4 个 Port无法确定是从哪个 Port 进的、哪个 Port 出的。原因设备端事件里只写了 Carrier ID没有带 Port ID。协议允许这样写但从追溯角度是残缺数据。解决联调时把 Port ID 加进关键事件放置完成、移走完成的数据项中。如果设备供应商说做不到要求对方至少把 Port ID 打在全事件日志里Host 可以靠时间戳与事件记录关联。注意只有 Carrier ID、没有 Port ID 的数据在量产后会变成不可修复的历史黑洞。5.4 坑四TCP 粘包和半包导致报文解析错位现象Host 偶发报错显示消息解析失败重连后又能正常工作一阵子。原因SECS-I 基于 TCP 传输报文边界不保证正好等于 recv 的边界。实现时如果按 recv 一次拼一条消息很容易把两条消息拼在一起或拆散。解决接收端必须维护一个缓冲区循环解析每次按头部 Length 字段切出完整消息。切完之后剩余字节继续留在缓冲区。数据量大的产线环境建议排查一下接收缓冲是否过小必要时调大内核缓冲区。5.5 坑五设备状态机卡死复位后业务数据不同步现象设备侧网络异常后Host 显示通信断开设备侧显示还在 Processing。原因重连时没有先做状态同步。设备侧认为通信断了业务照跑Host 侧则在等待事件两边状态不一致。解决通信恢复后Host 主动发送状态查询设备回复当前所有 Port 的 Carrier 状态。Host 以设备回复为准重新建立自己内部的记录。这一步要写进重连流程里而不是仅仅恢复 S1F13/S1F14 就算完。现场最容易忽略的是重连完成之后Port 状态和流程状态没有同步导致后续动作建立在错误前提上。6. 进阶验证方法用 E87 事件日志反推设备搬运轨迹精准定位瓶颈顺完基本流程站到进阶视角时E87 的价值就不只是“防错”了。它的事件日志本身就是一个丰富的数据源可以用来反推每台设备的实际利用率、搬运时间和等待时间。很多工厂上了 E87 只盯着异常报警把 Event 日志当作排错工具实在太可惜。我的做法是把设备事件导出为一份时间线例如事件时间设备名PortCarrier ID事件类型09:00:01.123ETCH-01PORT1C2021001Carrier Placed09:00:05.456ETCH-01PORT1C2021001Processing Started09:12:37.890ETCH-01PORT1C2021001Process Complete09:12:40.112ETCH-01PORT1C2021001Carrier Removed从这份时间线能算出几个指标放置到开始加工的时间设备的启动响应速度。加工时间设备实际工艺时间。加工完成到被取走的时间搬运系统的响应速度也是设备空闲等待的外在表现。如果某个 Port 的“放置到开始加工”时间从 2 秒慢慢涨到 15 秒很可能不是设备慢而是 Host 下发配方前的检查项越来越多或者通信链路变慢。把 E87 状态时间戳与 MES 工单时间戳对齐后瓶颈在设备端还是调度端一眼就能区分。手动验证的话可以做一个很小的脚本把 E87 事件日志按 Carrier ID 分组然后计算每个阶段的时间差输出异常阈值。例如我对“放置到开始加工”超过 30 秒的记录打标记对“加工完成到移走”超过 60 秒的记录打标记。产线设备多了之后这份异常名单能帮你在巡检时直接锁定问题端口。我自己的习惯是每次新项目上线后连续一周每天导出 E87 事件日志按上述时间线做一次人工跑查看看有没有状态丢失、事件重复、时间戳倒挂。时间戳倒挂是我特别敏感的信号——它通常就是设备端时钟未同步或消息重发导致的会搞乱追溯。解决方法是让设备端和 Host 都在同一台 NTP 服务器上校时且不要在设备本地生成业务时间统一用 Host 接收时间做主记录。最后一个忠告E87 没你想的那么复杂但它比你想的更不容出错。跑通协议只是起点把日志用起来、把状态一致性盯住才是让整套自动化系统稳定运行的正道。希望这些一线经验能帮到你在现场少走我当年走过的弯路。本文还有配套的精品资源点击获取
返回列表