← 전체 글
SECS/GEM/약 20분 읽기/ 조회

Equipment Constant는 이름만 다른 Recipe 변경이다

Host가 EC를 썼고 장비는 EAC = 0을 돌려줬는데도 아홉 lot이 이전 값으로 돌았다. SEMI E5 EAC code, 실제 socket에서 뜬 S2F13 readback byte, S2F29 namelist, SAT에서 돌릴 EC test matrix.

SECS/GEMMES문제 해결프로젝트 노트체크리스트

아홉 lot이 이전 threshold로 돌았다

화요일 06:40, 엔지니어가 계측 장비의 검사 threshold를 바꿨다. S2F15에 ECID 하나, 새 값 하나. 장비는 S2F16으로 EAC = 0을 돌려줬다. 승인. MES는 request ID에 변경을 기록하고 constant를 updated로 표시한 뒤 queue를 풀었다.

그 장비는 새 값을 수신 시점이 아니라 다음 recipe load 시점에 적용하는 구조였다. 이미 carrier가 진행 중이었고, scheduler는 recipe reload 없이 남은 shift 내내 물량을 밀어 넣었다. 모든 기록 시스템이 새 값이 적용됐다고 말하는 동안 아홉 lot이 이전 threshold로 흘러갔다.

설정이 틀린 건 아니다. Host가 물었고 장비가 그렇다고 답했을 뿐인데, 그 "그렇다"의 범위가 아무도 확인하지 않은 만큼 좁았다. Acknowledge와 실제 적용 사이의 이 간극에서 EC 사고 대부분이 나오고, acknowledge code는 그 간극을 알려주지 못한다.

EAC = 0은 "받았다"이지 "적용됐다"가 아니다

SEMI E5가 실제로 보장하는 범위를 정확히 볼 필요가 있다. S2F16EAC는 binary 1 byte고, E5가 뜻을 정해 둔 값은 256개 중 네 개뿐이다.

EAC의미
0Acknowledge
1거부 — 존재하지 않는 constant가 하나 이상 있음
2거부 — busy, 나중에 재시도
3거부 — 범위를 벗어난 constant가 하나 이상 있음
4–63E5 예약 — 정의된 뜻 없음

사람들이 틀리는 줄은 마지막 줄이다. 4는 "거부, 기타"가 아니다. E5가 거기 정해 둔 뜻이 아예 없다. 그리고 예약(reserved)은 사용 가능과 다르다. 그래도 7을 돌려주는 장비는 실제로 있다. 즉 이건 규격 문제가 아니라 그 장비 manual 문제다. E5가 그 범위 사용을 허용한다는 근거는 확인하지 못했으니, 3보다 큰 vendor code는 그 장비의 사설 확장으로 취급하는 게 안전하다.

어느 쪽이든 host parser 모양은 같다. Byte 비교에 default 분기를 반드시 넣는다. 0이 아니면 전부 거부로 보고 원본 숫자를 로그에 남긴다. 모르는 enum이 그렇듯 그냥 흘러 나가게 두면 안 된다. Default가 없어서 매핑 안 된 EAC를 성공으로 처리한 host를 본 적이 있다.

계약은 여기까지다. 적용 시점을 약속하는 항목도, 여러 ECID를 담은 message가 원자적으로 처리된다는 항목도 없다. Vendor마다 둘 다 다르게 구현한다. ECID 세 개짜리 S2F15를 받아 둘만 적용하고 나머지 하나는 내부적으로 거부하면서도 EAC = 0을 돌려주는 장비를 본 적이 있다.

그래서 loop는 host가 직접 닫아야 한다.

  1. Write 후 S2F13으로 다시 읽어 ECV를 비교한다. 값뿐 아니라 format까지 본다.
  2. 장비의 change event(S6F11)를 기다려 request ID와 연결한다.
  3. ECID별로 값이 언제 유효해지는지 기록한다. 즉시인지, 다음 recipe load인지, 다음 carrier인지, PPSELECT 이후인지, software restart 이후인지.

3번을 건너뛰는 이유는 manual에 대개 "즉시 적용"이라고 적혀 있기 때문이다. 연동 시험 때 동작을 눈으로 확인할 수 있는 constant를 골라 write하고, ack이 온 시점이 아니라 동작이 바뀐 시점을 본다. 해당 장비에서 batch 원자성을 따로 검증하지 않았다면 message 하나당 ECID 하나로 쪼개서 보낸다. 왕복 횟수보다 고장 진단이 쉬운 쪽이 이득이다.

