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

화면은 ONLINE인데 S2F41이 HCACK 2로 튕긴다 — E30 제어 상태 세 가지

설비 화면은 ONLINE인데 S2F41 START가 HCACK 2로 거절될 때. E30의 통신 상태와 제어 상태를 구분하고, OFF-LINE·ON-LINE LOCAL·ON-LINE REMOTE를 명령 하나로 확인하는 법.

SECS/GEMMESSCADA문제 해결체크리스트

Host가 S2F41에 RCMD START를 실어 보냈다. S2F42가 1 ms 만에 돌아온다. HCACK은 2. 설비 앞에 서 있는 사람은 화면에 ONLINE이라고 떠 있다고 말한다. 회의실에서 30분이 그냥 간다.

HCACK 2는 SEMI E5에서 "지금은 수행할 수 없음"이다. 명령이 없다는 뜻도, 파라미터가 틀렸다는 뜻도 아니다. 상태가 아니라는 뜻이다. 그리고 설비 화면의 "ONLINE"과 SEMI E30이 말하는 상태는 같은 것이 아니다.

E30에는 state machine이 두 개 있고, 둘은 서로 다른 질문에 답한다.

E30의 두 state machine: S1F13/S1F14로 넘어가는 통신 상태와 S1F17/S1F15로 움직이는 제어 상태, S2F41이 통하는 자리는 ON-LINE REMOTE 하나 GEM 통신 상태GEM 제어 상태 NOT COMMUNICATING COMMUNICATING OFF-LINE ON-LINE LOCAL ON-LINE REMOTE S1F13 S1F14 Separate.req socket close S1F17 S1F15 operator 패널 S1F13 이전 · 모든 message → SxF0 OFF-LINE · LOCAL → HCACK 2 ON-LINE REMOTE → HCACK 0

통신 상태와 제어 상태는 다른 질문에 답한다

**통신 상태(communication state)**는 "SECS-II 대화가 열렸는가"에 답한다. 값은 NOT COMMUNICATING과 COMMUNICATING 두 개뿐이다. Host가 S1F13을 보내고 설비가 COMMACK 0을 실은 S1F14로 답하면 COMMUNICATING으로 넘어간다. Socket이 끊기거나 Separate.req가 오면 다시 NOT COMMUNICATING이다.

**제어 상태(control state)**는 "지금 이 설비를 누가 지시하는가"에 답한다. 값은 OFF-LINE, ON-LINE LOCAL, ON-LINE REMOTE 세 개다. Host의 명령을 받아 주는 자리는 마지막 하나뿐이다.

두 machine은 독립이 아니라 순서가 있다. 통신이 열리지 않았으면 제어 상태를 물어볼 일도 없다. 그래서 증상이 세 가지로 갈린다.

지금 상태S2F41을 보내면화면에는
NOT COMMUNICATING (S1F13 이전)S2F0 — function 0짜리 abort. 요청 자체가 없던 일이 된다대개 아무것도 안 뜬다
COMMUNICATING + OFF-LINES2F42, HCACK 2OFFLINE 또는 공백
COMMUNICATING + ON-LINE LOCALS2F42, HCACK 2ONLINE — 여기가 함정이다
COMMUNICATING + ON-LINE REMOTES2F42, HCACK 0ONLINE

세 번째 줄이 회의를 길게 만드는 줄이다. Operator가 설비 panel을 LOCAL로 돌려 놓으면 설비는 여전히 online이다. 화면도 ONLINE이라고 쓴다. 그런데 host 명령은 전부 HCACK 2로 튕긴다. Operator 입장에서는 아무것도 안 건드렸고, host 입장에서는 어제까지 되던 게 안 된다.

HCACK 값 자체를 다시 볼 일이 있으면 HCACK 0이 실제로 보장하는 것 쪽에 E5 코드 표가 정리돼 있다. 여기서 필요한 건 0과 2 두 개다.

SxF0을 "무응답"으로 읽지 말 것

S1F13 이전에 보낸 message는 거절당하는 게 아니라 abort된다. 설비는 같은 stream에 function 0을 붙여 돌려준다. S2F41에는 S2F0, S1F3에는 S1F0이다.

이걸 T3 timeout으로 오독하는 host driver를 자주 본다. Function 0은 body가 없고 W-bit도 없으니, function 필드를 안 보고 "기대한 S2F42가 아니면 응답 없음"으로 처리하면 45초를 기다린 뒤 없는 network 문제를 찾으러 간다. Socket은 멀쩡하고 설비는 1 ms 만에 답했다.

HSMS가 selected인데 여기서 막히는 경우는 selected와 communicating을 구분하는 글에 따로 적어 뒀다.

제어 상태를 움직이는 message

Host 쪽에서 제어 상태를 바꾸는 방법은 두 개다.

  • S1F17 Request ON-LINE → 설비가 S1F18 ONLACK으로 답한다. 0이면 받아들여졌다는 뜻이고, 2는 이미 online이라는 뜻으로 쓰인다.
  • S1F15 Request OFF-LINES1F16 OFLACK. Host가 스스로 물러나는 message다. 유지보수 전에 host 명령이 끼어들지 않게 만들 때 쓴다.

ONLACK 2를 "이미 online"으로 읽는 해석은 널리 쓰이지만 이 실행으로 검증한 것은 아니다 — unverified로 둔다.

여기서 놓치기 쉬운 게 하나 있다. S1F17이 성공해도 ON-LINE LOCAL로 갈지 ON-LINE REMOTE로 갈지는 설비가 정한다. Panel이 LOCAL이면 S1F17에 ONLACK 0을 주고 LOCAL로 올라가는 설비가 있다. Host 로그에는 "online 성공"이 찍히고, 다음 S2F41은 HCACK 2다. 그러니 online 여부의 최종 판정은 ONLACK이 아니라 실제 S2F41의 HCACK이다.

