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

S2F23에 S2F0이 돌아왔다 — 기능 미구현인지 통신 게이트인지 바이트로는 못 가린다

같은 세션에서 S2F23이 두 번 S2F0으로 돌아온 캡처. 원인은 E30 통신 게이트와 기능 미구현으로 서로 다른데 응답 바이트는 SystemBytes만 빼고 같다.

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

Host 드라이버에 trace 수집을 붙이려고 S2F23(Trace Initialize Send)을 던졌다. 돌아온 건 S2F24가 아니라 S2F0이다. 본문 없는 10 byte. 문제는 그 전에, S1F13도 보내기 전에 실수로 던졌던 S2F23에 돌아온 응답과 이게 SystemBytes만 빼고 똑같다는 것이다. 설비가 그 기능을 아예 구현하지 않은 건지, 아니면 아직 E30 통신이 열리지 않은 건지 — 응답 안에는 그걸 가릴 필드가 없다.

S2F23에 S2F0이 돌아왔을 때, 같은 세션에서 S1F14의 COMMACK 0이 이미 끝났는지로 원인을 E30 통신 게이트와 기능 미구현 둘로 가르는 판단 분기 S2F23 → S2F0 본문 없음, 상태 코드 없음 S1F14의 COMMACK 0, 받았나 아니오 E30 통신 게이트 S1F13 먼저 예 기능 미구현 Trace Data Collection 없음

아래 frame은 전부 SECS/GEM 시뮬레이터의 passive listener(127.0.0.1:5501)에 python socket client를 직접 붙여서 한 세션 안에서 주고받은 것이다. 원본 export는 content/demos/s2f23-trace-capability-probe-sxf0.json에 그대로 넣어뒀다.

먼저 Select, 그 다음 아무것도 안 열린 상태

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

SType 1에 SType 2, Select Status는 byte 3의 00이다. E37대로 control message에는 SessionID FF FF를 썼는데 돌아온 Select.rsp는 00 0B, 즉 11이다. 그건 답장의 SessionID가 보낸 값이 아닐 수 있다에서 따로 다뤘으니 여기서는 넘어간다. 여기서 중요한 건 HSMS가 SELECTED라는 것뿐이다.

같은 S2F23, 두 번

E5의 S2F23 본문은 L[5]{ TRID, DSPER, TOTSMP, REPGSZ, L[n]{SVID} }다. TRID 1, DSPER은 ASCII "000100", TOTSMP 60, REPGSZ 1, SVID 두 개를 담았다.

TX S2F23 W   00 00 00 34 00 01 82 17 00 00 00 00 00 02
             01 05 B1 04 00 00 00 01 41 06 30 30 30 31 30 30
             B1 04 00 00 00 3C B1 04 00 00 00 01
             01 02 B1 04 00 00 00 65 B1 04 00 00 00 66
RX reply     00 00 00 0A 00 01 02 00 00 00 00 00 00 02
BytesFieldValue
00 00 00 0ALength10 — 헤더만, body 없음
00 01SessionID1 — 요청 값 그대로
02헤더 바이트 2W-bit 0, Stream 2
00헤더 바이트 3Function 0
00 00PType, SType0, 0 — 데이터 message
00 00 00 02SystemBytes2 — 요청 값 그대로

이 시점에 설비는 E30 communication state model의 NOT COMMUNICATING이었다. 그래서 이 S2F0은 통신 게이트다. 그 메커니즘은 SELECTED인데 S1F3이 S1F0으로 돌아오는 이유에서 바이트까지 다뤘다.

이제 같은 소켓에서 S1F13을 통과시킨다.

TX S1F13 W   00 00 00 0C 00 01 81 0D 00 00 00 00 00 03  01 00
RX S1F14     00 00 00 37 00 01 01 0E 00 00 00 00 00 03
             01 02 21 01 00
             01 02 41 15 56 58 2D 39 30 30 30 20 50 6C 61 73 6D 61 20 45 74 63 68 65 72
             41 0D 53 45 43 53 47 45 4D 2D 31 2E 34 2E 31

본문은 L[2]{ B 0, L[2]{A "VX-9000 Plasma Etcher", A "SECSGEM-1.4.1"} }다. 앞의 21 01 00이 COMMACK 0 — 수락이다. 이제 COMMUNICATING이다.

그리고 완전히 같은 S2F23 바이트를 다시 던진다. SystemBytes만 2에서 4로 바뀐다.

TX S2F23 W   00 00 00 34 00 01 82 17 00 00 00 00 00 04
             01 05 B1 04 00 00 00 01 41 06 30 30 30 31 30 30
             B1 04 00 00 00 3C B1 04 00 00 00 01
             01 02 B1 04 00 00 00 65 B1 04 00 00 00 66
RX reply     00 00 00 0A 00 01 02 00 00 00 00 00 00 04

또 S2F0이다. 두 응답을 나란히 놓으면 이렇다.