Readback은 wire에서 이렇게 생겼다

위의 1번은 vendor PDF 보고 구현한 뒤 실제 byte를 한 번도 안 들여다보는 항목이다. 그래서 떠 봤다. Host 쪽은 Python socket client, 장비 쪽은 SECS/GEM simulator의 HSMS passive listener(127.0.0.1:5501, SessionID 11, fault 없음). 아래 frame은 전부 장비 쪽 RX 로그에 찍힌 것이다. Message 객체를 예쁘게 출력한 게 아니라 진짜 wire byte다.

Data message를 보내려면 먼저 SELECTED로 들어가야 한다.

TX  00 00 00 0A  00 0B 00 00 00 01  00 00 00 01     Select.req
RX  00 00 00 0A  00 0B 00 00 00 02  00 00 00 01     Select.rsp, Select Status 0

그다음 빈 list를 담은 S2F13. SEMI E5는 이걸 equipment constant 전부 달라로 읽는다.

TX  00 00 00 0C  00 0B 82 0D 00 00 00 00 00 02  01 00
Byte필드
00 00 00 0CLength12 — header 10 byte + body 2 byte
00 0BSessionID11
82Header byte 2W-bit 0x80 설정, Stream 2
0DHeader byte 3Function 13
00PType0, SECS-II
00SType0, data message
00 00 00 02SystemBytes2
01 00BodyL,0 — item 0개짜리 list

같은 요청에 ECID 두 개를 U4로 넣은 것, 그리고 ASCII로 넣은 것. E5는 둘 다 허용한다. 그게 핵심이다.

TX  00 00 00 18  00 0B 82 0D 00 00 00 00 00 03
    01 02  B1 04 00 00 01 2C  B1 04 00 00 01 2D

TX  00 00 00 3B  00 0B 82 0D 00 00 00 00 00 04
    01 02  41 17 45 43 33 30 30 5F 54 61 72 67 65 74 54 65 6D 70 65 72 61 74 75 72 65
           41 14 45 43 33 30 31 5F 54 61 72 67 65 74 50 72 65 73 73 75 72 65

01 02item 두 개짜리 list다. List의 length 필드는 byte 수가 아니라 원소 개수를 센다. 이 capture를 처음 뜰 때 나도 그걸 byte 수로 넣었고, listener는 그 잘못된 frame을 아무 불평 없이 RX 로그에 찍었다. RX 로그가 깨끗하다는 게 뭘 보장해 주는지에 대한 꽤 정직한 경고다. B1은 format code 54 octal(U4)에 length byte 1개, 그래서 B1 04 00 00 01 2C가 ECID 300이다. 41은 format code 20 octal(A), 41 17은 23자 문자열이고 45 43 33 30 30 5FEC300_이다. ECID를 U4로 못 박은 host는 이 message에서 안 깨진다. 몇 달 뒤 ASCII ECID를 쓰는 장비가 들어올 때 깨진다.

셋 다 S2F14를 못 받았다. 이건 이 listener 특성이다. HSMS control message만 구현돼 있고 SECS-II responder가 없다. 장비 동작으로 읽으면 안 된다. 가져갈 건 모양이다. 응답 없는 readback 세 개 직후에 보낸 Linktest.req는 1 ms 안에 Linktest.rsp를 받았다.

TX  00 00 00 0A  00 0B 00 00 00 05  00 00 00 05     Linktest.req
RX  00 00 00 0A  00 0B 00 00 00 06  00 00 00 05     Linktest.rsp

HSMS는 링크가 멀쩡하다고 말하는데 application layer는 아무 말이 없다. Linktest로 장비 상태를 판단하는 host는 EC readback이 한 shift 내내 무응답인 동안 인터페이스를 초록색으로 표시한다. 여기서 돌아야 하는 시계는 E37의 T3 reply timeout이고 default는 45초다. 내 client는 message당 2초만 기다리고 넘어갔으니 capture의 대기 시간은 T-timer 값이 아니라 client 쪽 값이다.

목록은 장비에게 물어본다: S2F29

MES에 아무것도 넣기 전에 S2F29(Equipment Constant Namelist Request)를 빈 list로 보내 S2F30으로 전체를 받는다. ECID, ECNAME, ECMIN, ECMAX, ECDEF, UNITS가 온다. 이 응답은 지금 돌고 있는 software가 생성한 값이다. FAT 때 vendor가 메일로 보낸 PDF는 그렇지 않다.

