Solution (source code)

= Solution

Give the hardware to a single <device driver> process. Other processes request a conversion through <message passing> and never touch its <memory-mapped input-output> registers. The following is protocol pseudocode for <Phōs>: its operation names specify their required semantics, rather than asserting an unverified spelling of a particular 2019 C interface. The hardware actions and the request/reply design are fully specified.

Use a <FIFO queue> of accepted requests, each containing its sender and a per-call token. Bind the device's interrupt to a persistent notification addressed to the driver before any conversion is started. A notification must remain pending if it arrives before the driver next waits; this is the <lost-wakeup avoidance> requirement. The driver receives both client requests and interrupt notifications in its event loop.

``
configure sensor and connect its interrupt notification to this process
TEMP_DATARDY := 0
clear stale pending interrupt notification
enable sensor interrupt and interrupt-controller delivery
pending := empty FIFO
active := none

forever:
    if active is none and pending is not empty:
        active := remove oldest request from pending
        TEMP_DATARDY := 0
        clear stale pending interrupt notification
        TEMP_START := 1

    event := wait for a request or persistent interrupt notification

    if event is REQUEST(sender, token):
        append (sender, token) to pending

    if event is sensor interrupt and active is not none:
        if TEMP_DATARDY != 0:
            value := TEMP_TEMP
            TEMP_DATARDY := 0
            acknowledge the interrupt through the OS interrupt mechanism
            send RESULT(active.token, value) to active.sender
            active := none
``

After receiving an idle-time request, the next loop iteration starts its conversion before waiting again. While a conversion is in progress, additional requests join the queue without starting another conversion. A completed reading is copied before its ready flag is cleared, and the next request cannot start until the current result has been delivered. Spurious or stale notifications do not complete a request unless the device's ready register confirms completion.

Clearing old status and notification precedes `TEMP_START`; doing so afterwards could erase a very fast completion. The <operating system> interrupt binding and persistent notification cover completion in the interval between starting the device and entering the wait. Register accesses must use the platform's device-access semantics, including required <volatile-qualified objects in C> or ordering primitives. Exact initialization and interrupt-connection call names remain an implementation binding, not invented <Phōs> API calls. The later teaching site's named system is documented separately; it is not used as <proof> of an identical historical API.<Digital Systems course archive of the University of Oxford>[2018–2019 course record and linked teaching-site description of process/message-based device drivers]{ref}