00 00 00 0A 00 01 02 00 00 00 00 00 00 02   ← 게이트가 닫혀 있어서
00 00 00 0A 00 01 02 00 00 00 00 00 00 04   ← 기능이 없어서

14 byte 중 13 byte가 같다. 다른 건 SystemBytes뿐이고, 그건 내가 보낸 값이다. 설비가 보내준 정보 중에 원인을 가리는 건 하나도 없다.

통신이 열려 있다는 걸 같은 세션에서 확인해 두는 게 중요하다. 이 설비가 구현한 S2F33을 같은 소켓에서 던져보면 제대로 답한다.

TX S2F33 W   00 00 00 14 00 01 82 21 00 00 00 00 00 05  01 02 B1 04 00 00 00 00 01 00
RX S2F34     00 00 00 0D 00 01 02 22 00 00 00 00 00 05  21 01 00

헤더 바이트 3이 22, Function 34다. 본문 21 01 00은 Binary 0, DRACK 0 — 수락. 같은 세션, 같은 SessionID, 같은 상태에서 한 function은 답하고 한 function은 abort한다. 그래서 두 번째 S2F0은 세션 문제가 아니다. 그 function을 이 설비가 구현하지 않은 것이다.

S2F0에는 이유가 들어갈 자리가 없다

SEMI E5에서 SxF0은 abort transaction이다. 요청이 쓴 stream을 그대로 쓰고 function만 0, W-bit는 꺼지고 본문은 비운다. 필드가 없으니 상태 코드도, ERRCODE도 없다. S2F42의 HCACK이나 S2F34의 DRACK처럼 "왜"를 담는 자리가 애초에 없는 모양이다.

E5는 구현하지 않은 function에 대해 S9F5(Unrecognized Function Type)를 보내는 길도 정의한다. 어느 쪽을 보낼지는 설비 구현에 달렸고, S9이 온다고 기대하고 host를 짜면 안 된다는 건 설비가 S9를 보내줄 거라 기대하면 안 되는 이유에 정리해뒀다. 위 캡처의 설비는 S9F5가 아니라 S2F0을 보냈다. 다른 설비가 어느 쪽을 보낼지는 나도 확인하지 못했다.

Trace Data Collection은 GEM의 선택 사항이다

여기서 S2F23을 고른 건 우연이 아니다. SEMI E30은 trace data collection을 모든 설비가 반드시 갖춰야 하는 기능으로 두지 않는다. 추가 기능이다. S2F23/S2F24로 trace를 걸고 S6F1/S6F2로 sample이 올라온다. 그러니 "GEM 설비니까 trace가 있다"는 전제는 틀릴 수 있고, 틀렸을 때 설비가 알려주는 방법이 위의 10 byte다.

MES 쪽 요구가 "1초 간격 온도 추이"로 내려오면 trace로 받고 싶어진다. 나는 그걸 설계에 넣기 전에 S2F23 하나 던져보는 쪽이다. 없으면 S6F11을 짧은 주기로 돌리는 타협을 하게 되는데, 그 선택의 대가는 GEM link는 초록불인데 MES가 run을 못 맞추는 이유에 적어뒀다. 둘 중 뭘 할지는 설비가 뭘 구현했는지 확인한 다음 정할 일이다.

Host 드라이버에 넣을 것

  • 선택 기능은 기동 시 한 번 찔러보고 결과를 저장한다. S1F13/S1F14가 COMMACK 0으로 끝난 직후, 쓸 예정인 선택 기능의 primary를 하나씩 보낸다. SxF0이 오면 "미지원"으로 기록하고 다시 안 보낸다. 재시도할 일이 아니다.
  • 게이트가 열린 뒤에 찔러본다. S1F14 전에 보낸 probe는 전부 S2F0이 돌아와서 전 기능이 미지원이라는 결론이 나온다. 순서를 틀리면 그 결론을 그대로 믿게 된다.
  • 같은 세션에 대조군을 하나 둔다. S1F3이나 S2F13처럼 E30이 필수로 요구하는 primary 하나를 probe 목록 안에 같이 넣는다. 그게 답하는데 probe만 abort면 통신이 아니라 기능 문제다. 그게 같이 abort면 세션 문제다.
  • abort를 로그할 때 요청 헤더 10 byte를 같이 남긴다. S2F0 안에는 SystemBytes뿐이다. 어떤 요청이 abort됐는지는 host가 자기 기록으로만 복원할 수 있다.
  • "SxF0 실패"와 "ACK 코드 non-zero 실패"를 같은 에러로 뭉치지 않는다. 앞은 그 function이 지금 이 설비에 없다는 뜻이고, 뒤는 있는데 거절했다는 뜻이다. 대응이 완전히 다르다.

설비 없이 이 교환을 직접 재현해보려면 SECS/GEM 시뮬레이터의 passive listener에 socket client를 붙이면 된다. S1F13 전후로 같은 primary를 두 번 던지는 것만으로 위 두 S2F0이 그대로 나온다.