SECS/GEM 协议栈开发笔记 · 第 1 篇
基于代码库:Libsecs(一个 C++ 实现的 SEMI 协议栈)
说在前面:由于工作的原因,本人早些年开发了一套SEMI标准的协议栈用于公司的SECS标准实现,为了防止经验遗忘,特写下本专辑以免后续忘记。
如果你在晶圆厂(fab)待过,或者做过设备端软件,大概率撞见过这种场景:
产线主管跑过来说,新到的那台设备得上 EAP;IT 甩给你一份接口文档,满篇"S1F13 建立通信""S6F11 事件上报";你盯着这些字母数字组合,心里只剩一个问号:设备到底是怎么跟工厂系统聊起来的?
先认识三个"说话的对象"
产线里真正在通信的,其实就三个角色:
- 设备(Equipment):刻蚀机、光刻机、贴片机这些干活的。它负责生产,也负责把"我在干嘛、出没出问题"告诉外界。
- 主机(Host):通常指 EAP(设备自动化程序)。它一头连设备,一头连上层工厂系统,相当于车间的"现场调度"。
- 工厂系统(MES):管排产、管批次、管报表的那套大系统,站在最上面,决定"这块 wafer 接下来去哪"。
设备一般不直接跟 MES 聊,中间隔着 Host 这层。你可以理解成:设备只跟"工长"(Host)汇报,工长再去跟"总部"(MES)对接。
#mermaid-svg-pkeMttUgmlPbrXT6{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pkeMttUgmlPbrXT6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pkeMttUgmlPbrXT6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pkeMttUgmlPbrXT6 .error-icon{fill:#552222;}#mermaid-svg-pkeMttUgmlPbrXT6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pkeMttUgmlPbrXT6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pkeMttUgmlPbrXT6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pkeMttUgmlPbrXT6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pkeMttUgmlPbrXT6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pkeMttUgmlPbrXT6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pkeMttUgmlPbrXT6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pkeMttUgmlPbrXT6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pkeMttUgmlPbrXT6 .marker.cross{stroke:#333333;}#mermaid-svg-pkeMttUgmlPbrXT6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pkeMttUgmlPbrXT6 p{margin:0;}#mermaid-svg-pkeMttUgmlPbrXT6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pkeMttUgmlPbrXT6 .cluster-label text{fill:#333;}#mermaid-svg-pkeMttUgmlPbrXT6 .cluster-label span{color:#333;}#mermaid-svg-pkeMttUgmlPbrXT6 .cluster-label span p{background-color:transparent;}#mermaid-svg-pkeMttUgmlPbrXT6 .label text,#mermaid-svg-pkeMttUgmlPbrXT6 span{fill:#333;color:#333;}#mermaid-svg-pkeMttUgmlPbrXT6 .node rect,#mermaid-svg-pkeMttUgmlPbrXT6 .node circle,#mermaid-svg-pkeMttUgmlPbrXT6 .node ellipse,#mermaid-svg-pkeMttUgmlPbrXT6 .node polygon,#mermaid-svg-pkeMttUgmlPbrXT6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pkeMttUgmlPbrXT6 .rough-node .label text,#mermaid-svg-pkeMttUgmlPbrXT6 .node .label text,#mermaid-svg-pkeMttUgmlPbrXT6 .image-shape .label,#mermaid-svg-pkeMttUgmlPbrXT6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-pkeMttUgmlPbrXT6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pkeMttUgmlPbrXT6 .rough-node .label,#mermaid-svg-pkeMttUgmlPbrXT6 .node .label,#mermaid-svg-pkeMttUgmlPbrXT6 .image-shape .label,#mermaid-svg-pkeMttUgmlPbrXT6 .icon-shape .label{text-align:center;}#mermaid-svg-pkeMttUgmlPbrXT6 .node.clickable{cursor:pointer;}#mermaid-svg-pkeMttUgmlPbrXT6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pkeMttUgmlPbrXT6 .arrowheadPath{fill:#333333;}#mermaid-svg-pkeMttUgmlPbrXT6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pkeMttUgmlPbrXT6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pkeMttUgmlPbrXT6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pkeMttUgmlPbrXT6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pkeMttUgmlPbrXT6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pkeMttUgmlPbrXT6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pkeMttUgmlPbrXT6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pkeMttUgmlPbrXT6 .cluster text{fill:#333;}#mermaid-svg-pkeMttUgmlPbrXT6 .cluster span{color:#333;}#mermaid-svg-pkeMttUgmlPbrXT6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pkeMttUgmlPbrXT6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pkeMttUgmlPbrXT6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-pkeMttUgmlPbrXT6 .icon-shape,#mermaid-svg-pkeMttUgmlPbrXT6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pkeMttUgmlPbrXT6 .icon-shape p,#mermaid-svg-pkeMttUgmlPbrXT6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pkeMttUgmlPbrXT6 .icon-shape .label rect,#mermaid-svg-pkeMttUgmlPbrXT6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pkeMttUgmlPbrXT6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pkeMttUgmlPbrXT6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pkeMttUgmlPbrXT6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} MES 工厂系统
排产 / 批次 / 报表
Host / EAP
现场调度
Equipment 设备
生产 + 上报状态
为什么非得有套"标准语言"
早些年没有统一标准时,每家设备厂都自己搞一套通信协议:A 家用串口发二进制,B 家用自定义 XML,C 家甚至拿 telnet 敲命令。结果就是------
每进一台新设备,fab 的集成工程师就得从头写一套对接程序;设备一升级,对接可能就崩;换个厂牌,全部重来。这种重复劳动,在动辄几百台设备、几十个厂牌的产线里,成本高得离谱。
SECS 就是为这件事诞生的:它把"设备跟主机之间怎么传消息"标准化成了一整套规则。大家都说同一种语言,设备厂和 fab 都省心。
SECS 和 GEM,到底什么关系
这是新手最容易绕晕的地方,我打个比方:
- SECS 管"怎么传"。它规定消息长什么样、怎么打包、走串口还是网线、收不到回复怎么办。它解决的是通信本身的可靠性。
- GEM 管"传什么、怎么聊"。光能传字节还不够,你得更进一步约定:设备上线要先报个到(建立通信),出报警了要主动通知,host 让你读个参数你得回。GEM 就是架在 SECS 之上的"行为准则",规定一台"合规"的设备该会哪些本事。
一句话:SECS 是电话线路和通话规则,GEM 是大家约定好的业务话术。 光有线路打不了业务电话,光有话术没有线路也传不出去。两者合起来,就是常被提到的 SECS/GEM。
这套东西在标准里叫什么号
SECS/GEM 不是一份文档,而是一族 SEMI 标准。先混个脸熟,后面逐个展开:
- E4 / SECS-I:最底下那层,走串口的传输规则。
- E37 / HSMS:后来用网线(TCP/IP)取代串口的那层,现在主流都用它。
- E5 / SECS-II:消息内容怎么组织,也就是数据项(Item)和 SxFy 这套编号。
- E30 / GEM:最上面那层,定义设备该有的行为和状态。
- E87 等:GEM 之上的扩展,比如载具(Carrier)管理。
这些编号都是标准规范约束的,没有为什么,就是人家老外很早就定下来的标准,我们必须服从,毕竟标准是人家建立的。先建立一层概念:大概就是底下管"怎么传",中间管"传什么格式",上面管"怎么聊业务",再往上还有各种扩展,就这样。
这个系列专辑打算怎么讲
我手边早些年做了一个纯 C++ 写的SEMI协议栈,叫 LibSecs,上面说的 E4/E5/E37/E30 它都实现了,还带了 E87 扩展。这个系列就拿它当样本,把 SECS/GEM 讲透的同时,也把"一个协议栈怎么搭出来"的思路带出来,目的是给自己复盘实现过程,也好给半导体人参考。
这个专辑的连载文章可能会这样进行:
- 不堆标准原文。标准谁都能下,会更多的去理解"为什么标准要这么定"。
- 也不逐行贴源码。代码太大,贴出来也未必看得进。会讲实现思路------状态机怎么搭、消息怎么路由、数据项怎么设计------挑关键处给点片段。
- 每篇尽量走"概念 → 思路 → 跑一下/想一想",能动手的就去验证。
篇幅的话可能大概是 20 篇,路线是这样的:
- 基础理解:SEMI 标准分层、SECS-I、HSMS、SECS-II 消息模型、序列化;
- 架构骨架:事务管理、消息分发;
- 研究 GEM:通信 / 控制 / 加工三个状态机,以及事件、变量、Trace、报警、远程命令这些"本事";
- 研究GEM扩展:E87 载具管理,以及怎么在 LIBSecs 上自己加一条新消息。
- 可能会拓展到GEM300(待定)
下一篇聊什么
下一篇把 SEMI 那张"协议栈分层图"摊开:E4、E37、E5、E30 各自站在哪一层、彼此怎么咬合,先研究以下在开始讲实现。
需要注意的是:我不是 SEMI专家,也是啃标准文档一步一步实现的,理解有偏差欢迎拍砖。如果你已经在做设备对接,不妨说说被 SECS 哪块坑过------是建链握手卡住?事件上报对不上?还是报警状态机绕晕了?可以一起探讨。