E5는 이 항목들의 형식을 일부러 넓게 열어 뒀다. ECIDU1/U2/U4/U8, 부호 있는 I 계열, A 중 아무거나로 올 수 있고, ECMIN/ECMAX/ECDEF는 숫자 형식 전부에 A, B, BOOLEAN까지 가능하다. ECNAMEUNITS만 항상 A다. ECID를 U4로 가정한 parser는 constant 번호를 ASCII 문자열로 매기는 장비를 만나기 전까지만 돌아간다. 그리고 그때는 write가 아니라 접속 단계에서 깨진다.

이걸 interface 사양서와 diff한다. 대체로 이런 게 나온다.

  • 어떤 문서에도 없던 ECID. 그중에 재미있는 게 섞여 있다.
  • Firmware update로 넓어지거나 좁아진 range. MES 범위 검사가 장비는 받아줄 값을 거부하거나, 반대로 장비가 clamp할 값을 통과시킨다.
  • 현장 가정과 다른 UNITS. 초와 밀리초가 대표적이고, 단위를 틀린 T3 timeout은 network 문제처럼 보이는 방식으로 실패한다.
  • Namelist에는 있지만 실제로는 read-only여서 write하면 vendor 영역 EAC로 거부되는 constant.

장비 software를 update할 때마다 S2F30 응답을 snapshot해서 이전 것과 diff한다. script 열 줄 정도인데, release note보다 조용한 동작 변경을 훨씬 많이 잡아준다.

분류부터 한다. 안 그러면 화면 언어 설정에 결재가 붙는다

모든 constant에 변경 요청서가 필요하진 않다. 무엇을 망가뜨릴 수 있는지로 나눈다.

구분관리 기준
정보성UI 언어, 화면 blank timeoutLocal 변경, 승인 불필요
통신T3 reply timeout, event report enableEngineering 검토, 연동 재시험
자동화 동작Auto-start enable, carrier verification modeHost 가시성, audit, idle에서만
공정 중요검사 threshold, 온도 offset공정 owner 승인, rollback 값 필수
정비 bypassSensor ignore, dry-run mode시간 제한 승인, 만료 강제

Class는 이름이 아니라 그 장비의 ECID에 붙는다. 같은 vendor parameter가 구형 platform에서는 표시용이고 신형에서는 실제 sequence 조건인 경우가 흔하다. Interface 설계 단계에서 정한다. 이미 돌고 있는 장비에 분류를 나중에 붙이면 누군가 추측으로 채우고, 추측은 항상 낮은 쪽으로 간다.

정비 bypass는 아무도 요구하지 않아도 만료 시간을 강제로 건다. Reset event가 없는 bypass는 꺼지지 않는다. 잊힐 뿐이고, 반년 뒤 일탈 조사에서 발견된다.

ECID table은 하나, host 범위 검사는 거기서 생성한다

EC mismatch는 대부분 같은 모양이다. 규칙이 세 곳에 있다. MES는 0~10, 장비 ECMAX는 100, 그리고 둘보다 오래된 엔지니어 spreadsheet에 네 번째 숫자가 있다.

Table은 하나만 두고, host 검증 로직은 그 table을 읽게 한다. 다시 구현하면 안 된다. 최소 항목은 이렇다.

  • ECID, vendor ECNAME, 그리고 현장 언어로 쓴 기능 설명.
  • Format code(U4, I2, F4, A), unit, min, max, enumeration list.
  • Namelist에서 받은 ECDEF와 승인된 production value. 이 둘이 보통 다르다는 게 요점이다.
  • Host write 허용 여부, local operator edit 허용 여부.
  • 값이 유효해지는 시점.
  • 변경 audit에 쓰는 event 또는 report.
  • 승인 owner와 문서화된 rollback 값.

Format은 보기보다 중요하다. 장비가 U4를 기대하는데 U1을 보내면 어떤 구현은 조용히 변환하고, 어떤 구현은 truncate하고, 어떤 구현은 vendor 영역 EAC로 거부하고, 하나는 보내지도 않은 값을 저장한다. Readback에서 숫자만 보지 말고 format도 assert한다.

결국 물리는 건 local panel 변경이다

Host 변경은 쉬운 쪽이다. Request, ack, readback, event가 다 있다. 위험한 건 03:00에 operator나 vendor service engineer가 장비 화면에서 직접 값을 바꾸는 경로다.

