냉장고가 255°C라고 우긴다 · 재시도하다 다음 일을 놓쳤다 · 실습
거짓 온도를 잡는 C 드라이버
목표
두 바이트 변환과 HAL 오류·기한 계약을 C로 구현합니다. 실제 C 프로그램을 실행하지만 실물 MCU·I2C 파형·전압 계측은 하지 않습니다.
왜 중요한가
숫자가 출력되어도 부호나 단위가 틀리면 정상 측정이 아닙니다. 부분 읽기는 마지막 정상 값을 오염시킬 수 있고 무한 재시도는 다음 작업을 막습니다. 오류·값·시간을 함께 검증해 재현 가능한 드라이버 시험을 만듭니다. C 함수·포인터·구조체와 셸 기초가 필요합니다.
단계
1. 바이트를 온도로 바꾼다 — sensor_decode(hi, lo, out)를 구현하세요. 정상 모드의 유효 양수·0 입력을 상위 바이트 먼저 결합하고 하위 4비트를 제외한 카운트에 62,500을 곱해 int32_t 마이크로 섭씨로 저장합니다. 성공은 SENSOR_OK입니다. 0~2047 카운트 전체와 분수 값이 대상입니다.
2. 255라는 숫자 뒤의 음수를 찾는다 — 정상 모드의 음수를 포함한 4096개 카운트 전체를 지원하세요. 12비트 2의 보수 부호를 복원하며 -0.0625°C는 -62,500으로 저장합니다. 이전 양수 변환은 유지하세요.
3. 확장 모드와 깨진 입력을 구분한다 — lo의 bit 0이 1이면 확장 모드: 13비트 카운트, 하위 3비트 제외, 예약 bit 2·1은 0이어야 합니다. 정상 모드는 lo의 하위 4비트가 0이어야 합니다. 예약 비트 위반은 SENSOR_FORMAT, NULL 출력은 SENSOR_ARG입니다. 오류 때 *out을 바꾸지 마세요. 두 모드 전체 65,536 바이트 조합을 검사합니다.
4. 주소와 결합 전송을 연결한다 — sensor_read(bus, address7, budget_ms, out)에 정상 경로를 구현하세요. now_ms(ctx)로 시작과 완료 시각을 읽고, transfer(ctx,address7,&pointer,1,bytes,2,start+budget_ms)를 한 번 호출합니다. pointer는 0x00, address7은 0x48~0x4b 그대로입니다. 변환 결과와 완료 확인 시각을 out->micro_c·observed_ms에 저장하고 SENSOR_OK를 반환합니다. 정상·확장 모드 모두 지원합니다.
5. 부분 실패가 정상 표본을 덮지 못하게 한다 — NACK·SHORT·FORMAT 오류를 그대로 반환하고 재전송·복구하지 마세요. 오류 때 out의 두 필드는 진입 시 값 그대로 유지합니다. transfer 실패 시 bytes 일부가 바뀔 수 있으므로 별도 작업 버퍼와 지역 변환 값을 사용하세요.
6. 한 번만 복구하고 다시 읽는다 — 첫 전송이 SENSOR_BUS일 때만 recover(ctx,deadline)를 한 번 호출하세요. 복구가 성공하면 같은 주소·포인터·길이·deadline으로 전송을 한 번 재시도합니다. 복구 오류는 그대로 반환하고, 두 번째 전송의 BUS에는 더 복구하지 않습니다. 다른 오류와 출력 보존 계약을 유지하세요.
7. 늦은 성공에도 실패라고 답한다 — 전송·복구·재시도가 시작 시 구한 단일 deadline을 공유하게 하세요. 각 transfer·recover 직후 uint32_t 경과 시간이 budget_ms 이상이면 SENSOR_TIMEOUT입니다. HAL이 늦은 성공을 반환해도 표본을 갱신하지 않습니다. 예산은 이번 단계에서 유효하며, 정확히 기한에 도착해도 시간 초과입니다.
8. 시계 경계와 잘못된 호출까지 방어한다 — I/O 전에 bus·out·transfer·now_ms·recover가 NULL인지, 주소가 0x48~0x4b인지, 예산이 1~INT32_MAX인지 검사해 잘못되면 SENSOR_ARG를 반환하세요. ctx 자체는 NULL일 수 있습니다. 인자 오류에도 출력과 I/O 상태는 유지합니다. uint32_t 시계가 한 번 래핑하는 전송과 정상→부분 실패→정상 연속 호출까지 앞 단계 계약을 유지하세요. 완료 확인 시각은 ADC 측정 시각이 아닙니다.
참고
모든 구현은 /root/sensor-driver/sensor.c 하나에 저장합니다. mkdir -p /root/sensor-driver로 폴더를 만들고 예시 틀을 처음 한 번만 저장하세요. 제공 헤더는 /opt/lab/sensor_driver/sensor.h입니다. cat 명령으로 함수와 상태 코드를 확인하세요. 자체 컴파일 확인: cc -std=c11 -Wall -Wextra -Werror -Wconversion -pedantic -I /opt/lab/sensor_driver -c /root/sensor-driver/sensor.c -o /tmp/sensor.o. main 함수는 검사기가 제공합니다. 표준 출력에 디버그 로그를 추가하지 마세요. 추가 라이브러리 설치나 인터넷은 필요 없습니다. 제출 파일은 64 KiB 이하의 일반 C 파일이며, 채점의 컴파일 3초·실행 2초 제한은 학습 시간 제한과 다릅니다. 검사기는 앞 단계도 다시 확인합니다. 중간 단계 구현은 아직 전체 계약을 만족하지 않습니다. 필요하면 세션의 +시간으로 연장하고 세션 종료 전에 소스와 기록을 따로 보관하세요. 종료 후 파일은 유지되지 않습니다.
단계 8개
- 바이트를 온도로 바꾼다
- 255라는 숫자 뒤의 음수를 찾는다
- 확장 모드와 깨진 입력을 구분한다
- 주소와 결합 전송을 연결한다
- 부분 실패가 정상 표본을 덮지 못하게 한다
- 한 번만 복구하고 다시 읽는다
- 늦은 성공에도 실패라고 답한다
- 시계 경계와 잘못된 호출까지 방어한다