콘텐츠로 이동
무료 평가 시작

SECS-I

SECS-I(SEMI E4)는 RS-232 직렬 회선으로 SECS-II 메시지를 보내는 방법입니다. HSMS보다 오래된 방식이지만 기존 장비에는 아직 많이 남아 있습니다. 회선은 두 장치를 일대일로 잇습니다. 메시지는 블록(block)으로 나뉘어 하나씩 전달되고, 블록마다 확인 응답을 받습니다.

블록 하나는 길이 바이트, 10바이트 헤더, 최대 244바이트 데이터, 2바이트 체크섬(checksum)으로 이뤄집니다(SEMI E4, 블록 형식).

+--------+-------------------------------+------------------+----------+
| length | header (10 bytes) | data (0..244) | checksum |
| 1 byte | | | 2 bytes |
+--------+-------------------------------+------------------+----------+
header byte 1 2 3 4 5 6 7..10
R-bit + device ID W-bit + function E-bit + block no. system bytes
device ID (low 8) stream block no. (low 8)
(high 7) (high 7)
  • 길이 바이트는 헤더와 데이터의 바이트 수입니다. 10–254 범위입니다.
  • R 비트(reverse bit)는 메시지 방향입니다. 1이면 장비에서 호스트로, 0이면 호스트에서 장비로 가는 메시지입니다.
  • E 비트(end bit)는 메시지의 마지막 블록에 켜집니다.
  • 블록 번호(block number)는 여러 블록으로 나뉜 메시지에서 1부터 차례로 붙습니다.
  • 체크섬은 헤더와 데이터 바이트를 모두 더한 16비트 값입니다.

244바이트보다 큰 메시지는 여러 블록으로 나뉩니다(multi-block message). 받는 쪽은 블록을 순서대로 모아 하나의 메시지로 다시 조립합니다.

SECS-I는 네 개의 제어 문자로 회선 사용권을 주고받습니다.

문자 값 의미
ENQ 05h 보낼 블록이 있다는 요청
EOT 04h 받을 준비가 됐다는 응답
ACK 06h 블록을 정상적으로 받음
NAK 15h 블록에 오류가 있음

블록 하나는 다음 순서로 전달됩니다.

Sender Receiver
| ------------ ENQ --------------> |
| <----------- EOT --------------- | within T2
| ---- length, header, data, ----> | characters within T1
| checksum |
| <----------- ACK (or NAK) ------ | within T2
  • 송신자는 NAK를 받거나 T2 안에 응답이 없으면 같은 블록을 다시 보냅니다. 재시도 한도(retry limit, RTY)를 넘으면 전송이 실패합니다.
  • 양쪽이 동시에 ENQ를 보내면 경합(contention)입니다. 마스터(master) 쪽은 계속 보내고, 슬레이브(slave) 쪽은 양보하고 먼저 받습니다. E4의 배치는 장비가 마스터, 호스트가 슬레이브입니다.
타이머 이름 의미
T1 문자 간 타임아웃(intercharacter timeout) 블록을 받는 동안 문자 사이의 최대 간격
T2 프로토콜 타임아웃(protocol timeout) ENQ 뒤 EOT, 블록 뒤 ACK/NAK를 기다리는 시간
T3 응답 타임아웃(reply timeout) W 비트 메시지의 응답 메시지를 기다리는 시간
T4 블록 간 타임아웃(interblock timeout) 여러 블록 메시지에서 다음 블록을 기다리는 시간

PDComm의 SECS-I 끝점은 직렬 포트를 직접 열지 않습니다. 애플리케이션이 읽기(read)와 쓰기(write) 콜백(callback)을 제공하고, 끝점은 그 콜백으로 바이트를 주고받습니다. 그래서 같은 코드로 실제 COM 포트, 가상 직렬 포트, 메모리 안의 시험 회선을 모두 다룰 수 있습니다.

  • 콜백은 막히지 않아야(non-blocking) 합니다. 읽을 데이터가 없으면 PDCOMM_SECS1_IO_WOULD_BLOCK을 돌려줍니다.
  • 콜백은 poll 안에서만 동기적으로 호출됩니다. 끝점의 모든 함수는 끝점을 만든 스레드에서 호출해야 하며, 콜백 안에서 끝점 함수를 다시 호출하면 PDCOMM_INVALID_STATE가 됩니다.
  • 시간은 애플리케이션이 poll에 넘기는 틱(tick) 값입니다. 타이머 옵션도 같은 틱 단위입니다. .NET 작업자는 밀리초를 틱으로 씁니다.
  • 결과는 이벤트로 나옵니다. 메시지 수신(INBOUND), 송신 완료(OUTBOUND_COMPLETE), 송신 실패(OUTBOUND_FAILED), 회선 오류(FAULT)입니다.

