LabHub
배우기 러닝패스 코스

냉장고가 255°C라고 우긴다 · 재시도하다 다음 일을 놓쳤다 · 실습

거짓 온도를 잡는 C 드라이버

LabHub 에서 이어서 보기

목표

두 바이트 변환과 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개

  1. 바이트를 온도로 바꾼다
  2. 255라는 숫자 뒤의 음수를 찾는다
  3. 확장 모드와 깨진 입력을 구분한다
  4. 주소와 결합 전송을 연결한다
  5. 부분 실패가 정상 표본을 덮지 못하게 한다
  6. 한 번만 복구하고 다시 읽는다
  7. 늦은 성공에도 실패라고 답한다
  8. 시계 경계와 잘못된 호출까지 방어한다