Skip to content

Commit 2b4adcd

Browse files
committed
doc: dts: update howtos with new API
Document the use of DEVICE_DT_GET() to fetch device pointers at compile time, and update the documentation on defining device instances to use the devicetree macros. Signed-off-by: Peter Bigot <[email protected]>
1 parent 86e98f0 commit 2b4adcd

File tree

1 file changed

+42
-24
lines changed

1 file changed

+42
-24
lines changed

doc/guides/dts/howtos.rst

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,13 @@ works best for your requirements. Here are some examples:
8888
/* Option 4: by path */
8989
#define MY_SERIAL DT_PATH(soc, serial_40002000)
9090
91-
Once you have a node identifier, get the ``struct device`` by combining
91+
Once you have a node identifier there are two ways to proceed. The
92+
classic way is to get the ``struct device`` by combining
9293
:c:func:`DT_LABEL` with :c:func:`device_get_binding`:
9394

9495
.. code-block:: c
9596
96-
struct device *uart_dev = device_get_binding(DT_LABEL(MY_SERIAL));
97+
const struct device *uart_dev = device_get_binding(DT_LABEL(MY_SERIAL));
9798
9899
You can then use ``uart_dev`` with :ref:`uart_api` API functions like
99100
:c:func:`uart_configure`. Similar code will work for other device types; just
@@ -103,6 +104,23 @@ There's no need to override the ``label`` property to something else: just make
103104
a node identifier and pass it to ``DT_LABEL`` to get the right string to pass
104105
to ``device_get_binding()``.
105106

107+
The second way to get a device is to use :c:func:`DEVICE_DT_GET`:
108+
109+
.. code-block:: c
110+
111+
const struct device *uart_dev = DEVICE_DT_GET(MY_SERIAL);
112+
113+
if (!device_is_ready(uart_dev)) {
114+
/* Not ready, do not use */
115+
return -ENODEV;
116+
}
117+
118+
This idiom fetches the device pointer at build-time, which is useful when you
119+
want to store the device pointer as configuration data. But because the
120+
device may not be initialized, or may have failed to initialize, you must
121+
verify that the device is ready to be used before passing it to any API
122+
functions. (This check is done for you by :c:func:`device_get_binding`.)
123+
106124
If you're having trouble, see :ref:`dt-trouble`. The first thing to check is
107125
that the node has ``status = "okay"``, like this:
108126

@@ -111,7 +129,7 @@ that the node has ``status = "okay"``, like this:
111129
#define MY_SERIAL DT_NODELABEL(my_serial)
112130
113131
#if DT_NODE_HAS_STATUS(MY_SERIAL, okay)
114-
struct device *uart_dev = device_get_binding(DT_LABEL(MY_SERIAL));
132+
const struct device *uart_dev = device_get_binding(DT_LABEL(MY_SERIAL));
115133
#else
116134
#error "Node is disabled"
117135
#endif
@@ -432,17 +450,17 @@ using instance numbers. Do this after defining ``my_api_funcs``.
432450
/* initialize ROM values as needed. */ \
433451
}; \
434452
DEVICE_DT_INST_DEFINE(inst, \
435-
my_dev_init_function, \
436-
device_pm_control_nop, \
437-
&my_data_##inst, \
438-
&my_cfg_##inst, \
439-
MY_DEV_INIT_LEVEL, MY_DEV_INIT_PRIORITY, \
440-
&my_api_funcs);
441-
442-
Notice the use of APIs like :c:func:`DT_INST_LABEL` and :c:func:`DT_INST_PROP`
443-
to access devicetree node data. These APIs retrieve data from the devicetree
444-
for instance number ``inst`` of the node with compatible determined by
445-
``DT_DRV_COMPAT``.
453+
my_dev_init_function, \
454+
device_pm_control_nop, \
455+
&my_data_##inst, \
456+
&my_cfg_##inst, \
457+
MY_DEV_INIT_LEVEL, MY_DEV_INIT_PRIORITY, \
458+
&my_api_funcs);
459+
460+
Notice the use of APIs like :c:func:`DT_INST_PROP` and
461+
:c:func:`DEVICE_DT_INST_DEFINE` to access devicetree node data. These
462+
APIs retrieve data from the devicetree for instance number ``inst`` of
463+
the node with compatible determined by ``DT_DRV_COMPAT``.
446464

447465
Finally, pass the instantiation macro to :c:func:`DT_INST_FOREACH_STATUS_OKAY`:
448466

@@ -508,16 +526,16 @@ devicetree to operate on specific device nodes:
508526
.freq = DT_PROP(MYDEV(idx), clock_frequency), \
509527
}; \
510528
static const struct my_dev_cfg my_cfg_##idx = { /* ... */ }; \
511-
DEVICE_DT_INST_DEFINE(idx, \
512-
my_dev_init_function, \
513-
device_pm_control_nop, \
514-
&my_data_##idx, \
515-
&my_cfg_##idx, \
516-
MY_DEV_INIT_LEVEL, MY_DEV_INIT_PRIORITY, \
517-
&my_api_funcs)
518-
519-
Notice the use of APIs like :c:func:`DT_LABEL` and :c:func:`DT_PROP` to access
520-
devicetree node data.
529+
DEVICE_DT_DEFINE(MYDEV(idx), \
530+
my_dev_init_function, \
531+
device_pm_control_nop, \
532+
&my_data_##idx, \
533+
&my_cfg_##idx, \
534+
MY_DEV_INIT_LEVEL, MY_DEV_INIT_PRIORITY, \
535+
&my_api_funcs)
536+
537+
Notice the use of APIs like :c:func:`DT_PROP` and
538+
:c:func:`DEVICE_DT_DEFINE` to access devicetree node data.
521539

522540
Finally, manually detect each enabled devicetree node and use
523541
``CREATE_MY_DEVICE`` to instantiate each ``struct device``:

0 commit comments

Comments
 (0)