PdcommSecs1Options의 타이머 필드는 E4 타이머에 다음처럼 대응합니다.

PDComm 필드 E4 설명
priority 마스터/슬레이브 경합 때 누가 양보할지 정합니다(PDCOMM_SECS1_MASTER, PDCOMM_SECS1_SLAVE).
retry_limit RTY 블록 재전송 한도
grant_wait_ticks T2 보낸 ENQ에 대한 EOT를 기다리는 시간
ack_wait_ticks T2 보낸 블록에 대한 ACK/NAK, 보낸 EOT 뒤 길이 바이트를 기다리는 시간
inbound_progress_ticks T1 블록을 받는 동안 문자 사이 간격
inter_block_ticks T4 여러 블록 메시지에서 다음 블록까지 간격

SECS-I 끝점은 블록 전송을 처리하고 메시지를 전달합니다. 요청과 응답은 애플리케이션이 시스템 바이트로 짝짓고, W 비트 메시지의 응답 타임아웃(T3)도 애플리케이션이 잽니다.

메시지를 보낼 때는 장치 ID, 방향(PDCOMM_SECS1_TO_HOST 또는 PDCOMM_SECS1_TO_EQUIPMENT), 스트림, 펑션, W 비트, 시스템 바이트, 본문을 지정해 pdcomm_secs1_submit를 호출합니다. 본문이 옵션의 본문 크기 한도(max_outbound_body_bytes, max_body_bytes)나 블록 수 한도(max_outbound_blocks, max_blocks)를 넘으면 PDCOMM_LIMIT_EXCEEDED가 돌아옵니다. E4는 ENQ/EOT/ACK/NAK가 아닌 바이트를 회선 제어에서 무시하도록 정합니다. PDComm은 이런 바이트를 세고 선택형 진단 로그에 남깁니다.

  • C: pdcomm_secs1_create로 끝점을 만들고 pdcomm_secs1_poll로 진행시킵니다. 만들기와 시작에는 secs-gem 모듈 라이선스가 필요합니다(라이선스 설치와 확인).
  • C++: Secs1Endpoint는 콜백을 타입 안전하게 감싸고, C 함수 포인터 밖으로 예외가 새지 않게 막습니다.
  • .NET: Secs1Worker는 전용 스레드에서 끝점을 만들고 poll을 반복합니다. StartAsync, SubmitAsync, ReadEventsAsync, StopAsync, ResetAsync, DisposeAsync를 제공합니다. 작업자는 직렬 포트를 열거나 닫지 않습니다. 콜백은 빨리 반환해야 하고 작업자 메서드를 다시 호출하면 안 됩니다.

실제 직렬 장비가 없어도 SECS-I를 시험할 수 있습니다.

  • 메모리 가상 쌍(virtual pair): 시뮬레이터는 호스트 쪽(슬레이브)과 장비 쪽(마스터) SECS-I 끝점을 메모리 안의 회선으로 연결합니다. GUI 시뮬레이터의 SECS-I 작업 공간, MCP 서버, headless 시뮬레이터의 secs1-virtual-pair 시나리오가 이 쌍을 씁니다. 블록 분할, 재조립, 회선 오류 주입(fault injection)을 직렬 포트 없이 확인합니다.
  • 가상 직렬 포트: 실제 COM 포트처럼 동작하는 포트 쌍이 필요하면 PDComm 도구의 가상 직렬 포트를 씁니다. 애플리케이션은 일반 직렬 포트처럼 열고, SECS-I 끝점의 콜백에서 그 포트를 읽고 씁니다.

시뮬레이터 사용법은 SECS/GEM 가이드에서 설명합니다.