The Fridge Insists It Is 255°C
A failed read overwrote the last sample
In one line
A driver is not a function that returns a normal temperature; it is a boundary that also decides what it will not change when it fails.
Why this was needed
The transfer function failed, yet the first byte of the buffer has changed. When old and new values mix, you get a temperature that looks plausible but never existed. Checking only the error code is a different matter from not exposing the failed result to the user. Finish conversion and validation in a working buffer, and update the sample at the very end of the success path.
In this lab, a real C compiler runs your driver, but no voltage is applied to an I2C line. The hardware abstraction layer (HAL) is provided as a bundle of function pointers. ctx points to the model's state, and transfer, now_ms, and recover use that state. You do not modify the model's internals; you communicate only through this public interface.
How it works
Pass the address as a 7-bit value from 0x48 to 0x4b. Shifting it left once more to attach the R/W bit is wrong under this HAL contract. Even when you port a real driver library, first check in the documentation whether the argument is a 7-bit address or the address byte used for transmission.
A single transfer call carries a one-byte write of the pointer 0x00 and a two-byte read together. The repeated START, the NACK on the last read, and the STOP of a real bus are left to the HAL. The checker in this course verifies the address, length, pointer, and deadline of the combined call; it does not measure electrical waveforms. The sensor datasheet and the HAL API contract are different documents.
The error policy is stated explicitly too. SENSOR_NACK is a transfer-failure status, and it does not mean the same thing as the normal NACK the controller sends on the last read byte. SENSOR_SHORT means that not all required bytes were obtained. These two statuses and the format error are not retried. Only SENSOR_BUS triggers one recover and then one more read. If the retry also fails, the function ends as is. An implementation that retries every error forever cannot fix a wrong address and only holds the caller hostage.
The model's recover resets the stuck state. You cannot claim it replaced toggling SCL nine times or power-cycling. Real recovery must be designed separately to fit the bus configuration and the part specification. Here the model is built so that the next transfer succeeds only if recovery really changes the state, which distinguishes the mistake of merely calling the function by name and ignoring the result.
Track failures by binding temperature and time together
Suppose that on entry the public sample is micro_c=25000000, observed_ms=100. The new transfer writes only the first byte, 0x1a, and returns SENSOR_SHORT. If you use the public sample's memory as the receive buffer, the old value can be corrupted before you even check the error. Receive into a two-byte working buffer inside the function, and keep the converted integer in a local variable too. The failure path returns only the error and does not touch the public sample. Only the success path moves in the new temperature and the time the completion was confirmed.
| Call situation | Returned status | Public temperature after the call | Public time after the call |
|---|---|---|---|
| Start from the previous good value | Not applicable | 25000000 | 100 |
| Read that received only one byte | SENSOR_SHORT | 25000000 | 100 |
| Next read completes normally at 26°C | SENSOR_OK | 26000000 | New completion-confirmed time |
An implementation that preserves only the temperature and changes the time to the present is also wrong, because an old measurement would look like the latest sample on screen. Conversely, an implementation that returns the old value forever after a single failure is also wrong. Preservation applies only to the failed call, and the next good call updates both fields. You must test the order in this table as the real call order to tell "preservation" apart from a "permanent cache".
Updating them together here refers to the success/failure contract of a single function call. It does not mean that the assignment of the two fields looks atomic to other threads. This model does not run concurrent readers. In a real RTOS or multithreaded program, you must also define consistency rules, such as locking or message passing, for the side that reads the sample. Do not write that creating a local buffer has also solved the data race.
Record recovery as states in order, like 전송 BUS → 복구 OK → 재전송 OK (the Korean words mean transfer, recover, and retransfer). If you write only that the last result was SENSOR_OK, you cannot tell apart an implementation that passed by accident without recovery. With 전송 BUS → 복구 NACK, the function must return the recovery error and end, and no transfer call may follow. Even in 전송 BUS → 복구 OK → 재전송 BUS, recovery is not started a second time. Only when you can say why each arrow is allowed or forbidden have you implemented the bounded retry policy.
What it looks like in the field
The official embedded engineer posting from Orion Sleep, checked on 2026-09-10, lists C/C++, hardware interfaces, and debugging and test practices under limited resources together. This course practices the driver contract and reproduction tests from that list. It does not generalize one overseas senior posting into domestic hiring demand as a whole, and this course alone cannot replace RTOS or board bring-up experience. Whether the posting is currently accepting applications must also be checked separately.
In a practical portfolio, keep both normal cases and fault-injection cases. Whether the temperature and time saved before a partial read are still the same after the error, and whether the number of recoveries is really one, are the observable evidence. If you write only "a stable driver" without that evidence, nobody can tell what you verified.
What to check next
In the quiz that follows you check the differences among address, error, and recovery, and then read the time budget reading. In steps 4–6 of the cumulative lab of the last module, you connect the normal transfer and then add sample preservation and bounded recovery. At first you handle only the normal path, so each intermediate version is not yet a production driver. Keep the previous implementation and add the contract of the current step.