Part 1
요약·해설
공식 코드 30개, property type 11행, compatible·child-binding·bus·on-bus·include·nexus 규칙을 원문 순서로 보존했습니다.
11 type · constraints
child-binding
bus · on-bus
include · merge
Part 2
접을 수 있는 영어 원문 전체
영어 원문 전체 펼치기
DEEF55CF0EC7FE4E292B2A9DB7E9F123D8CCB2E3697674F74E2A6B42959D325F
.. _dt-bindings-file-syntax:
Devicetree bindings syntax
##########################
This page documents the syntax of Zephyr's bindings format. Zephyr bindings
files are YAML files. A :ref:`simple example <dt-bindings-simple-example>` was
given in the introduction page.
.. contents:: Contents
:local:
:depth: 3
Top level keys
**************
The top level of a bindings file maps keys to values. The top-level keys look
like this:
.. code-block:: yaml
# A high level description of the device the binding applies to:
description: |
This is the Vendomatic company's foo-device.
Descriptions which span multiple lines (like this) are OK,
and are encouraged for complex bindings.
See https://yaml-multiline.info/ for formatting help.
# You can include definitions from other bindings using this syntax:
include: other.yaml
# Used to match nodes to this binding:
compatible: "manufacturer,foo-device"
properties:
# Requirements for and descriptions of the properties that this
# binding's nodes need to satisfy go here.
child-binding:
# You can constrain the children of the nodes matching this binding
# using this key.
# If the node describes bus hardware, like an SPI bus controller
# on an SoC, use 'bus:' to say which one, like this:
bus: spi
# If the node instead appears as a device on a bus, like an external
# SPI memory chip, use 'on-bus:' to say what type of bus, like this.
# Like 'compatible', this key also influences the way nodes match
# bindings.
on-bus: spi
foo-cells:
# "Specifier" cell names for the 'foo' domain go here; example 'foo'
# values are 'gpio', 'pwm', and 'dma'. See below for more information.
These keys are explained in the following sections.
.. _dt-bindings-description:
Description
***********
A free-form description of node hardware goes here. You can put links to
datasheets or example nodes or properties as well.
.. _dt-bindings-compatible:
Compatible
**********
This key is used to match nodes to this binding as described in
:ref:`dt-binding-compat`. It should look like this in a binding file:
.. code-block:: YAML
# Note the comma-separated vendor prefix and device name
compatible: "manufacturer,device"
This devicetree node would match the above binding:
.. code-block:: devicetree
device {
compatible = "manufacturer,device";
};
Assuming no binding has ``compatible: "manufacturer,device-v2"``, it would also
match this node:
.. code-block:: devicetree
device-2 {
compatible = "manufacturer,device-v2", "manufacturer,device";
};
Each node's ``compatible`` property is tried in order. The first matching
binding is used. The :ref:`on-bus: <dt-bindings-on-bus>` key can be used to
refine the search.
If more than one binding for a compatible is found, an error is raised.
The ``manufacturer`` prefix identifies the device vendor. See
:zephyr_file:`dts/bindings/vendor-prefixes.txt` for a list of accepted vendor
prefixes. The ``device`` part is usually from the datasheet.
Some bindings apply to a generic class of devices which do not have a specific
vendor. In these cases, there is no vendor prefix. One example is the
:dtcompatible:`gpio-leds` compatible which is commonly used to describe board
LEDs connected to GPIOs.
.. _dt-bindings-properties:
Properties
**********
The ``properties:`` key describes properties that nodes which match the binding
contain. For example, a binding for a UART peripheral might look something like
this:
.. code-block:: YAML
compatible: "manufacturer,serial"
properties:
reg:
type: array
description: UART peripheral MMIO register space
required: true
current-speed:
type: int
description: current baud rate
required: true
In this example, a node with compatible ``"manufacturer,serial"`` must contain
a node named ``current-speed``. The property's value must be a single integer.
Similarly, the node must contain a ``reg`` property.
The build system uses bindings to generate C macros for devicetree properties
that appear in DTS files. You can read more about how to get property values in
source code from these macros in :ref:`dt-from-c`. Generally speaking, the
build system only generates macros for properties listed in the ``properties:``
key for the matching binding. Properties not mentioned in the binding are
generally ignored by the build system.
The one exception is that the build system will always generate macros for
standard properties, like :ref:`reg <dt-important-props>`, whose meaning is
defined by the devicetree specification. This happens regardless of whether the
node has a matching binding or not.
Property entry syntax
=====================
Property entries in ``properties:`` are written in this syntax:
.. code-block:: none
<property name>:
required: <true | false>
type: <string | int | boolean | array | uint8-array | string-array |
phandle | phandles | phandle-array | path | compound>
deprecated: <true | false>
default: <default>
description: <description of the property>
enum:
- <item1>
- <item2>
...
- <itemN>
const: <string | int | array | uint8-array | string-array>
specifier-space: <space-name>
.. _dt-bindings-example-properties:
Example property definitions
============================
Here are some more examples.
.. code-block:: YAML
properties:
# Describes a property like 'current-speed = <115200>;'. We pretend that
# it's obligatory for the example node and set 'required: true'.
current-speed:
type: int
required: true
description: Initial baud rate for bar-device
# Describes an optional property like 'keys = "foo", "bar";'
keys:
type: string-array
description: Keys for bar-device
# Describes an optional property like 'maximum-speed = "full-speed";'
# the enum specifies known values that the string property may take
maximum-speed:
type: string
description: Configures USB controllers to work up to a specific speed.
enum:
- "low-speed"
- "full-speed"
- "high-speed"
- "super-speed"
# Describes an optional property like 'resolution = <16>;'
# the enum specifies known values that the int property may take
resolution:
type: int
enum:
- 8
- 16
- 24
- 32
# Describes a required property '#address-cells = <1>'; the const
# specifies that the value for the property is expected to be the value 1
"#address-cells":
type: int
required: true
const: 1
int-with-default:
type: int
default: 123
description: Value for int register, default is power-up configuration.
array-with-default:
type: array
default: [1, 2, 3] # Same as 'array-with-default = <1 2 3>'
string-with-default:
type: string
default: "foo"
string-array-with-default:
type: string-array
default: ["foo", "bar"] # Same as 'string-array-with-default = "foo", "bar"'
uint8-array-with-default:
type: uint8-array
default: [0x12, 0x34] # Same as 'uint8-array-with-default = [12 34]'
required
========
Adding ``required: true`` to a property definition will fail the build if a
node matches the binding, but does not contain the property.
The default setting is ``required: false``; that is, properties are optional by
default. Using ``required: false`` is therefore redundant and strongly
discouraged.
type
====
The type of a property constrains its values. The following types are
available. See :ref:`dt-writing-property-values` for more details about writing
values of each type in a DTS file. See :ref:`dt-phandles` for more information
about the ``phandle*`` type properties.
.. list-table::
:header-rows: 1
:widths: 1 3 2
* - Type
- Description
- Example in DTS
* - ``string``
- exactly one string
- ``status = "disabled";``
* - ``int``
- exactly one 32-bit value (cell)
- ``current-speed = <115200>;``
* - ``boolean``
- flags that don't take a value when true, and are absent if false
- ``hw-flow-control;``
* - ``array``
- zero or more 32-bit values (cells)
- ``offsets = <0x100 0x200 0x300>;``
* - ``uint8-array``
- zero or more bytes, in hex ('bytestring' in the Devicetree specification)
- ``local-mac-address = [de ad be ef 12 34];``
* - ``string-array``
- zero or more strings
- ``dma-names = "tx", "rx";``
* - ``phandle``
- exactly one phandle
- ``interrupt-parent = <&gic>;``
* - ``phandles``
- zero or more phandles
- ``pinctrl-0 = <&usart2_tx_pd5 &usart2_rx_pd6>;``
* - ``phandle-array``
- a list of phandles and 32-bit cells (usually specifiers)
- ``dmas = <&dma0 2>, <&dma0 3>;``
* - ``path``
- a path to a node as a phandle path reference or path string
- ``zephyr,bt-c2h-uart = &uart0;`` or
``foo = "/path/to/some/node";``
* - ``compound``
- a catch-all for more complex types (no macros will be generated)
- ``foo = <&label>, [01 02];``
deprecated
==========
A property with ``deprecated: true`` indicates to both the user and the tooling
that the property is meant to be phased out.
The tooling will report a warning if the devicetree includes the property that
is flagged as deprecated. (This warning is upgraded to an error in the
:ref:`twister_script` for upstream pull requests.)
The default setting is ``deprecated: false``. Using ``deprecated: false`` is
therefore redundant and strongly discouraged.
.. _dt-bindings-default:
default
=======
The optional ``default:`` setting gives a value that will be used if the
property is missing from the devicetree node.
For example, with this binding fragment:
.. code-block:: YAML
properties:
foo:
type: int
default: 3
If property ``foo`` is missing in a matching node, then the output will be as
if ``foo = <3>;`` had appeared in the DTS (except YAML data types are used for
the default value).
Note that combining ``default:`` with ``required: true`` will raise an error.
For rules related to ``default`` in upstream Zephyr bindings, see
:ref:`dt-bindings-default-rules`.
See :ref:`dt-bindings-example-properties` for examples. Putting ``default:`` on
any property type besides those used in :ref:`dt-bindings-example-properties`
will raise an error.
enum
====
The ``enum:`` line is followed by a list of values the property may contain. If
a property value in DTS is not in the ``enum:`` list in the binding, an error
is raised. See :ref:`dt-bindings-example-properties` for examples.
const
=====
This specifies a constant value the property must take. It is mainly useful for
constraining the values of common properties for a particular piece of
hardware.
.. _dt-bindings-specifier-space:
specifier-space
===============
.. warning::
It is an abuse of this feature to use it to name properties in
unconventional ways.
For example, this feature is not meant for cases like naming a property
``my-pin``, then assigning it to the "gpio" specifier space using this
feature. Properties which refer to GPIOs should use conventional names, i.e.
end in ``-gpios`` or ``-gpio``.
This property, if present, manually sets the specifier space associated with a
property with type ``phandle-array``.
Normally, the specifier space is encoded implicitly in the property name. A
property named ``foos`` with type ``phandle-array`` implicitly has specifier
space ``foo``. As a special case, ``*-gpios`` properties have specifier space
"gpio", so that ``foo-gpios`` will have specifier space "gpio" rather than
"foo-gpio".
You can use ``specifier-space`` to manually provide a space if
using this convention would result in an awkward or unconventional name.
For example:
.. code-block:: YAML
compatible: ...
properties:
bar:
type: phandle-array
specifier-space: my-custom-space
Above, the ``bar`` property's specifier space is set to "my-custom-space".
You could then use the property in a devicetree like this:
.. code-block:: DTS
controller1: custom-controller@1000 {
#my-custom-space-cells = <2>;
};
controller2: custom-controller@2000 {
#my-custom-space-cells = <1>;
};
my-node {
bar = <&controller1 10 20>, <&controller2 30>;
};
Generally speaking, you should reserve this feature for cases where the
implicit specifier space naming convention doesn't work. One appropriate
example is an ``mboxes`` property with specifier space "mbox", not "mboxe". You
can write this property as follows:
.. code-block:: YAML
properties:
mboxes:
type: phandle-array
specifier-space: mbox
.. _dt-bindings-child:
Child-binding
*************
``child-binding`` can be used when a node has children that all share the same
properties. Each child gets the contents of ``child-binding`` as its binding,
though an explicit ``compatible = ...`` on the child node takes precedence, if
a binding is found for it.
Consider a binding for a PWM LED node like this one, where the child nodes are
required to have a ``pwms`` property:
.. code-block:: devicetree
pwmleds {
compatible = "pwm-leds";
red_pwm_led {
pwms = <&pwm3 4 15625000>;
};
green_pwm_led {
pwms = <&pwm3 0 15625000>;
};
/* ... */
};
The binding would look like this:
.. code-block:: YAML
compatible: "pwm-leds"
child-binding:
description: LED that uses PWM
properties:
pwms:
type: phandle-array
required: true
``child-binding`` also works recursively. For example, this binding:
.. code-block:: YAML
compatible: foo
child-binding:
child-binding:
properties:
my-property:
type: int
required: true
will apply to the ``grandchild`` node in this DTS:
.. code-block:: devicetree
parent {
compatible = "foo";
child {
grandchild {
my-property = <123>;
};
};
};
.. _dt-bindings-bus:
Bus
***
If the node is a bus controller, use ``bus:`` in the binding to say what type
of bus. For example, a binding for a SPI peripheral on an SoC would look like
this:
.. code-block:: YAML
compatible: "manufacturer,spi-peripheral"
bus: spi
# ...
The presence of this key in the binding informs the build system that the
children of any node matching this binding appear on this type of bus.
This in turn influences the way ``on-bus:`` is used to match bindings for the
child nodes.
For a single bus supporting multiple protocols, e.g. I3C and I2C, the ``bus:``
in the binding can have a list as value:
.. code-block:: YAML
compatible: "manufacturer,i3c-controller"
bus: [i3c, i2c]
# ...
.. _dt-bindings-on-bus:
On-bus
******
If the node appears as a device on a bus, use ``on-bus:`` in the binding to say
what type of bus.
For example, a binding for an external SPI memory chip should include this line:
.. code-block:: YAML
on-bus: spi
And a binding for an I2C based temperature sensor should include this line:
.. code-block:: YAML
on-bus: i2c
When looking for a binding for a node, the build system checks if the binding
for the parent node contains ``bus: <bus type>``. If it does, then only
bindings with a matching ``on-bus: <bus type>`` and bindings without an
explicit ``on-bus`` are considered. Bindings with an explicit ``on-bus: <bus
type>`` are searched for first, before bindings without an explicit ``on-bus``.
The search repeats for each item in the node's ``compatible`` property, in
order.
This feature allows the same device to have different bindings depending on
what bus it appears on. For example, consider a sensor device with compatible
``manufacturer,sensor`` which can be used via either I2C or SPI.
The sensor node may therefore appear in the devicetree as a child node of
either an SPI or an I2C controller, like this:
.. code-block:: devicetree
spi-bus@0 {
/* ... some compatible with 'bus: spi', etc. ... */
sensor@0 {
compatible = "manufacturer,sensor";
reg = <0>;
/* ... */
};
};
i2c-bus@0 {
/* ... some compatible with 'bus: i2c', etc. ... */
sensor@79 {
compatible = "manufacturer,sensor";
reg = <79>;
/* ... */
};
};
You can write two separate binding files which match these individual sensor
nodes, even though they have the same compatible:
.. code-block:: YAML
# manufacturer,sensor-spi.yaml, which matches sensor@0 on the SPI bus:
compatible: "manufacturer,sensor"
on-bus: spi
# manufacturer,sensor-i2c.yaml, which matches sensor@79 on the I2C bus:
compatible: "manufacturer,sensor"
properties:
uses-clock-stretching:
type: boolean
on-bus: i2c
Only ``sensor@79`` can have a ``use-clock-stretching`` property. The
bus-sensitive logic ignores :file:`manufacturer,sensor-i2c.yaml` when searching
for a binding for ``sensor@0``.
.. _dt-bindings-cells:
Specifier cell names (\*-cells)
*******************************
This section documents how to name the cells in a specifier within a binding.
These concepts are discussed in detail later in this guide in
:ref:`dt-phandle-arrays`.
Consider a binding for a node whose phandle may appear in a ``phandle-array``
property, like the PWM controllers ``pwm1`` and ``pwm2`` in this example:
.. code-block:: DTS
pwm1: pwm@deadbeef {
compatible = "foo,pwm";
#pwm-cells = <2>;
};
pwm2: pwm@deadbeef {
compatible = "bar,pwm";
#pwm-cells = <1>;
};
my-node {
pwms = <&pwm1 1 2000>, <&pwm2 3000>;
};
The bindings for compatible ``"foo,pwm"`` and ``"bar,pwm"`` must give a name to
the cells that appear in a PWM specifier using ``pwm-cells:``, like this:
.. code-block:: YAML
# foo,pwm.yaml
compatible: "foo,pwm"
...
pwm-cells:
- channel
- period
# bar,pwm.yaml
compatible: "bar,pwm"
...
pwm-cells:
- period
A ``*-names`` (e.g. ``pwm-names``) property can appear on the node as well,
giving a name to each entry.
This allows the cells in the specifiers to be accessed by name, e.g. using APIs
like :c:macro:`DT_PWMS_CHANNEL_BY_NAME`.
If the specifier is empty (e.g. ``#clock-cells = <0>``), then ``*-cells`` can
either be omitted (recommended) or set to an empty array. Note that an empty
array is specified as e.g. ``clock-cells: []`` in YAML.
.. _dt-bindings-include:
Include
*******
Bindings can include other files, which can be used to share common property
definitions between bindings. Use the ``include:`` key for this. Its value is
either a string or a list.
In the simplest case, you can include another file by giving its name as a
string, like this:
.. code-block:: YAML
include: foo.yaml
If any file named :file:`foo.yaml` is found (see
:ref:`dt-where-bindings-are-located` for the search process), it will be
included into this binding.
Included files are merged into bindings with a simple recursive dictionary
merge. The build system will check that the resulting merged binding is
well-formed. It is allowed to include at any level, including ``child-binding``,
like this:
.. code-block:: YAML
# foo.yaml will be merged with content at this level
include: foo.yaml
child-binding:
# bar.yaml will be merged with content at this level
include: bar.yaml
It is an error if a key appears with a different value in a binding and in a
file it includes, with one exception: a binding can have ``required: true`` for
a :ref:`property definition <dt-bindings-properties>` for which the included
file has ``required: false``. The ``required: true`` takes precedence, allowing
bindings to strengthen requirements from included files.
Note that weakening requirements by having ``required: false`` where the
included file has ``required: true`` is an error. This is meant to keep the
organization clean.
The file :zephyr_file:`base.yaml <dts/bindings/base/base.yaml>` contains
definitions for many common properties. When writing a new binding, it is a
good idea to check if :file:`base.yaml` already defines some of the needed
properties, and include it if it does.
Note that you can make a property defined in base.yaml obligatory like this,
taking :ref:`reg <dt-important-props>` as an example:
.. code-block:: YAML
reg:
required: true
This relies on the dictionary merge to fill in the other keys for ``reg``, like
``type``.
To include multiple files, you can use a list of strings:
.. code-block:: YAML
include:
- foo.yaml
- bar.yaml
This includes the files :file:`foo.yaml` and :file:`bar.yaml`. (You can
write this list in a single line of YAML as ``include: [foo.yaml, bar.yaml]``.)
When including multiple files, any overlapping ``required`` keys on properties
in the included files are ORed together. This makes sure that a ``required:
true`` is always respected.
In some cases, you may want to include some property definitions from a file,
but not all of them. In this case, ``include:`` should be a list, and you can
filter out just the definitions you want by putting a mapping in the list, like
this:
.. code-block:: YAML
include:
- name: foo.yaml
property-allowlist:
- i-want-this-one
- and-this-one
- name: bar.yaml
property-blocklist:
- do-not-include-this-one
- or-this-one
Each map element must have a ``name`` key which is the filename to include, and
may have ``property-allowlist`` and ``property-blocklist`` keys that filter
which properties are included.
You cannot have a single map element with both ``property-allowlist`` and
``property-blocklist`` keys. A map element with neither ``property-allowlist``
nor ``property-blocklist`` is valid; no additional filtering is done.
You can freely intermix strings and mappings in a single ``include:`` list:
.. code-block:: YAML
include:
- foo.yaml
- name: bar.yaml
property-blocklist:
- do-not-include-this-one
- or-this-one
Finally, you can filter from a child binding like this:
.. code-block:: YAML
include:
- name: bar.yaml
child-binding:
property-allowlist:
- child-prop-to-allow
Nexus nodes and maps
********************
All ``phandle-array`` type properties support mapping through ``*-map``
properties, e.g. ``gpio-map``, as defined by the Devicetree specification.
This is used, for example, to define connector nodes for common breakout
headers, such as the ``arduino_header`` nodes that are conventionally defined
in the devicetrees for boards with Arduino compatible expansion headers.
Part 3
한국어 전문 번역
Binding 파일의 최상위 키
Zephyr binding은 YAML 파일입니다. 최상위에는 key와 value의 mapping이 있으며 전체 형태는 다음 예와 같습니다.
# A high level description of the device the binding applies to:
description: |
This is the Vendomatic company's foo-device.
Descriptions which span multiple lines (like this) are OK,
and are encouraged for complex bindings.
See https://yaml-multiline.info/ for formatting help.
# You can include definitions from other bindings using this syntax:
include: other.yaml
# Used to match nodes to this binding:
compatible: "manufacturer,foo-device"
properties:
# Requirements for and descriptions of the properties that this
# binding's nodes need to satisfy go here.
child-binding:
# You can constrain the children of the nodes matching this binding
# using this key.
# If the node describes bus hardware, like an SPI bus controller
# on an SoC, use 'bus:' to say which one, like this:
bus: spi
# If the node instead appears as a device on a bus, like an external
# SPI memory chip, use 'on-bus:' to say what type of bus, like this.
# Like 'compatible', this key also influences the way nodes match
# bindings.
on-bus: spi
foo-cells:
# "Specifier" cell names for the 'foo' domain go here; example 'foo'
# values are 'gpio', 'pwm', and 'dma'. See below for more information.description은 장치 설명, include는 공통 정의 재사용, compatible은 node matching, properties는 property 제약, child-binding은 child 제약을 담당합니다. Bus controller는 bus, bus 위의 device는 on-bus를 사용합니다. foo-cells 형태의 키는 GPIO·PWM·DMA 같은 specifier의 cell 이름을 정의합니다.
Description
description에는 node hardware를 자유 형식으로 설명합니다. Datasheet 링크, 예제 node, property 사용 예도 넣을 수 있고 복잡한 binding은 여러 줄 설명을 권장합니다.
Compatible
compatible은 node와 binding을 연결합니다. 보통 comma로 구분한 vendor prefix와 device 이름을 사용합니다.
# Note the comma-separated vendor prefix and device name
compatible: "manufacturer,device"다음 node는 위 binding과 직접 일치합니다.
device {
compatible = "manufacturer,device";
};manufacturer,device-v2 전용 binding이 없다면 다음 node도 두 번째 compatible을 통해 같은 binding과 일치합니다.
device-2 {
compatible = "manufacturer,device-v2", "manufacturer,device";
};각 compatible은 적힌 순서대로 시도하며 첫 번째 일치 binding을 사용합니다. on-bus가 검색을 더 세분화합니다. 같은 compatible에 대한 binding이 둘 이상 발견되면 모호하므로 error입니다. Vendor prefix는 dts/bindings/vendor-prefixes.txt의 허용 목록을 따르고 device 부분은 보통 datasheet의 이름을 사용합니다. 특정 vendor가 없는 일반 장치 class는 gpio-leds처럼 prefix 없이 쓸 수 있습니다.
Properties
properties는 일치하는 node가 가질 property와 제약을 설명합니다. 다음 UART binding은 reg와 current-speed를 모두 필수로 지정합니다.
compatible: "manufacturer,serial"
properties:
reg:
type: array
description: UART peripheral MMIO register space
required: true
current-speed:
type: int
description: current baud rate
required: true따라서 manufacturer,serial node에는 정수 current-speed와 reg가 반드시 있어야 합니다. 일반적으로 build system은 binding의 properties에 적힌 DTS property만 C macro로 만들고 나머지는 무시합니다. 단, Devicetree 규격이 정의한 reg 같은 표준 property는 matching binding이 없어도 macro를 생성합니다.
Property 항목 문법
<property name>:
required: <true | false>
type: <string | int | boolean | array | uint8-array | string-array |
phandle | phandles | phandle-array | path | compound>
deprecated: <true | false>
default: <default>
description: <description of the property>
enum:
- <item1>
- <item2>
...
- <itemN>
const: <string | int | array | uint8-array | string-array>
specifier-space: <space-name>각 property에는 필수 여부, 자료형, 폐기 여부, 기본값, 설명, 허용 목록, 상수값, specifier 공간을 조합해 지정할 수 있습니다.
Property 정의 예제
properties:
# Describes a property like 'current-speed = <115200>;'. We pretend that
# it's obligatory for the example node and set 'required: true'.
current-speed:
type: int
required: true
description: Initial baud rate for bar-device
# Describes an optional property like 'keys = "foo", "bar";'
keys:
type: string-array
description: Keys for bar-device
# Describes an optional property like 'maximum-speed = "full-speed";'
# the enum specifies known values that the string property may take
maximum-speed:
type: string
description: Configures USB controllers to work up to a specific speed.
enum:
- "low-speed"
- "full-speed"
- "high-speed"
- "super-speed"
# Describes an optional property like 'resolution = <16>;'
# the enum specifies known values that the int property may take
resolution:
type: int
enum:
- 8
- 16
- 24
- 32
# Describes a required property '#address-cells = <1>'; the const
# specifies that the value for the property is expected to be the value 1
"#address-cells":
type: int
required: true
const: 1
int-with-default:
type: int
default: 123
description: Value for int register, default is power-up configuration.
array-with-default:
type: array
default: [1, 2, 3] # Same as 'array-with-default = <1 2 3>'
string-with-default:
type: string
default: "foo"
string-array-with-default:
type: string-array
default: ["foo", "bar"] # Same as 'string-array-with-default = "foo", "bar"'
uint8-array-with-default:
type: uint8-array
default: [0x12, 0x34] # Same as 'uint8-array-with-default = [12 34]'예제는 필수 정수, 선택 문자열 배열, 문자열·정수 enum, 상수, 그리고 int·array·string·string-array·uint8-array 기본값을 모두 보여 줍니다.
required
required: true인 property가 matching node에 없으면 build가 실패합니다. 기본값은 false, 즉 선택 사항이므로 required: false를 명시하는 것은 중복이며 강하게 권장되지 않습니다.
type
Type은 DTS에서 property가 가질 수 있는 값의 모양을 제한합니다.
| Type | 설명 | DTS 예제 |
|---|---|---|
string | 정확히 한 개의 문자열 | status = "disabled"; |
int | 정확히 한 개의 32-bit 값(cell) | current-speed = <115200>; |
boolean | 참이면 값 없이 존재하고 거짓이면 property 자체가 없음 | hw-flow-control; |
array | 0개 이상의 32-bit 값(cell) | offsets = <0x100 0x200 0x300>; |
uint8-array | 0개 이상의 16진수 byte. Devicetree 규격의 bytestring | local-mac-address = [de ad be ef 12 34]; |
string-array | 0개 이상의 문자열 | dma-names = "tx", "rx"; |
phandle | 정확히 한 개의 phandle | interrupt-parent = <&gic>; |
phandles | 0개 이상의 phandle | pinctrl-0 = <&usart2_tx_pd5 &usart2_rx_pd6>; |
phandle-array | phandle과 32-bit cell, 보통 specifier의 목록 | dmas = <&dma0 2>, <&dma0 3>; |
path | Phandle path 참조 또는 path 문자열로 쓴 node 경로 | zephyr,bt-c2h-uart = &uart0; 또는 foo = "/path/to/some/node"; |
compound | 더 복잡한 형식의 포괄 항목. Macro는 생성되지 않음 | foo = <&label>, [01 02]; |
deprecated
deprecated: true는 해당 property를 단계적으로 제거할 예정임을 사용자와 도구에 알립니다. DTS가 이 property를 포함하면 warning이 발생하며 upstream pull request용 Twister에서는 error로 승격됩니다. 기본값은 false이므로 이를 명시하지 않는 것이 좋습니다.
default
선택적인 default는 DTS node에 property가 없을 때 사용할 값을 지정합니다.
properties:
foo:
type: int
default: 3Matching node에 foo가 없으면 출력은 DTS에 foo = <3>;가 있었던 것처럼 동작합니다. 다만 default 값에는 YAML 자료형을 사용합니다. default와 required: true를 함께 쓰면 error입니다. 공식 예제에서 지원한 type 이외에 default를 붙여도 error가 납니다.
enum과 const
enum은 property가 가질 수 있는 값의 목록입니다. DTS 값이 목록에 없으면 error입니다. const는 property가 반드시 가져야 할 단 하나의 상수값이며, 특정 hardware에서 공통 property의 값을 더 좁게 제한할 때 유용합니다.
specifier-space
specifier-space는 phandle-array property와 연결할 specifier 공간을 수동 지정합니다. 보통 foos는 암묵적으로 foo 공간을 사용합니다. 특별히 *-gpios는 foo-gpio가 아니라 gpio 공간을 사용합니다.
compatible: ...
properties:
bar:
type: phandle-array
specifier-space: my-custom-space위 binding은 bar를 my-custom-space에 연결하므로 다음처럼 controller마다 다른 cell 수를 사용할 수 있습니다.
controller1: custom-controller@1000 {
#my-custom-space-cells = <2>;
};
controller2: custom-controller@2000 {
#my-custom-space-cells = <1>;
};
my-node {
bar = <&controller1 10 20>, <&controller2 30>;
};이 기능은 암묵적 이름 규칙이 어색해지는 경우에만 사용해야 합니다. 대표적인 올바른 예는 mboxes의 공간을 잘못 파생된 mboxe가 아니라 mbox로 정하는 경우입니다.
properties:
mboxes:
type: phandle-array
specifier-space: mboxChild-binding
child-binding은 한 node의 모든 child가 같은 property 구조를 가질 때 사용합니다. 각 child는 이 내용을 자신의 binding으로 받습니다. 다만 child에 명시적인 compatible이 있고 그에 맞는 binding을 찾으면 그 binding이 우선합니다.
pwmleds {
compatible = "pwm-leds";
red_pwm_led {
pwms = <&pwm3 4 15625000>;
};
green_pwm_led {
pwms = <&pwm3 0 15625000>;
};
/* ... */
};위 PWM LED child는 모두 pwms가 필요하므로 parent binding은 다음과 같이 작성합니다.
compatible: "pwm-leds"
child-binding:
description: LED that uses PWM
properties:
pwms:
type: phandle-array
required: truechild-binding은 재귀적으로 중첩할 수 있습니다.
compatible: foo
child-binding:
child-binding:
properties:
my-property:
type: int
required: true위 두 단계 child-binding은 다음 DTS의 grandchild에 적용되어 my-property를 필수 정수로 검사합니다.
parent {
compatible = "foo";
child {
grandchild {
my-property = <123>;
};
};
};Bus와 On-bus
bus
Node가 bus controller라면 binding의 bus에 bus 종류를 선언합니다.
compatible: "manufacturer,spi-peripheral"
bus: spi
# ...이 키는 matching node의 child가 해당 종류 bus 위에 있음을 build system에 알리고, child의 on-bus binding 검색에 영향을 줍니다. I3C와 I2C처럼 한 controller가 여러 protocol을 지원하면 목록을 사용할 수 있습니다.
compatible: "manufacturer,i3c-controller"
bus: [i3c, i2c]
# ...on-bus
Node가 bus 위의 device라면 binding의 on-bus에 bus 종류를 지정합니다. 외부 SPI memory와 I2C temperature sensor는 각각 다음처럼 씁니다.
on-bus: spion-bus: i2cBinding 검색 시 parent binding이 bus: <종류>를 가지면 같은 on-bus를 가진 binding과 on-bus가 없는 binding만 후보가 됩니다. 명시적인 on-bus 일치를 먼저 찾고, 그 다음 일반 binding을 찾습니다. 이 검색은 node의 compatible 항목마다 순서대로 반복됩니다.
따라서 같은 compatible의 sensor라도 SPI child와 I2C child에 서로 다른 binding을 적용할 수 있습니다.
spi-bus@0 {
/* ... some compatible with 'bus: spi', etc. ... */
sensor@0 {
compatible = "manufacturer,sensor";
reg = <0>;
/* ... */
};
};
i2c-bus@0 {
/* ... some compatible with 'bus: i2c', etc. ... */
sensor@79 {
compatible = "manufacturer,sensor";
reg = <79>;
/* ... */
};
};두 node의 compatible은 같지만 별도의 SPI·I2C binding 파일을 작성할 수 있습니다.
# manufacturer,sensor-spi.yaml, which matches sensor@0 on the SPI bus:
compatible: "manufacturer,sensor"
on-bus: spi
# manufacturer,sensor-i2c.yaml, which matches sensor@79 on the I2C bus:
compatible: "manufacturer,sensor"
properties:
uses-clock-stretching:
type: boolean
on-bus: i2cI2C binding에만 정의된 uses-clock-stretching property는 sensor@79에서만 사용할 수 있습니다. SPI의 sensor@0을 찾을 때는 I2C binding을 무시합니다.
Specifier cell 이름(*-cells)
phandle-array 안의 specifier cell은 binding에서 이름을 붙여야 API가 각 값을 이름으로 읽을 수 있습니다. 다음 두 PWM controller는 각각 2개와 1개의 PWM cell을 사용합니다.
pwm1: pwm@deadbeef {
compatible = "foo,pwm";
#pwm-cells = <2>;
};
pwm2: pwm@deadbeef {
compatible = "bar,pwm";
#pwm-cells = <1>;
};
my-node {
pwms = <&pwm1 1 2000>, <&pwm2 3000>;
};각 compatible binding은 pwm-cells에 cell 이름을 같은 순서로 정의합니다.
# foo,pwm.yaml
compatible: "foo,pwm"
...
pwm-cells:
- channel
- period
# bar,pwm.yaml
compatible: "bar,pwm"
...
pwm-cells:
- periodNode에는 pwm-names 같은 *-names property를 두어 각 entry에도 이름을 줄 수 있습니다. 그러면 DT_PWMS_CHANNEL_BY_NAME 같은 API로 specifier cell을 읽을 수 있습니다. Specifier가 비어 #clock-cells = <0>이면 *-cells를 생략하는 것이 권장되며, 명시하려면 YAML에서 clock-cells: []를 사용합니다.
Include
include는 공통 property 정의를 다른 binding과 공유합니다. 값은 문자열 하나 또는 목록입니다.
include: foo.yamlBinding 검색 경로에서 foo.yaml을 찾으면 현재 binding에 포함합니다. 포함 파일은 단순한 재귀 dictionary merge로 합치며, 합친 결과가 올바른 binding인지 다시 검사합니다. 최상위뿐 아니라 child-binding 안에서도 include할 수 있습니다.
# foo.yaml will be merged with content at this level
include: foo.yaml
child-binding:
# bar.yaml will be merged with content at this level
include: bar.yaml같은 key가 현재 binding과 포함 파일에 서로 다른 값으로 있으면 원칙적으로 error입니다. 유일한 예외는 포함 파일의 required: false를 현재 binding이 required: true로 강화하는 경우입니다. 반대로 필수 항목을 선택 항목으로 약화하면 error입니다.
base.yaml에는 여러 공통 property 정의가 있으므로 새 binding을 만들 때 먼저 확인해야 합니다. 예를 들어 base.yaml의 reg 정의를 가져온 상태에서 다음처럼 필수 여부만 강화할 수 있고, type 같은 나머지 key는 dictionary merge로 채워집니다.
reg:
required: true여러 파일은 문자열 목록으로 포함하며 한 줄 YAML 목록도 가능합니다.
include:
- foo.yaml
- bar.yaml여러 포함 파일의 같은 property에서 required가 겹치면 논리 OR로 합칩니다. 따라서 어느 한 파일의 required: true도 사라지지 않습니다.
파일의 일부 property만 포함하려면 목록의 mapping 항목에 property-allowlist 또는 property-blocklist를 사용합니다.
include:
- name: foo.yaml
property-allowlist:
- i-want-this-one
- and-this-one
- name: bar.yaml
property-blocklist:
- do-not-include-this-one
- or-this-one각 mapping에는 포함할 파일명인 name이 필수입니다. 한 mapping에 allowlist와 blocklist를 동시에 둘 수 없습니다. 둘 다 없으면 추가 filtering 없이 전체를 포함합니다. 같은 include 목록에서 단순 문자열과 mapping을 자유롭게 섞을 수도 있습니다.
include:
- foo.yaml
- name: bar.yaml
property-blocklist:
- do-not-include-this-one
- or-this-oneChild binding의 property에도 filter를 적용할 수 있습니다.
include:
- name: bar.yaml
child-binding:
property-allowlist:
- child-prop-to-allowNexus node와 map
모든 phandle-array property는 Devicetree 규격이 정의한 *-map property, 예를 들어 gpio-map을 통한 mapping을 지원합니다. Board의 Arduino 호환 expansion header에 관례적으로 정의하는 arduino_header 같은 공통 breakout connector node가 대표적인 사용 사례입니다.
Source
출처
원문 파일의 단락, directive, 표, 코드, symbol, 경로는 영어 원문 영역에 그대로 보존했습니다.