I2C 슬레이브가 SCL을 Low로 붙잡아 마스터를 기다리게 하는 기능 (clock stretching).
어떻게 가능한가
- SCL도 오픈드레인이다
- 마스터가 High로 놓아도, 슬레이브가 Low로 당기면 Low가 유지된다
- 마스터는 SCL이 실제로 High가 됐는지 확인하고 진행한다
- (안 올라갔으면 기다린다)
"클럭은 마스터가 만든다"는 원칙의 유일한 예외다.
언제 쓰나
- ① EEPROM 쓰기 — 내부 쓰기에 수 ms가 걸린다
- ② ADC 변환 대기 — 값이 준비될 때까지
- ③ 슬레이브 MCU가 소프트웨어로 I2C를 처리 — 인터럽트 응답 시간이 필요
- ④ 센서가 측정 중
느린 슬레이브가 마스터에게 "잠깐만"이라고 말하는 유일한 수단이다. 이것이 없으면 마스터는 무작정 보내고, 슬레이브는 놓친다.
흐름
마스터: 데이터 8비트 전송 → ACK 클럭을 만들려고 SCL을 High로 슬레이브: 아직 처리 중 → SCL을 Low로 붙잡음 마스터: SCL이 High가 안 됐네 → 대기 슬레이브: 처리 완료 → SCL 해제 마스터: SCL이 High가 됨 → 진행
문제 ① — 마스터가 지원하지 않을 수 있다
소프트웨어 I2C(비트뱅잉)로 구현할 때 "SCL을 High로 만들었으니 됐겠지" 하고 넘어가면
- 슬레이브가 아직 준비 안 됐는데 진행 → 데이터 깨짐
올바른 비트뱅잉 구현
SCL_RELEASE(); // 오픈드레인 해제
uint32_t timeout = 10000;
while (!READ_SCL() && --timeout) { } // 실제로 High가 될 때까지 대기
if (!timeout) { /* 스트레칭 타임아웃 → 버스 오류 */ }
"SCL을 놓았으면 실제로 올라갔는지 읽어서 확인" 하는 것이 핵심이다.
문제 ② — 하드웨어 버그로 유명한 경우들
일부 MCU의 I2C 하드웨어가 클럭 스트레칭을 제대로 처리하지 못한다 (특정 실리콘 리비전의 에라타로 공개된 사례가 여럿 있다)
증상: 스트레칭하는 슬레이브와 통신하면 간헐적으로 버스가 멈춘다
칩 에라타 문서를 확인하는 습관이 필요하다. "이 조합에서만 안 된다"는 문제는 대개 에라타에 이미 나와 있다.
문제 ③ — 무한 대기
- 슬레이브가 고장나 SCL을 영영 놓지 않으면
- 마스터가 영원히 멈춘다
반드시 타임아웃을 둔다.
HAL_I2C_Master_Transmit(&hi2c, addr, data, len, 100); // 100ms 타임아웃
타임아웃 후에는 버스 복구 절차(SCL 9회 토글 + STOP)를 수행하고 필요하면 I2C 주변장치를 리셋한다.
문제 ④ — SMBus는 제한한다
SMBus 규격: 클럭 Low 유지 시간 최대 35ms 초과하면 타임아웃 오류로 처리
I2C에는 시간 제한이 없어 이론상 무한히 늘릴 수 있는데, SMBus는 시스템이 멈추지 않도록 상한을 정했다. 배터리·전원 관리처럼 멈추면 안 되는 용도이기 때문이다.
설계 관점 — 슬레이브를 만든다면
-
가능하면 스트레칭을 쓰지 않는 설계가 좋다
-
대안
-
① 상태 레지스터를 두고 마스터가 폴링하게 한다
- "준비됐나요?" → "아직" → 나중에 다시
-
② 인터럽트 핀으로 "준비 완료"를 알린다 ← 가장 깔끔
-
③ 데이터를 미리 준비해 두고 요청 즉시 응답
②의 방식이 널리 쓰인다 — 대부분의 센서에 INT 핀이 있는 이유다. 버스를 붙잡지 않으면서 다른 장치와의 통신도 방해하지 않는다.
확인 방법
로직 애널라이저로 SCL을 보면 마스터가 만드는 규칙적인 클럭 사이에 비정상적으로 긴 Low 구간이 보인다 → 스트레칭
그 구간의 길이가 슬레이브의 처리 시간이다. 너무 길면 전체 통신 성능에 영향을 주므로 설계를 재검토한다.