Zephyr OS Device References: Separate Missing Driver Objects from Failed Initialization
A Zephyr device problem can occur before the firmware links or after the firmware starts. An undefined device reference and a false readiness check belong to different diagnostic stages. Identify the stage first, then collect the evidence that can explain it instead of changing hardware wiring and configuration indiscriminately.
This guide uses Zephyr 4.4.0 source and documentation. It proposes a diagnostic workflow for an application that expects a driver-backed device. It does not report a tested board failure, and it does not assume every devicetree node should create a device object.

Start with the exact failure stage
Save the first meaningful diagnostic and the build revision. A preprocessing error involving a property macro, a linker error involving a device symbol and an application message reporting an unready device are not interchangeable symptoms.
If linking failed, the new application never reached a runtime readiness check. Investigating the driver's initialization return value cannot explain why that binary failed to link. Conversely, when an application is running and reports an unready device, adding a declaration to satisfy the linker is no longer the relevant question.
Keep the board target, effective configuration and generated devicetree from the failing build together. Mixing the log from one configuration with generated files from another can produce a convincing but incorrect explanation.
Map the reference back to the intended node
The application may select a node through a label, alias, chosen property or another devicetree expression. Confirm which node that expression selects in the generated build, rather than relying on the name of an overlay file.
The version-pinned Zephyr 4.4.0 devicetree HOWTO identifies the generated DTS and header as useful build outputs. Use them to connect an application reference to the node and binding the build actually processed.
For an ordinal-based linker diagnostic, consult the generated node information for that same build. Do not treat the numeric ordinal as a permanent board identifier. Describe the resolved node path in an investigation record so another engineer can understand it without reconstructing an unrelated build's numbering.
Investigate a missing device object at build time
A node being present in devicetree does not by itself prove that a driver object was compiled and instantiated. Review the node status, compatible binding, driver implementation and effective Kconfig selection as a connected path.
The Zephyr 4.4.0 device header defines device construction and reference macros. The relevant question is whether the selected driver creates the object that the application references, not whether an arbitrary external declaration can silence part of the diagnostic.
Inspect the driver's build integration and configuration dependencies. A requested option can remain disabled if its prerequisites are unmet. A custom driver can also be present in the repository without being included by the active build. Collect the final configuration and relevant compilation evidence before deciding which layer is absent.
Avoid manufacturing a dummy device object simply to make the link succeed. That can hide the integration defect while leaving an unusable API or uninitialized state behind. Fix the actual driver selection or correct an application reference that points to the wrong node.
Investigate readiness only after an object exists
Once the firmware links and runs, evaluate readiness before using the device API. A reference obtained at build time does not establish that initialization completed successfully.
An unready device calls for lifecycle evidence: whether initialization was attempted, whether it failed and whether initialization was intentionally deferred. Driver logs or a debugger can help locate the failing dependency or return path. State which observation was actually made rather than declaring every false result a wiring fault.
A hypothetical sensor driver might have a valid device object but fail initialization because its bus dependency is unavailable. Another configuration might deliberately postpone initialization. Both can appear unready to application code, but their next steps differ. The first needs the dependency failure investigated; the second needs the intended startup owner and timing checked.
Keep driver readiness separate from product function
A successful readiness check is a prerequisite for normal device use, not a complete acceptance test for the product. It does not prove that the connected peripheral is the expected variant, that every optional feature works or that the application's timing requirement is met.
After fixing the integration or initialization problem, perform a bounded functional check appropriate to the driver. For a hypothetical sensor, that might include a documented identity check and one valid measurement under known conditions. Do not substitute an arbitrary register access for the driver's supported API unless the investigation explicitly requires and understands it.
This separation makes the diagnosis useful: build-time evidence establishes the object, startup evidence establishes readiness and a functional check establishes the behavior actually required by the application.
Record the causal path, not only the final setting
When the problem is resolved, retain the node path, selected driver, relevant configuration change and the observation that confirmed the corrected stage. If a configuration dependency caused the missing object, record that dependency rather than merely saying that enabling more drivers fixed the build.
If initialization failed, retain the original error and the reason the later attempt succeeded. If the device was deferred, identify the component responsible for starting it. These details prevent a future engineer from undoing the fix because its purpose is unclear.
The practical sequence is short: classify the failure stage, resolve the intended node, prove object creation, inspect initialization and then test the required function. Each step answers a different question. Following that order reduces speculative edits and produces evidence another maintainer can reproduce.