1.. _dt-howtos:
2
3Devicetree HOWTOs
4#################
5
6This page has step-by-step advice for getting things done with devicetree.
7
8.. tip:: See :ref:`dt-trouble` for troubleshooting advice.
9
10.. _get-devicetree-outputs:
11
12Get your devicetree and generated header
13****************************************
14
15A board's devicetree (:ref:`BOARD.dts <devicetree-in-out-files>`) pulls in
16common node definitions via ``#include`` preprocessor directives. This at least
17includes the SoC's ``.dtsi``. One way to figure out the devicetree's contents
18is by opening these files, e.g. by looking in
19``dts/<ARCH>/<vendor>/<soc>.dtsi``, but this can be time consuming.
20
21If you just want to see the "final" devicetree for your board, build an
22application and open the :file:`zephyr.dts` file in the build directory.
23
24.. tip::
25
26   You can build :ref:`hello_world` to see the "base" devicetree for your board
27   without any additional changes from :ref:`overlay files <dt-input-files>`.
28
29For example, using the :ref:`qemu_cortex_m3` board to build :ref:`hello_world`:
30
31.. code-block:: sh
32
33   # --cmake-only here just forces CMake to run, skipping the
34   # build process to save time.
35   west build -b qemu_cortex_m3 samples/hello_world --cmake-only
36
37You can change ``qemu_cortex_m3`` to match your board.
38
39CMake prints the input and output file locations like this:
40
41.. code-block:: none
42
43   -- Found BOARD.dts: .../zephyr/boards/arm/qemu_cortex_m3/qemu_cortex_m3.dts
44   -- Generated zephyr.dts: .../zephyr/build/zephyr/zephyr.dts
45   -- Generated devicetree_generated.h: .../zephyr/build/zephyr/include/generated/devicetree_generated.h
46
47The :file:`zephyr.dts` file is the final devicetree in DTS format.
48
49The :file:`devicetree_generated.h` file is the corresponding generated header.
50
51See :ref:`devicetree-in-out-files` for details about these files.
52
53.. _dt-get-device:
54
55Get a struct device from a devicetree node
56******************************************
57
58When writing Zephyr applications, you'll often want to get a driver-level
59:ref:`struct device <device_model_api>` corresponding to a devicetree node.
60
61For example, with this devicetree fragment, you might want the struct device
62for ``serial@40002000``:
63
64.. code-block:: devicetree
65
66   / {
67           soc {
68                   serial0: serial@40002000 {
69                           status = "okay";
70                           current-speed = <115200>;
71                           /* ... */
72                   };
73           };
74
75           aliases {
76                   my-serial = &serial0;
77           };
78
79           chosen {
80                   zephyr,console = &serial0;
81           };
82   };
83
84Start by making a :ref:`node identifier <dt-node-identifiers>` for the device
85you are interested in. There are different ways to do this; pick whichever one
86works best for your requirements. Here are some examples:
87
88.. code-block:: c
89
90   /* Option 1: by node label */
91   #define MY_SERIAL DT_NODELABEL(serial0)
92
93   /* Option 2: by alias */
94   #define MY_SERIAL DT_ALIAS(my_serial)
95
96   /* Option 3: by chosen node */
97   #define MY_SERIAL DT_CHOSEN(zephyr_console)
98
99   /* Option 4: by path */
100   #define MY_SERIAL DT_PATH(soc, serial_40002000)
101
102Once you have a node identifier there are two ways to proceed. One way to get a
103device is to use :c:func:`DEVICE_DT_GET`:
104
105.. code-block:: c
106
107   const struct device *const uart_dev = DEVICE_DT_GET(MY_SERIAL);
108
109   if (!device_is_ready(uart_dev)) {
110           /* Not ready, do not use */
111           return -ENODEV;
112   }
113
114There are variants of :c:func:`DEVICE_DT_GET` such as
115:c:func:`DEVICE_DT_GET_OR_NULL`, :c:func:`DEVICE_DT_GET_ONE` or
116:c:func:`DEVICE_DT_GET_ANY`. This idiom fetches the device pointer at
117build-time, which means there is no runtime penalty. This method is useful if
118you want to store the device pointer as configuration data. But because the
119device may not be initialized, or may have failed to initialize, you must verify
120that the device is ready to be used before passing it to any API functions.
121(This check is done for you by :c:func:`device_get_binding`.)
122
123In some situations the device cannot be known at build-time, e.g., if it depends
124on user input like in a shell application. In this case you can get the
125``struct device`` by combining :c:func:`device_get_binding` with the device
126name:
127
128.. code-block:: c
129
130   const char *dev_name = /* TODO: insert device name from user */;
131   const struct device *uart_dev = device_get_binding(dev_name);
132
133You can then use ``uart_dev`` with :ref:`uart_api` API functions like
134:c:func:`uart_configure`. Similar code will work for other device types; just
135make sure you use the correct API for the device.
136
137If you're having trouble, see :ref:`dt-trouble`. The first thing to check is
138that the node has ``status = "okay"``, like this:
139
140.. code-block:: c
141
142   #define MY_SERIAL DT_NODELABEL(my_serial)
143
144   #if DT_NODE_HAS_STATUS(MY_SERIAL, okay)
145   const struct device *const uart_dev = DEVICE_DT_GET(MY_SERIAL);
146   #else
147   #error "Node is disabled"
148   #endif
149
150If you see the ``#error`` output, make sure to enable the node in your
151devicetree. In some situations your code will compile but it will fail to link
152with a message similar to::
153
154   ...undefined reference to `__device_dts_ord_N'
155   collect2: error: ld returned 1 exit status
156
157This likely means there's a Kconfig issue preventing the device driver from
158being built, resulting in a reference that does not exist. If your code compiles
159successfully, the last thing to check is if the device is ready, like this:
160
161.. code-block:: c
162
163   if (!device_is_ready(uart_dev)) {
164        printk("Device not ready\n");
165   }
166
167If you find that the device is not ready, it likely means that the device's
168initialization function failed. Enabling logging or debugging driver code may
169help in such situations. Note that you can also use :c:func:`device_get_binding`
170to obtain a reference at runtime. If it returns ``NULL`` it can either mean that
171device's driver failed to initialize or that it does not exist.
172
173.. _dts-find-binding:
174
175Find a devicetree binding
176*************************
177
178:ref:`dt-bindings` are YAML files which declare what you can do with the nodes
179they describe, so it's critical to be able to find them for the nodes you are
180using.
181
182If you don't have them already, :ref:`get-devicetree-outputs`. To find a node's
183binding, open the generated header file, which starts with a list of nodes in a
184block comment:
185
186.. code-block:: c
187
188   /*
189    * [...]
190    * Nodes in dependency order (ordinal and path):
191    *   0   /
192    *   1   /aliases
193    *   2   /chosen
194    *   3   /flash@0
195    *   4   /memory@20000000
196    *          (etc.)
197    * [...]
198    */
199
200Make note of the path to the node you want to find, like ``/flash@0``. Search
201for the node's output in the file, which starts with something like this if the
202node has a matching binding:
203
204.. code-block:: c
205
206   /*
207    * Devicetree node:
208    *   /flash@0
209    *
210    * Binding (compatible = soc-nv-flash):
211    *   $ZEPHYR_BASE/dts/bindings/mtd/soc-nv-flash.yaml
212    * [...]
213    */
214
215See :ref:`missing-dt-binding` for troubleshooting.
216
217.. _set-devicetree-overlays:
218
219Set devicetree overlays
220***********************
221
222Devicetree overlays are explained in :ref:`devicetree-intro`. The CMake
223variable :makevar:`DTC_OVERLAY_FILE` contains a space- or semicolon-separated
224list of overlay files to use. If :makevar:`DTC_OVERLAY_FILE` specifies multiple
225files, they are included in that order by the C preprocessor.  A file in a
226Zephyr module can be referred to by escaping the Zephyr module dir variable
227like ``\${ZEPHYR_<module>_MODULE_DIR}/<path-to>/dts.overlay``
228when setting the DTC_OVERLAY_FILE variable.
229
230You can set :makevar:`DTC_OVERLAY_FILE` to contain exactly the files you want
231to use. Here is an :ref:`example <west-building-dtc-overlay-file>` using
232``west build``.
233
234If you don't set :makevar:`DTC_OVERLAY_FILE`, the build system will follow
235these steps, looking for files in your application configuration directory to
236use as devicetree overlays:
237
238#. If the file :file:`boards/<BOARD>.overlay` exists, it will be used.
239#. If the current board has :ref:`multiple revisions <porting_board_revisions>`
240   and :file:`boards/<BOARD>_<revision>.overlay` exists, it will be used.
241   This file will be used in addition to :file:`boards/<BOARD>.overlay`
242   if both exist.
243#. If one or more files have been found in the previous steps, the build system
244   stops looking and just uses those files.
245#. Otherwise, if :file:`<BOARD>.overlay` exists, it will be used, and the build
246   system will stop looking for more files.
247#. Otherwise, if :file:`app.overlay` exists, it will be used.
248
249Extra devicetree overlays may be provided using ``EXTRA_DTC_OVERLAY_FILE`` which
250will still allow the build system to automatically use devicetree overlays
251described in the above steps.
252
253The build system appends overlays specified in ``EXTRA_DTC_OVERLAY_FILE``
254to the overlays in ``DTC_OVERLAY_FILE`` when processing devicetree overlays.
255This means that changes made via ``EXTRA_DTC_OVERLAY_FILE`` have higher
256precedence than those made via ``DTC_OVERLAY_FILE``.
257
258All configuration files will be taken from the application's configuration
259directory except for files with an absolute path that are given with the
260``DTC_OVERLAY_FILE`` or ``EXTRA_DTC_OVERLAY_FILE`` argument.
261
262See :ref:`Application Configuration Directory <application-configuration-directory>`
263on how the application configuration directory is defined.
264
265Using :ref:`shields` will also add devicetree overlay files.
266
267The :makevar:`DTC_OVERLAY_FILE` value is stored in the CMake cache and used
268in successive builds.
269
270The :ref:`build system <build_overview>` prints all the devicetree overlays it
271finds in the configuration phase, like this:
272
273.. code-block:: none
274
275   -- Found devicetree overlay: .../some/file.overlay
276
277.. _use-dt-overlays:
278
279Use devicetree overlays
280***********************
281
282See :ref:`set-devicetree-overlays` for how to add an overlay to the build.
283
284Overlays can override node property values in multiple ways.
285For example, if your BOARD.dts contains this node:
286
287.. code-block:: devicetree
288
289   / {
290           soc {
291                   serial0: serial@40002000 {
292                           status = "okay";
293                           current-speed = <115200>;
294                           /* ... */
295                   };
296           };
297   };
298
299These are equivalent ways to override the ``current-speed`` value in an
300overlay:
301
302.. code-block:: none
303
304   /* Option 1 */
305   &serial0 {
306   	current-speed = <9600>;
307   };
308
309   /* Option 2 */
310   &{/soc/serial@40002000} {
311   	current-speed = <9600>;
312   };
313
314We'll use the ``&serial0`` style for the rest of these examples.
315
316You can add aliases to your devicetree using overlays: an alias is just a
317property of the ``/aliases`` node. For example:
318
319.. code-block:: none
320
321   / {
322   	aliases {
323   		my-serial = &serial0;
324   	};
325   };
326
327Chosen nodes work the same way. For example:
328
329.. code-block:: none
330
331   / {
332   	chosen {
333   		zephyr,console = &serial0;
334   	};
335   };
336
337To delete a property (in addition to deleting properties in general, this is
338how to set a boolean property to false if it's true in BOARD.dts):
339
340.. code-block:: none
341
342   &serial0 {
343   	/delete-property/ some-unwanted-property;
344   };
345
346You can add subnodes using overlays. For example, to configure a SPI or I2C
347child device on an existing bus node, do something like this:
348
349.. code-block:: none
350
351   /* SPI device example */
352   &spi1 {
353	my_spi_device: temp-sensor@0 {
354		compatible = "...";
355		label = "TEMP_SENSOR_0";
356		/* reg is the chip select number, if needed;
357		 * If present, it must match the node's unit address. */
358		reg = <0>;
359
360		/* Configure other SPI device properties as needed.
361		 * Find your device's DT binding for details. */
362		spi-max-frequency = <4000000>;
363	};
364   };
365
366   /* I2C device example */
367   &i2c2 {
368	my_i2c_device: touchscreen@76 {
369		compatible = "...";
370		label = "TOUCHSCREEN";
371		/* reg is the I2C device address.
372		 * It must match the node's unit address. */
373		reg = <76>;
374
375		/* Configure other I2C device properties as needed.
376		 * Find your device's DT binding for details. */
377	};
378   };
379
380Other bus devices can be configured similarly:
381
382- create the device as a subnode of the parent bus
383- set its properties according to its binding
384
385Assuming you have a suitable device driver associated with the
386``my_spi_device`` and ``my_i2c_device`` compatibles, you should now be able to
387enable the driver via Kconfig and :ref:`get the struct device <dt-get-device>`
388for your newly added bus node, then use it with that driver API.
389
390.. _dt-create-devices:
391
392Write device drivers using devicetree APIs
393******************************************
394
395"Devicetree-aware" :ref:`device drivers <device_model_api>` should create a
396``struct device`` for each ``status = "okay"`` devicetree node with a
397particular :ref:`compatible <dt-important-props>` (or related set of
398compatibles) supported by the driver.
399
400Writing a devicetree-aware driver begins by defining a :ref:`devicetree binding
401<dt-bindings>` for the devices supported by the driver. Use existing bindings
402from similar drivers as a starting point. A skeletal binding to get started
403needs nothing more than this:
404
405.. code-block:: yaml
406
407   description: <Human-readable description of your binding>
408   compatible: "foo-company,bar-device"
409   include: base.yaml
410
411See :ref:`dts-find-binding` for more advice on locating existing bindings.
412
413After writing your binding, your driver C file can then use the devicetree API
414to find ``status = "okay"`` nodes with the desired compatible, and instantiate
415a ``struct device`` for each one. There are two options for instantiating each
416``struct device``: using instance numbers, and using node labels.
417
418In either case:
419
420- Each ``struct device``\ 's name should be set to its devicetree node's
421  ``label`` property. This allows the driver's users to :ref:`dt-get-device` in
422  the usual way.
423
424- Each device's initial configuration should use values from devicetree
425  properties whenever practical. This allows users to configure the driver
426  using :ref:`devicetree overlays <use-dt-overlays>`.
427
428Examples for how to do this follow. They assume you've already implemented the
429device-specific configuration and data structures and API functions, like this:
430
431.. code-block:: c
432
433   /* my_driver.c */
434   #include <zephyr/drivers/some_api.h>
435
436   /* Define data (RAM) and configuration (ROM) structures: */
437   struct my_dev_data {
438   	/* per-device values to store in RAM */
439   };
440   struct my_dev_cfg {
441   	uint32_t freq; /* Just an example: initial clock frequency in Hz */
442   	/* other configuration to store in ROM */
443   };
444
445   /* Implement driver API functions (drivers/some_api.h callbacks): */
446   static int my_driver_api_func1(const struct device *dev, uint32_t *foo) { /* ... */ }
447   static int my_driver_api_func2(const struct device *dev, uint64_t bar) { /* ... */ }
448   static struct some_api my_api_funcs = {
449   	.func1 = my_driver_api_func1,
450   	.func2 = my_driver_api_func2,
451   };
452
453.. _dt-create-devices-inst:
454
455Option 1: create devices using instance numbers
456===============================================
457
458Use this option, which uses :ref:`devicetree-inst-apis`, if possible. However,
459they only work when devicetree nodes for your driver's ``compatible`` are all
460equivalent, and you do not need to be able to distinguish between them.
461
462To use instance-based APIs, begin by defining ``DT_DRV_COMPAT`` to the
463lowercase-and-underscores version of the compatible that the device driver
464supports. For example, if your driver's compatible is ``"vnd,my-device"`` in
465devicetree, you would define ``DT_DRV_COMPAT`` to ``vnd_my_device`` in your
466driver C file:
467
468.. code-block:: c
469
470   /*
471    * Put this near the top of the file. After the includes is a good place.
472    * (Note that you can therefore run "git grep DT_DRV_COMPAT drivers" in
473    * the zephyr Git repository to look for example drivers using this style).
474    */
475   #define DT_DRV_COMPAT vnd_my_device
476
477.. important::
478
479   As shown, the DT_DRV_COMPAT macro should have neither quotes nor special
480   characters. Remove quotes and convert special characters to underscores
481   when creating ``DT_DRV_COMPAT`` from the compatible property.
482
483Finally, define an instantiation macro, which creates each ``struct device``
484using instance numbers. Do this after defining ``my_api_funcs``.
485
486.. code-block:: c
487
488   /*
489    * This instantiation macro is named "CREATE_MY_DEVICE".
490    * Its "inst" argument is an arbitrary instance number.
491    *
492    * Put this near the end of the file, e.g. after defining "my_api_funcs".
493    */
494   #define CREATE_MY_DEVICE(inst)					\
495   	static struct my_dev_data my_data_##inst = {			\
496   		/* initialize RAM values as needed, e.g.: */		\
497   		.freq = DT_INST_PROP(inst, clock_frequency),		\
498   	};								\
499   	static const struct my_dev_cfg my_cfg_##inst = {		\
500   		/* initialize ROM values as needed. */			\
501   	};								\
502   	DEVICE_DT_INST_DEFINE(inst,					\
503   			      my_dev_init_function,			\
504			      NULL,             			\
505   			      &my_data_##inst,				\
506   			      &my_cfg_##inst,				\
507   			      MY_DEV_INIT_LEVEL, MY_DEV_INIT_PRIORITY,	\
508   			      &my_api_funcs);
509
510Notice the use of APIs like :c:func:`DT_INST_PROP` and
511:c:func:`DEVICE_DT_INST_DEFINE` to access devicetree node data. These
512APIs retrieve data from the devicetree for instance number ``inst`` of
513the node with compatible determined by ``DT_DRV_COMPAT``.
514
515Finally, pass the instantiation macro to :c:func:`DT_INST_FOREACH_STATUS_OKAY`:
516
517.. code-block:: c
518
519   /* Call the device creation macro for each instance: */
520   DT_INST_FOREACH_STATUS_OKAY(CREATE_MY_DEVICE)
521
522``DT_INST_FOREACH_STATUS_OKAY`` expands to code which calls
523``CREATE_MY_DEVICE`` once for each enabled node with the compatible determined
524by ``DT_DRV_COMPAT``. It does not append a semicolon to the end of the
525expansion of ``CREATE_MY_DEVICE``, so the macro's expansion must end in a
526semicolon or function definition to support multiple devices.
527
528Option 2: create devices using node labels
529==========================================
530
531Some device drivers cannot use instance numbers. One example is an SoC
532peripheral driver which relies on vendor HAL APIs specialized for individual IP
533blocks to implement Zephyr driver callbacks. Cases like this should use
534:c:func:`DT_NODELABEL` to refer to individual nodes in the devicetree
535representing the supported peripherals on the SoC. The devicetree.h
536:ref:`devicetree-generic-apis` can then be used to access node data.
537
538For this to work, your :ref:`SoC's dtsi file <dt-input-files>` must define node
539labels like ``mydevice0``, ``mydevice1``, etc. appropriately for the IP blocks
540your driver supports. The resulting devicetree usually looks something like
541this:
542
543.. code-block:: devicetree
544
545   / {
546           soc {
547                   mydevice0: dev@0 {
548                           compatible = "vnd,my-device";
549                   };
550                   mydevice1: dev@1 {
551                           compatible = "vnd,my-device";
552                   };
553           };
554   };
555
556The driver can use the ``mydevice0`` and ``mydevice1`` node labels in the
557devicetree to operate on specific device nodes:
558
559.. code-block:: c
560
561   /*
562    * This is a convenience macro for creating a node identifier for
563    * the relevant devices. An example use is MYDEV(0) to refer to
564    * the node with label "mydevice0".
565    */
566   #define MYDEV(idx) DT_NODELABEL(mydevice ## idx)
567
568   /*
569    * Define your instantiation macro; "idx" is a number like 0 for mydevice0
570    * or 1 for mydevice1. It uses MYDEV() to create the node label from the
571    * index.
572    */
573   #define CREATE_MY_DEVICE(idx)					\
574	static struct my_dev_data my_data_##idx = {			\
575		/* initialize RAM values as needed, e.g.: */		\
576		.freq = DT_PROP(MYDEV(idx), clock_frequency),		\
577	};								\
578	static const struct my_dev_cfg my_cfg_##idx = { /* ... */ };	\
579   	DEVICE_DT_DEFINE(MYDEV(idx),					\
580   			my_dev_init_function,				\
581			NULL,           				\
582			&my_data_##idx,					\
583			&my_cfg_##idx,					\
584			MY_DEV_INIT_LEVEL, MY_DEV_INIT_PRIORITY,	\
585			&my_api_funcs)
586
587Notice the use of APIs like :c:func:`DT_PROP` and
588:c:func:`DEVICE_DT_DEFINE` to access devicetree node data.
589
590Finally, manually detect each enabled devicetree node and use
591``CREATE_MY_DEVICE`` to instantiate each ``struct device``:
592
593.. code-block:: c
594
595   #if DT_NODE_HAS_STATUS(DT_NODELABEL(mydevice0), okay)
596   CREATE_MY_DEVICE(0)
597   #endif
598
599   #if DT_NODE_HAS_STATUS(DT_NODELABEL(mydevice1), okay)
600   CREATE_MY_DEVICE(1)
601   #endif
602
603Since this style does not use ``DT_INST_FOREACH_STATUS_OKAY()``, the driver
604author is responsible for calling ``CREATE_MY_DEVICE()`` for every possible
605node, e.g. using knowledge about the peripherals available on supported SoCs.
606
607.. _dt-drivers-that-depend:
608
609Device drivers that depend on other devices
610*******************************************
611
612At times, one ``struct device`` depends on another ``struct device`` and
613requires a pointer to it. For example, a sensor device might need a pointer to
614its SPI bus controller device. Some advice:
615
616- Write your devicetree binding in a way that permits use of
617  :ref:`devicetree-hw-api` from devicetree.h if possible.
618- In particular, for bus devices, your driver's binding should include a
619  file like :zephyr_file:`dts/bindings/spi/spi-device.yaml` which provides
620  common definitions for devices addressable via a specific bus. This enables
621  use of APIs like :c:func:`DT_BUS` to obtain a node identifier for the bus
622  node. You can then :ref:`dt-get-device` for the bus in the usual way.
623
624Search existing bindings and device drivers for examples.
625
626.. _dt-apps-that-depend:
627
628Applications that depend on board-specific devices
629**************************************************
630
631One way to allow application code to run unmodified on multiple boards is by
632supporting a devicetree alias to specify the hardware specific portions, as is
633done in the :ref:`blinky-sample`. The application can then be configured in
634:ref:`BOARD.dts <devicetree-in-out-files>` files or via :ref:`devicetree
635overlays <use-dt-overlays>`.
636