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