doc/hardware/porting/board_porting.rst
.. _board_porting_guide:
Board Porting Guide ###################
To add Zephyr support for a new :term:board, you at least need a board
directory with various files in it. Files in the board directory inherit
support for at least one SoC and all of its features. Therefore, Zephyr must
support your :term:SoC as well.
.. _hw_model_v2:
Transition to the current hardware model
Shortly after Zephyr 3.6.0 was released, a new hardware model was introduced to Zephyr. This new model overhauls the way both SoCs and boards are named and defined, and adds support for features that had been identified as important over the years. Among them:
sysbuildAll the documentation in this page refers to the current hardware model. Please refer to the documentation in Zephyr v3.6.0 (or earlier) for information on the previous, now obsolete, hardware model.
More information about the rationale, development and concepts behind the new
model can be found in the :github:original issue <51831>, the
:github:original Pull Request <50305> and, for a complete set of changes
introduced, the hardware model v2 commit_.
Some non-critical features, enhancements and improvements of the new hardware
model are still in development. Check the
:github:hardware model v2 enhancements issue <69546> for a complete list.
The transition from the previous hardware model to the current one (commonly referred to as "hardware model v2") requires modifications to all existing board and SoC definitions. A decision was made not to provide direct backwards compatibility for the previous model, which leaves users transitioning from a previous version of Zephyr to one including the new model (v3.7.0 and onwards) with two options if they have an out-of-tree board (or SoC):
#. Convert the out-of-tree board to the current hardware model (recommended)
#. Take the SoC definition from Zephyr v3.6.0 and copy it to your downstream
repository (ensuring that the build system can find it via a
:ref:zephyr module <modules> or SOC_ROOT). This will allow your board,
defined in the previous hardware model, to continue to work
When converting your board from the previous to the current hardware model, we
recommend first reading through this page to understand the model in detail. You
can then use the example-application conversion Pull Request_ as an example on
how to port a simple board. Additionally, a conversion script_ is available
and works reliably in many cases (though multi-core SoCs may not be handled
entirely). Finally, the hardware model v2 commit_ contains the full conversion
of all existing boards from the old to the current model, so you can use it as a
complete conversion reference.
.. _hardware model v2 commit: https://github.com/zephyrproject-rtos/zephyr/commit/8dc3f856229ce083c956aa301c31a23e65bd8cd8 .. _example-application conversion Pull Request: https://github.com/zephyrproject-rtos/example-application/pull/58 .. _conversion script: https://github.com/zephyrproject-rtos/zephyr/blob/main/scripts/utils/board_v1_to_v2.py
.. _hw_support_hierarchy:
Hardware support hierarchy
Zephyr's hardware support is based on a series of hierarchical abstractions.
Primarily, each :term:board has one or more :term:SoC.
Each SoC can be optionally classed into an :term:SoC series, which in turn may optionally belong to an :term:SoC family.
Each SoC has one or more :term:CPU cluster, each containing one or more :term:CPU core of a particular :term:architecture.
You can visualize the hierarchy in the diagram below:
.. figure:: board/hierarchy.png :width: 500px :align: center :alt: Hardware support Hierarchy
Hardware support Hierarchy
Below are some examples of the hierarchy described in this section, in the form
of a :term:board per row with its corresponding hierarchy entries. Notice how
the :term:SoC series and :term:SoC family levels are not always used.
.. table::
+--------------------------------------------+--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
| :term:board name | :term:board qualifiers | :term:SoC | :term:SoC Series | :term:SoC family | CPU core | :term:architecture |
+============================================+==========================+=============+====================+====================+================+======================+
| :zephyr:board:nrf52dk | nrf52832 | nRF52832 | nRF52 | Nordic nRF | Arm Cortex-M4 | ARMv7-M |
+--------------------------------------------+--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
| :zephyr:board:frdm_k64f <frdm_k64f> | mk64f12 | MK64F12 | Kinetis K6x | NXP Kinetis | Arm Cortex-M4 | ARMv7-M |
+--------------------------------------------+--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
| :zephyr:board:rv32m1_vega <rv32m1_vega> | openisa_rv32m1/ri5cy | RV32M1 | (Not used) | (Not used) | RI5CY | RISC-V RV32 |
+--------------------------------------------+--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
| :zephyr:board:nrf5340dk | nrf5340/cpuapp | nRF5340 | nRF53 | Nordic nRF | Arm Cortex-M33 | ARMv8-M |
| +--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
| | nrf5340/cpunet | nRF5340 | nRF53 | Nordic nRF | Arm Cortex-M33 | ARMv8-M |
+--------------------------------------------+--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
| :zephyr:board:mimx8mp_evk <imx8mp_evk> | mimx8ml8/a53 | i.MX8M Plus | i.MX8M | NXP i.MX | Arm Cortex-A53 | ARMv8-A |
| +--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
| | mimx8ml8/m7 | i.MX8M Plus | i.MX8M | NXP i.MX | Arm Cortex-M7 | ARMv7-M |
| +--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
| | mimx8ml8/adsp | i.MX8M Plus | i.MX8M | NXP i.MX | Cadence HIFI4 | Xtensa LX6 |
+--------------------------------------------+--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
Additional details about terminology can be found in the next section.
.. _board_terminology:
Board terminology
The previous section introduced the hierarchical manner in which Zephyr classifies and implements hardware support. This section focuses on the terminology used around hardware support, and in particular when defining and working with boards and SoCs.
The overall set of terms used around the concept of board in Zephyr is depicted
in the image below, which uses the :zephyr:board:bl5340_dvk board as reference.
.. figure:: board/board-terminology.svg :width: 500px :align: center :alt: Board terminology diagram
Board terminology diagram
The diagram shows the different terms that are used to describe boards:
board name: bl5340_dvkboard revision: 1.2.0board qualifiers, that optionally describe the :term:SoC,
:term:CPU cluster and :term:variant: nrf5340/cpuapp/nsboard target, which uniquely identifies a combination of the above
and can be used to specify the hardware to build for when using the tooling
provided by Zephyr: [email protected]/nrf5340/cpuapp/nsFormally this can also be seen as
:samp:{board name}[@{revision}][/{board qualifiers}], which can be extended to
:samp:{board name}[@{revision}][/{SoC}[/{CPU cluster}][/{variant}]].
If a board contains only one single-core SoC, then the SoC can be omitted from
the board target. This implies that if the board does not define any board
qualifiers, the board name can be used as a board target. Conversely, if
board qualifiers are part of the board definition, then the SoC can be omitted
by leaving it out but including the corresponding forward-slashes: //.
Continuing with the example above, The board :zephyr:board:bl5340_dvk is a single SoC
board where the SoC defines two CPU clusters: cpuapp and cpunet. One of
the CPU clusters, cpuapp, additionally defines a non-secure board variant,
ns.
The board qualifiers nrf5340/cpuapp/ns can be read as:
nrf5340: The SoC, which is a Nordic nRF5340 dual-core SoCcpuapp: The CPU cluster cpuapp, which consists of a single Cortex-M33
CPU core. The number of cores in a CPU cluster cannot be determined from the
board qualifiers.ns: a variant, in this case ns is a common variant name in
Zephyr denoting a non-secure build for boards supporting :ref:tfm.Not all SoCs define CPU clusters or variants. For example a simple board
like the :zephyr:board:thingy52 contains a single SoC with no CPU clusters and
no variants.
For thingy52 the board target thingy52/nrf52832 can be read as:
thingy52: board name.nrf52832: The board qualifiers, in this case identical to the SoC, which
is a Nordic nRF52832.Make sure your SoC is supported
Start by making sure your SoC is supported by Zephyr. If it is, it's time to
:ref:create-your-board-directory. If you don't know, try:
boards for names that look relevant, and reading individual
board documentation to find out for sure.If you need to add a SoC, CPU cluster, or even architecture support, this is the wrong page, but here is some general advice.
See :ref:architecture_porting_guide.
CPU core support files go in core subdirectories under :zephyr_file:arch,
e.g. :zephyr_file:arch/x86/core.
See :ref:gs_toolchain for information about toolchains (compiler, linker,
etc.) supported by Zephyr. If you need to support a new toolchain,
:ref:build_overview is a good place to start learning about the build system.
Please reach out to the community if you are looking for advice or want to
collaborate on toolchain support.
Zephyr SoC support files are in architecture-specific subdirectories of
:zephyr_file:soc. They are generally grouped by SoC family.
When adding a new SoC family or series for a vendor that already has SoC
support within Zephyr, please try to extract common functionality into shared
files to avoid duplication. If there is no support for your vendor yet, you can
add it in a new directory zephyr/soc/<VENDOR>/<YOUR-SOC>; please use
self-explanatory directory names.
.. _create-your-board-directory:
Create your board directory
Once you've found an existing board that uses your SoC, you can usually start by copy/pasting its board directory and changing its contents for your hardware.
You need to give your board a unique name. Run west boards for a list of
names that are already taken, and pick something new. Let's say your board is
called plank (please don't actually use that name).
Start by creating the board directory zephyr/boards/<VENDOR>/plank, where
<VENDOR> is your vendor subdirectory. (You don't have to put your
board directory in the zephyr repository, but it's the easiest way to get
started. See :ref:custom_board_definition for documentation on moving your
board directory to a separate repository once it's working.)
.. note::
A <VENDOR> subdirectory is mandatory if contributing your board
to Zephyr, but if your board is placed in a local repo, then any folder
structure under <your-repo>/boards is permitted.
If the vendor is defined in the list in
:zephyr_file:dts/bindings/vendor-prefixes.txt then you must use
that vendor prefix as <VENDOR>. others may be used as vendor prefix if
the vendor is not defined.
.. note::
The board directory name does not need to match the name of the board. Multiple boards can even be defined in one directory.
Your board directory should look like this:
.. code-block:: none
boards/<VENDOR>/plank ├── board.yml ├── board.cmake ├── CMakeLists.txt ├── doc │ ├── plank.webp │ └── index.rst ├── Kconfig.plank ├── Kconfig.defconfig ├── plank_<qualifiers>defconfig ├── plank<qualifiers>.dts └── plank_<qualifiers>.yaml
Replace plank with your board's name, of course.
The mandatory files are:
#. :file:board.yml: a YAML file describing the high-level meta data of the
boards such as the boards names, their SoCs, and variants.
CPU clusters for multi-core SoCs are not described in this file as they are
inherited from the SoC's YAML description.
#. :file:plank_<qualifiers>.dts: a hardware description
in :ref:devicetree <dt-guide> format. This declares your SoC, connectors,
and any other hardware components such as LEDs, buttons, sensors, or
communication peripherals (USB, Bluetooth controller, etc).
#. :file:Kconfig.plank: the base software configuration for selecting SoC and
other board and SoC related settings. Kconfig settings outside of the board
and SoC tree must not be selected. To select general Zephyr Kconfig settings
the :file:Kconfig file must be used.
The optional files are:
Kconfig, :file:Kconfig.defconfig software configuration in
:ref:kconfig formats. This provides default settings for software features
and peripheral drivers.plank_defconfig and :file:plank_<qualifiers>_defconfig: software
configuration in Kconfig .conf format.board.cmake: used for :ref:flash-and-debug-supportCMakeLists.txt: if you need to add additional source files to
your build.doc/index.rst, :file:doc/plank.webp: documentation for and a picture
of your board. You only need this if you're :ref:contributing-your-board to
Zephyr.plank_<qualifiers>.yaml: a YAML file with miscellaneous metadata used
by the :ref:twister_script.Board qualifiers of the form <soc>/<cpucluster>/<variant> are normalized so
that / is replaced with _ when used for filenames, for example:
soc1/foo becomes soc1_foo when used in filenames.
.. _board_description:
Write your board YAML
The board YAML file describes the board at a high level. This includes the SoC, board variants, and board revisions.
Detailed configurations, such as hardware description and configuration are done in devicetree and Kconfig.
The skeleton of the board YAML file is:
.. code-block:: yaml
board: name: <board-name> vendor: <board-vendor> revision: format: <major.minor.patch|letter|number|custom> default: <default-revision-value> exact: <true|false> revisions: - name: <revA> - name: <revB> ... socs: - name: <soc-1> variants: - name: <variant-1> - name: <variant-2> variants: - name: <sub-variant-2-1> ... - name: <soc-2> ...
It is possible to have multiple boards located in the board folder.
If multiple boards are placed in the same board folder, then the file
:file:board.yml must describe those in a list as:
.. code-block:: yaml
boards:
.. _default_board_configuration:
Write your devicetree
The devicetree file :file:boards/<vendor>/plank/plank_<qualifiers>.dts describes your board
hardware in the Devicetree Source (DTS) format (as usual, change plank to
your board's name). If you're new to devicetree, see :ref:devicetree-intro.
In general, :file:plank_<qualifiers>.dts should look like this:
.. code-block:: devicetree
/dts-v1/; #include <your_soc_vendor/your_soc.dtsi>
/ { model = "A human readable name"; compatible = "yourcompany,plank";
chosen {
zephyr,console = &your_uart_console;
zephyr,sram = &your_memory_node;
/* other chosen settings for your hardware */
};
/*
* Your board-specific hardware: buttons, LEDs, sensors, etc.
*/
leds {
compatible = "gpio-leds";
led0: led_0 {
gpios = < /* GPIO your LED is hooked up to */ >;
label = "LED 0";
};
/* ... other LEDs ... */
};
buttons {
compatible = "gpio-keys";
/* ... your button definitions ... */
};
/* These aliases are provided for compatibility with samples */
aliases {
led0 = &led0; /* now you support the blinky sample! */
/* other aliases go here */
};
};
&some_peripheral_you_want_to_enable { /* like a GPIO or SPI controller */ status = "okay"; };
&another_peripheral_you_want { status = "okay"; };
In the case a board has only a single SoC, without any board variants then the dts file can be
named :file:<plank>.dts instead, however this is not recommended due to the file silently be
unused if a variant or other SoC is added to the board.
If you're in a hurry, simple hardware can usually be supported by copy/paste followed by trial and error. If you want to understand details, you will need to read the rest of the devicetree documentation and the devicetree specification.
.. _dt_k6x_example:
.. Give the filenames instead of the full paths below, as it's easier to read. The cramped 'foo.dts<path>' style avoids extra spaces before commas.
This section contains concrete examples related to writing your board's devicetree.
The FRDM-K64F and Hexiwear K64 board devicetrees are defined in
:zephyr_file:frdm_k64fs.dts <boards/nxp/frdm_k64f/frdm_k64f.dts> and
:zephyr_file:hexiwear_k64.dts <boards/mikroe/hexiwear/hexiwear_mk64f12.dts>
respectively. Both boards have NXP SoCs from the same Kinetis SoC family, the
K6X.
Common devicetree definitions for K6X are stored in :zephyr_file:nxp_k6x.dtsi <dts/arm/nxp/kinetis/nxp_k6x.dtsi>, which is included by both board
:file:.dts files. :zephyr_file:nxp_k6x.dtsi<dts/arm/nxp/kinetis/nxp_k6x.dtsi>
in turn includes
:zephyr_file:armv7-m.dtsi<dts/arm/armv7-m.dtsi>, which has common definitions
for Arm v7-M cores.
Since :zephyr_file:nxp_k6x.dtsi<dts/arm/nxp/kinetis/nxp_k6x.dtsi> is meant to be
generic across K6X-based boards, it leaves many devices disabled by default
using status properties. For example, there is a CAN controller defined as
follows (with unimportant parts skipped):
.. code-block:: devicetree
can0: can@40024000 { ... status = "disabled"; ... };
It is up to the board :file:.dts or application overlay files to enable these
devices as desired, by setting status = "okay". The board :file:.dts
files are also responsible for any board-specific configuration of the device,
such as adding nodes for on-board sensors, LEDs, buttons, etc.
For example, FRDM-K64 (but not Hexiwear K64) :file:.dts enables the CAN
controller and sets the bus speed:
.. code-block:: devicetree
&can0 { status = "okay"; };
The &can0 { ... }; syntax adds/overrides properties on the node with label
can0, i.e. the can@4002400 node defined in the :file:.dtsi file.
Other examples of board-specific customization is pointing properties in
aliases and chosen to the right nodes (see :ref:dt-alias-chosen), and
making GPIO/pinmux assignments.
.. _board_kconfig_files:
Write Kconfig files
Zephyr uses the Kconfig language to configure software features. Your board needs to provide some Kconfig settings before you can compile a Zephyr application for it.
Setting Kconfig configuration values is documented in detail in
:ref:setting_configuration_values.
There is one mandatory Kconfig file in the board directory, and several optional
files for a board named plank:
.. code-block:: none
boards/<vendor>/plank ├── Kconfig ├── Kconfig.plank ├── Kconfig.defconfig └── plank_<qualifiers>_defconfig
:file:Kconfig.plank
A shared Kconfig file which can be sourced both in Zephyr Kconfig and sysbuild
Kconfig trees.
This file selects the SoC in the Kconfig tree and potential other SoC related Kconfig settings. This file must not select anything outside the reusable Kconfig board and SoC trees.
A :file:Kconfig.plank may look like this:
.. code-block:: kconfig
config BOARD_PLANK
select SOC_SOC1
The Kconfig symbols :samp:BOARD_{board} and
:samp:BOARD_{normalized_board_target} are constructed by the build
system, therefore no type shall be defined in above code snippet.
:file:Kconfig
Included by :zephyr_file:boards/Kconfig.
This file can add Kconfig settings which are specific to the current board.
Not all boards have a :file:Kconfig file.
A board specific setting should be defining a custom setting and usually with a prompt, like this:
.. code-block:: kconfig
config BOARD_FEATURE
bool "Board specific feature"
If the setting name is identical to an existing Kconfig setting in Zephyr and
only modifies the default value of said setting, then
:file:Kconfig.defconfig should be used instead.
:file:Kconfig.defconfig
Board-specific default values for Kconfig options.
Not all boards have a :file:Kconfig.defconfig file.
The entire file should be inside an if BOARD_PLANK / endif pair of
lines, like this:
.. code-block:: kconfig
if BOARD_PLANK
config FOO
default y
if NETWORKING
config SOC_ETHERNET_DRIVER
default y
endif # NETWORKING
endif # BOARD_PLANK
:file:plank_<qualifiers>_defconfig (or :file:plank_defconfig in limited circumstances)
A Kconfig fragment that is merged as-is into the final build directory
:file:.config whenever an application is compiled for your board.
:file:plank_defconfig can only be used with boards that have no qualifiers, no variants and a
single SoC present, though this style of naming is not recommended due to samples/tests or
downstream usage breaking suddenly without warning if a new SoC or board variant/qualifier is
added to an board in upstream Zephyr.
.. note::
Multiple files are not merged and there is no fallback mechanism for files, this means if there
is a board with 2 different SoCs and each one has 2 board variants, a :file:plank_defconfig
file would be wholly unused, for the first qualifier and variant
:file:plank_<soc1>_<variant1>_defconfig will be used, it will not include other file.
The _defconfig should contain mandatory settings for your UART,
console, etc. The results are architecture-specific, but typically look
something like this:
.. code-block:: cfg
CONFIG_GPIO=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
CONFIG_SERIAL=y
:file:plank_x_y_z_defconfig / :file:plank_<qualifiers>_x_y_z_defconfig
A Kconfig fragment that is merged as-is into the final build directory
:file:.config whenever an application is compiled for your board revision
x.y.z.
Build, test, and fix
Now it's time to build and test the application(s) you want to run on your board until you're satisfied.
For example:
.. code-block:: console
west build -b plank samples/hello_world west flash
For west flash to work, see :ref:flash-and-debug-support below. You can
also just flash :file:build/zephyr/zephyr.elf, :file:zephyr.hex, or
:file:zephyr.bin with any other tools you prefer.
.. _porting-general-recommendations:
General recommendations
For consistency and to make it easier for users to build applications which remain board agnostic, please follow these guidelines when porting a board you intend to contribute to Zephyr:
Enable valuable components in Devicetree Devicetree nodes for valuable onboard components (LEDs, buttons, sensors, onboard USB/Ethernet/BLE/Wi-Fi, etc.) must be enabled by default and have correct pin control and driver configuration so that they work out of the box.
Keep subsystems disabled by default (Kconfig) Do not enable subsystems in the board defconfig unless they are strictly required for basic board operation, or are explicitly listed as exceptions in these recommendations.
Configure system clock and tick source Set up a functioning system clock and tick source.
Provide a default console
Use the zephyr,console chosen node to point to the UART controller used for console output.
Boards with built-in debug or a USB-to-UART adapter should set the console to the UART controller connected to that adapter.
USB-only boards without any debug adapter must include the common USB CDC-ACM
:zephyr_file:Kconfig <boards/common/usb/Kconfig.cdc_acm_serial.defconfig> and :zephyr_file:DTS <boards/common/usb/cdc_acm_serial.dtsi> fragments to enable CDC-ACM UART as a default backend
for logging and shell.
Add :ref:shield interface <shield-interfaces> definitions
For boards exposing standard expansion headers, add connector nodes and pin-muxing. Enable only
the peripherals needed for the expected/standard connector functionality.
Configure pins and peripheral instances Map peripherals to the correct pins (e.g., SPI on Arduino SPI pins) and provide default pinmux entries supporting the board's features.
Enable networking interfaces If networking hardware is present, configure default interfaces for each supported technology so that networking samples work out of the box.
Enable GPIO controllers All GPIO ports connected to onboard components or expansion headers should be enabled.
Enable MPU and stack protection
It is recommended to enable the MPU when available (unless memory resources are too limited).
When the MPU is enabled, it is recommended to also enable hardware stack protection
(:kconfig:option:CONFIG_HW_STACK_PROTECTION) to ease debugging by allowing the kernel to detect stack overflows.
.. _flash-and-debug-support:
Flash and debug support
Zephyr supports :ref:west-build-flash-debug via west extension commands.
To add west flash and west debug support for your board, you need to
create a :file:board.cmake file in your board directory. This file's job is
to configure a "runner" for your board. (There's nothing special you need to
do to get west build support for your board.)
"Runners" are Zephyr-specific Python classes that wrap :ref:flash and debug host tools <flash-debug-host-tools> and integrate with west and the zephyr build
system to support west flash and related commands. Each runner supports
flashing, debugging, or both. You need to configure the arguments to these
Python scripts in your :file:board.cmake to support those commands like this
example :file:board.cmake:
.. code-block:: cmake
board_runner_args(jlink "--device=nrf52" "--speed=4000") board_runner_args(pyocd "--target=nrf52" "--frequency=4000000")
include(${ZEPHYR_BASE}/boards/common/nrfutil.board.cmake) include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake)
This example configures the nrfutil, nrfjprog, jlink, and pyocd
runners.
.. warning::
Runners usually have names which match the tools they wrap, so the jlink
runner wraps Segger's J-Link tools, and so on. But the runner command line
options like --speed etc. are specific to the Python scripts.
.. note::
Runners and board configuration should be created without being targeted to
a single operating system if the tool supports multiple operating systems,
nor should it rely upon special system setup/configuration. For example; do
not assume that a user will have prior knowledge/configuration or (if using
Linux) special udev rules installed, do not assume one specific /dev/X
device for all platforms as this will not be compatible with Windows or
macOS, and allow for overriding of the selected device so that multiple
boards can be connected to a single system and flashed/debugged at the
choice of the user.
For more details:
west flash --context to see a list of available runners which support
flashing, and west flash --context -r <RUNNER> to view the specific options
available for an individual runner.west debug --context and west debug --context <RUNNER> to get
the same output for runners which support debugging.west flash --help and west debug --help for top-level options
for flashing and debugging.west-runner for Python APIs.board.cmake files for other boards similar to your own for
more examples.To see what a west flash or west debug command is doing exactly, run it
in verbose mode:
.. code-block:: sh
west --verbose flash west --verbose debug
Verbose mode prints any host tool commands the runner uses.
The order of the include() calls in your :file:board.cmake matters. The
first include sets the default runner if it's not already set. For example,
including nrfjprog.board.cmake first means that nrfjprog is the default
flash runner for this board. Since nrfjprog does not support debugging,
jlink is the default debug runner.
.. _porting_board_revisions:
Multiple board revisions
See :ref:application_board_version for basics on this feature from the user
perspective.
Board revisions are described in the revision entry of the
:file:board.yml.
.. code-block:: yaml
board: revision: format: <major.minor.patch|letter|number|custom> default: <default-revision-value> exact: <true|false> revisions: - name: <revA> - name: <revB>
Zephyr natively supports the following revision formats:
major.minor.patch: match a three digit revision, such as 1.2.3.number: matches integer revisionsletter: matches single letter revisions from A to Z only.. _board_fuzzy_revision_matching:
Fuzzy revision matching is enabled per default.
If the user selects a revision between those available, the closest revision
number that is not larger than the user's choice is used. For example, if the
board plank defines revisions 0.5.0, and 1.5.0 and the user builds
for [email protected], the build system will target revision 0.5.0.
The build system will print this at CMake configuration time:
.. code-block:: console
-- Board: plank, Revision: 0.7.0 (Active: 0.5.0)
This allows you to only create revision configuration files for board revision numbers that introduce incompatible changes.
Similarly for letter revision format, if revisions A, D, and F
are defined and the user builds for plank@E, the build system will target
revision D.
Exact revision matching is enabled when exact: true is specified in the
revision section in :file:board.yml.
When exact is defined then building for [email protected] in the above example
will result in the following error message:
.. code-block:: console
Board revision 0.7.0 not found. Please specify a valid board revision.
When the user builds for board plank@<revision> it is possible to make
adjustments to the board's normal configuration.
As described in the :ref:default_board_configuration and
:ref:board_kconfig_files sections the board default configuration is created
from the files :file:<board>.dts / :file:<board>_<qualifiers>.dts and
:file:<board>_defconfig / :file:<board>_<qualifiers>_defconfig.
When building for a specific board revision, the above files are used as a
starting point and the following board files will be used in addition:
:file:<board>_<qualifiers>_<revision>_defconfig: a specific revision
defconfig which is only used for the board and SOC / variants identified by
<board>_<qualifiers>.
:file:<board>_<revision>_defconfig: a specific revision defconfig which is
used for the board regardless of the SOC / variants.
:file:<board>_<qualifiers>_<revision>.overlay: a specific revision dts
overlay which is only used for the board and SOC / variants identified by
<board>_<qualifiers>.
:file:<board>_<revision>.overlay: a specific revision dts overlay which is
used for the board regardless of the SOC / variants.
This split allows boards with multiple SoCs, multi-core SoCs, or variants to place common revision adjustments which apply to all SoCs and variants in a single file, while still providing the ability to place SoC or variant specific adjustments in a dedicated revision file.
Using the plank board from previous sections, then we could have the following
revision adjustments:
.. code-block:: none
boards/zephyr/plank ├── plank_0_5_0_defconfig # Kconfig adjustment for all plank board qualifiers on revision 0.5.0 ├── plank_0_5_0.overlay # DTS overlay for all plank board qualifiers on revision 0.5.0 └── plank_soc1_foo_1_5_0_defconfig # Kconfig adjustment for plank board when building for soc1 variant foo on revision 1.5.0
Custom revision.cmake files
Some boards may not use board revisions supported natively by Zephyr. For example string revisions.
One reason why Zephyr doesn't support string revisions is that strings can take
many forms and it's not always clear if the given strings are just strings, such
as blue, green, red, etc. or if they provide an order which can be
matched against higher or lower revisions, such as alpha, beta```, gamma``.
Due to the sheer number of possibilities with strings, including the possibility
of doing regex matches internally, then string revisions must be done using
custom revision type.
To indicate to the build system that custom revisions are used, the format
field in the revision section of the :file:board.yml must be written as:
.. code-block:: yaml
board: revision: format: custom
When using custom revisions then a :file:revision.cmake must be created in the
board directory.
The :file:revision.cmake will be included by the build system when building
for the board and it is the responsibility of the file to validate the revision
specified by the user.
The :makevar:BOARD_REVISION variable holds the revision value specified by the
user.
To signal to the build system that it should use a different revision than the
one specified by the user, :file:revision.cmake can set the variable
ACTIVE_BOARD_REVISION to the revision to use instead. The corresponding
Kconfig files and devicetree overlays must be named
:file:<board>_<ACTIVE_BOARD_REVISION>_defconfig and
:file:<board>_<ACTIVE_BOARD_REVISION>.overlay.
.. _contributing-your-board:
Contributing your board
If you want to contribute your board to Zephyr, first -- thanks!
There are some extra things you'll need to do:
#. Make sure you've followed all the :ref:porting-general-recommendations.
They are requirements for boards included with Zephyr.
#. Add documentation for your board using the template file
:zephyr_file:doc/templates/board.tmpl. See :ref:zephyr_doc for
information on how to build your documentation before submitting
your pull request.
#. Prepare a pull request adding your board which follows the
:ref:contribute_guidelines.
.. _extend-board:
Board extensions
The board hardware model in Zephyr allows you to extend an existing board with new board variants. Such board extensions can be done in your custom repository and thus outside of the Zephyr repository.
Extending an existing board with an extra variant allows you to adjust an existing board and thereby during build to select building for the existing, unmodified board, or the new variant.
To extend an existing board, first create a :file:board.yml in your extended
board. Make sure to use the directory structure described in
:ref:create-your-board-directory.
The skeleton of the board YAML file for extending a board is:
.. code-block:: yaml
board: extend: <existing-board-name> variants: - name: <new-variant> qualifier: <existing-qualifier>
When extending a board, your board directory should look like:
.. code-block:: none
boards/<VENDOR>/plank ├── board.yml ├── plank_<new-qualifiers>defconfig └── plank<new-qualifiers>.dts
Replace plank with the real name of the board you extend.
In some cases you might want to also adjust additional settings, like the
:file:Kconfig.defconfig or :file:Kconfig.{board}.
Therefore it is also possible to provide the following in addition when
extending a board.
.. code-block:: none
boards/<VENDOR>/plank ├── board.cmake ├── Kconfig ├── Kconfig.plank ├── Kconfig.defconfig └── plank_<new-qualifiers>.yaml