GEM의 control state model(ON-LINE/REMOTELOCAL)은 누가 장비를 명령할 수 있는지는 정하지만, local 변경이 host에서 보이는 event를 만든다는 보장은 하지 않는다. Old value와 new value를 담아 collection event를 올리는 장비도 있고, 아무 정보 없는 일반 "parameter changed" CEID만 올리는 장비도 있고, 아무것도 안 올리는 장비도 있다.

어느 쪽인지 확인하고 거기에 맞춰 만든다.

  • Change event가 있으면 ECID, 이전 값, 새 값, 변경 주체를 담은 report를 정의해 CEID에 연결하고 S2F33/S2F35/S2F37로 enable한다. Host write뿐 아니라 local 편집에서도 뜨는지 확인한다.
  • Event가 없으면 주기적 baseline sweep을 돌린다. 관리 대상 ECID를 S2F13으로 정기적으로, 그리고 lot 시작마다 읽어 승인값과 다르면 exception을 낸다.

Sweep은 우아하지 않지만, drift된 constant를 몇 분 만에 찾느냐 scrap 조사에서 찾느냐를 가른다. Local change event가 없는 장비에서는 15분 주기에 carrier 도착 시점을 더해서 돌린다.

장비 change event가 new value만 주고 old value를 안 준다면, write 보내기 전에 host가 먼저 읽어서 이전 값으로 저장한다. Host application log만으로 조립한 audit trail은 "그 시점에 장비가 정말 그 값을 들고 있었나"라는 질문 한 번에 무너진다.

Test case로 만들어 둘 만한 고장 패턴

아래는 전부 누군가의 shift를 날려본 것들이다.

  • 장비가 busy 중에 write를 accept하고 현재 lot이 끝난 뒤 적용한다. 다음 shift는 몇 시간 전 timestamp가 찍힌 변경 기록과 바뀐 장비를 함께 물려받는다.
  • Enumeration 불일치. MES는 AUTO를 ASCII로 보내고 장비는 1U1으로 원한다. Error는 없고 값만 안 바뀐다.
  • Software restart 후 장비가 host 승인값이 아니라 ECDEF를 다시 불러온다. 모든 constant가 조용히 되돌아간다.
  • Multi-module 장비에서 chamber마다 ECID가 따로 있는데 host는 chamber 1만 쓰고 장비 전체가 성공했다고 보고한다.
  • MES 범위 검사는 통과했지만 장비가 ECMAX로 clamp하고, readback하지 않으면 clamp된 값을 알 수 없다.
  • 두 시간짜리 PM용으로 켠 maintenance bypass가 한 달 뒤에도 켜져 있다.

이걸 script화한 EC test matrix에 넣고 FAT만이 아니라 SAT에서도 돌린다. 현장에 설치된 장비 software는 vendor에서 시험한 version과 다른 경우가 많다. 항목은 정상 write와 readback, 범위 밖 write(EAC = 3 기대), 존재하지 않는 ECID(EAC = 1 기대), 처리 중 write(EAC = 2 또는 문서화된 지연 적용 기대), 틀린 format code, local panel 편집, power cycle 후 유지.

Production에 넘기기 전에

  • 관리 대상 ECID list를 manual이 아니라 설치된 software version의 S2F30에서 생성했는가.
  • 모든 controlled constant에 owner, range, unit, 변경 가능 상태, rollback 값이 있는가.
  • Host write 권한을 실제 장비에서 확인했는가.
  • Invalid write가 깔끔하게 거부되고 일부만 적용되지 않는가. 여러 ECID를 담은 message로 검증했는가.
  • Readback이 값과 format을 함께 비교하는가.
  • Local 변경이 event나 sweep으로 감지되는가.
  • Audit record를 lot, equipment, ECID, 시간 구간으로 검색할 수 있는가.

이 중 go-live 이후로 미루기 쉬운 항목이 restart 유지 시험인데, 하필 그게 모든 constant를 한꺼번에 되돌리는 항목이다. 제품이 올라가기 전에 해본다. 승인값을 쓰고, 장비 controller를 power cycle하고, S2F13으로 전체를 다시 읽어 diff한다. 장비가 ECDEF를 들고 돌아온다면 ON-LINE 전환 시점에 host가 값을 복구하는 단계가 필요하다. 첫 PM 전에 만들어야 한다.

장비가 아직 없는 상태에서 transport 쪽만 미리 연습하고 싶다면, SECS/GEM simulator가 위와 똑같은 S2F13 byte를 실제 socket으로 받아 주고 장비 쪽에 뭐가 찍혔는지 보여준다.