명령 하나로 여섯 줄

SECS/GEM 시뮬레이터의 HSMS listener를 상대로 방금 돌린 출력 그대로다. 합성이 아니라 socket에 오간 결과다.

npx secs-gem-host connect <host>:<port> state --report
Step Sent    Expect  Got     Ack  Time(ms)    Result  Note
------------------------------------------------------------------------
1    S1F1    S1F0    S1F0    -    1/45000     PASS    aborted before S1F13
2    S1F13   S1F14   S1F14   0    1/45000     PASS
3    S1F1    S1F2    S1F2    -    0/45000     PASS    2 items
4    S2F41   S2F42   S2F42   2    1/45000     PASS    HCACK 2 while not ON-LINE REMOTE
5    S1F17   S1F18   S1F18   0    1/45000     PASS
6    S2F41   S2F42   S2F42   0    1/45000     PASS    accepted ON-LINE REMOTE
------------------------------------------------------------------------
E30 state rules: 6/6 passed

여섯 줄이 위 표를 그대로 실행한 것이다.

1단계는 S1F13 전에 S1F1을 던진다. S1F0이 와야 PASS다. 정상 응답인 S1F2가 오면 그 설비는 통신 상태 gate를 안 걸고 있다는 뜻이고, 그건 그것대로 적어 둘 값이다.

2단계가 gate를 연다. 3단계는 같은 S1F1이 이제 S1F2로 답해지는지 확인한다 — 같은 message, 다른 상태, 다른 결과. 이 두 줄이 통신 상태가 실재한다는 증거다.

4단계가 이 글의 이유다. HCACK 2가 나와야 PASS다. 아직 online이 아닌 설비에 S2F41을 보냈는데 HCACK 0이 돌아오면, 그 설비는 제어 상태를 확인하지 않고 명령을 실행한 것이다. Operator가 panel 앞에 서 있는데 host가 wafer를 움직일 수 있다는 뜻이다.

5단계에서 S1F17을 보내고, 6단계에서 같은 S2F41이 HCACK 0으로 통과한다. Ack 열의 2 → 0이 이 실행 전체의 결론이다.

두 번 연속 돌리면 4단계가 깨진다

이 명령을 방금 돌린 설비에 그대로 다시 돌리면 이렇게 나온다.

4    S2F41   S2F42   S2F42   0    1/45000     FAIL    HCACK 0 — tool was already ON-LINE REMOTE; put it OFF-LINE and rerun
------------------------------------------------------------------------
E30 state rules: 5/6 passed

버그가 아니다. 5단계의 S1F17이 설비를 ON-LINE REMOTE로 올려 놓았고, 제어 상태는 socket을 끊어도 남는다. TCP를 다시 붙이면 통신 상태는 NOT COMMUNICATING으로 돌아가지만 제어 상태는 그대로다.

이게 현장에서 두 번째로 시간을 잡아먹는 오해다. 재접속은 제어 상태를 초기화하지 않는다. Host를 재기동했으니 설비도 처음 상태일 거라고 가정하고 짠 startup 순서는, 설비가 어제 저녁 상태 그대로 남아 있을 때 어긋난다. S1F13 다음에 S1F17을 조건 없이 한 번 보내는 편이 싸다.

거꾸로도 성립한다. 이 시뮬레이터는 S1F15를 받으면 제어 상태를 OFF-LINE으로 되돌린다. 위 실행에는 그 단계가 없으므로, 그 동작은 코드로 확인한 것이지 이 capture로 증명한 것은 아니다.

이건 core 모델이고, 실제 설비는 더 있다

여기까지가 E30의 뼈대다. 실제 설비는 이 위에 sub-state를 얹는다. HOST OFF-LINE과 EQUIPMENT OFF-LINE의 구분, 전원을 켰을 때 ATTEMPT ON-LINE으로 들어가 host와의 통신을 먼저 시도하는 동작, 그 시도를 관리하는 재시도 타이머 — 벤더 문서에 각각 다른 이름으로 적혀 있다.

시뮬레이터에는 그게 없다. 두 machine, sub-state 없음, 그게 전부다. 그래서 위 여섯 줄은 host driver가 core 규칙을 지키는지를 증명하지, 설비가 어떻게 동작할지를 증명하지 않는다. 실제 설비의 sub-state 전이는 capture로 뒷받침할 수 없으므로 여기서는 unverified다. 붙일 설비가 생기면 그때 각 sub-state에서 S2F41을 한 번씩 던져 보고 HCACK을 표로 남기는 게 맞다.

Startup 10단계 전체 — S1F13부터 S2F31까지 — 를 같은 방식으로 돌리는 쪽은 E30 startup을 명령 하나로 통과시키기에 있다.

다음에 HCACK 2를 보면

  1. 설비 화면 말고 S2F42의 HCACK 바이트를 본다. 2면 상태 문제, 1이면 그 RCMD 자체가 없는 것이다.
  2. S1F17을 보내고 ONLACK을 본다. 0이 와도 아직 아무것도 증명되지 않았다.
  3. S2F41을 다시 던진다. HCACK 0이면 끝, 또 2면 panel이 LOCAL이다. 그때는 코드가 아니라 설비 앞에 있는 사람에게 전화할 차례다.

시뮬레이터의 GEM Control 패널에 OFF-LINE / ON-LINE LOCAL / ON-LINE REMOTE 세 상태가 그대로 떠 있고, host가 보낸 S1F17·S1F15가 그 표시를 실시간으로 움직인다. 오가는 byte는 packet 목록에 그대로 남는다.

SECS/GEM 시뮬레이터는 지금 떠 있다.

npx secs-gem-host connect <host>:<port> state --report