.. _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.

Boards, SoCs, etc.
******************

Zephyr's hardware support hierarchy has these layers, from most to least
specific:

- Board: a particular CPU instance and its peripherals in a concrete hardware
  specification
- SoC: the exact system on a chip the board's CPU is part of
- SoC series: a smaller group of tightly related SoCs
- SoC family: a wider group of SoCs with similar characteristics
- CPU core: a particular CPU in an architecture
- Architecture: an instruction set architecture

You can visualize the hierarchy like this:

.. figure:: board/hierarchy.png
   :width: 500px
   :align: center
   :alt: Configuration Hierarchy

   Configuration Hierarchy

Here are some examples. Notice how the SoC series and family levels are
not always used.

.. list-table::
   :header-rows: 1

   * - Board
     - SoC
     - SoC series
     - SoC family
     - CPU core
     - Architecture
   * - :ref:`nrf52dk_nrf52832 <nrf52dk_nrf52832>`
     - nRF52832
     - nRF52
     - Nordic nRF5
     - Arm Cortex-M4
     - Arm
   * - :ref:`frdm_k64f <frdm_k64f>`
     - MK64F12
     - Kinetis K6x
     - NXP Kinetis
     - Arm Cortex-M4
     - Arm
   * - :ref:`stm32h747i_disco <stm32h747i_disco_board>`
     - STM32H747XI
     - STM32H7
     - STMicro STM32
     - Arm Cortex-M7
     - Arm
   * - :ref:`rv32m1_vega_ri5cy <rv32m1_vega>`
     - RV32M1
     - (Not used)
     - (Not used)
     - RI5CY
     - RISC-V

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:

- checking :ref:`boards` for names that look relevant, and reading individual
  board documentation to find out for sure.
- asking your SoC vendor

If you need to add SoC, CPU core, or even architecture support, this is the
wrong page, but here is some general advice.

Architecture
============

See :ref:`architecture_porting_guide`.

CPU Core
========

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.

SoC
===

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/<YOUR-ARCH>/<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/<ARCH>/plank``, where
``<ARCH>`` is your SoC's architecture 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::

  The board directory name does not need to match the name of the board.
  Multiple boards can even defined be in one directory.
  For example, for boards with multi-core SoC, a logical board might be created
  for each core following the naming scheme `<board>_<soc-core>`, with definitions
  for all of these different boards defined inside the same directory. This and
  similar schemes are common for upstream vendor boards.

Your board directory should look like this:

.. code-block:: none

   boards/<ARCH>/plank
   ├── board.cmake
   ├── CMakeLists.txt
   ├── doc
   │   ├── plank.png
   │   └── index.rst
   ├── Kconfig.board
   ├── Kconfig.defconfig
   ├── plank_defconfig
   ├── plank.dts
   └── plank.yaml

Replace ``plank`` with your board's name, of course.

The mandatory files are:

#. :file:`plank.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, BLE controller, etc).

#. :file:`Kconfig.board`, :file:`Kconfig.defconfig`, :file:`plank_defconfig`:
   software configuration in :ref:`kconfig` formats. This provides default
   settings for software features and peripheral drivers.

The optional files are:

- :file:`board.cmake`: used for :ref:`flash-and-debug-support`
- :file:`CMakeLists.txt`: if you need to add additional source files to
  your build.
- :file:`doc/index.rst`, :file:`doc/plank.png`: documentation for and a picture
  of your board. You only need this if you're :ref:`contributing-your-board` to
  Zephyr.
- :file:`plank.yaml`: a YAML file with miscellaneous metadata used by the
  :ref:`twister_script`.

.. _default_board_configuration:

Write your devicetree
*********************

The devicetree file :file:`boards/<ARCH>/plank/plank.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.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";
   };

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.

Board extensions
****************

Board extensions are board fragments that can be present in a board root
folder, under ``${BOARD_ROOT}/boards/extensions``. The extension folder must
follow the naming structure of the original board to extend. The board extension
directory may contain Kconfig fragments and/or devicetree overlays. Board
extensions are, by default, automatically loaded and applied on top of board
files, before anything else. There is no guarantee on which order extensions are
applied, in case multiple exist. This feature shall be disabled by passing
``-DBOARD_EXTENSIONS=OFF`` when building.

Board extensions are designed for downstream users, for example,
``example-application`` or vendor SDKs. In some situations, certain hardware
description or `choices <devicetree-chosen-nodes>`_ can not be added in the
upstream Zephyr repository, but they can be in a downstream project, where
custom bindings or driver classes can also be created. This feature may also be
useful in development phases, when the board skeleton lives upstream, but other
features are developed in a downstream module.

Note that board extensions need to follow the
:ref:`same guidelines <porting-general-recommendations>` as regular boards. For
example, it is wrong to enable extra peripherals or subsystems in a board
extension.

.. warning::

   Board extensions are not allowed in any module referenced in Zephyr's
   ``west.yml`` manifest file. Any board changes are required to be submitted to
   the main Zephyr repository.

.. _dt_k6x_example:

Example: FRDM-K64F and Hexiwear K64
===================================

.. 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/arm/frdm_k64f/frdm_k64f.dts>` and
:zephyr_file:`hexiwear_k64.dts <boards/arm/hexiwear_k64/hexiwear_k64.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/nxp_k6x.dtsi>`, which is included by both board :file:`.dts`
files. :zephyr_file:`nxp_k6x.dtsi<dts/arm/nxp/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/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";
	bus-speed = <125000>;
   };

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.

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 are three mandatory Kconfig files in the board directory for a board
named ``plank``:

.. code-block:: none

   boards/<ARCH>/plank
   ├── Kconfig.board
   ├── Kconfig.defconfig
   └── plank_defconfig

:file:`Kconfig.board`
  Included by :zephyr_file:`boards/Kconfig` to include your board
  in the list of options.

  This should at least contain a definition for a ``BOARD_PLANK`` option,
  which looks something like this:

  .. code-block:: none

     config BOARD_PLANK
     	bool "Plank board"
     	depends on SOC_SERIES_YOUR_SOC_SERIES_HERE
     	select SOC_PART_NUMBER_ABCDEFGH

:file:`Kconfig.defconfig`
  Board-specific default values for Kconfig options.

  The entire file should be inside an ``if BOARD_PLANK`` / ``endif`` pair of
  lines, like this:

  .. code-block:: none

     if BOARD_PLANK

     # Always set CONFIG_BOARD here. This isn't meant to be customized,
     # but is set as a "default" due to Kconfig language restrictions.
     config BOARD
     	default "plank"

     # Other options you want enabled by default go next. Examples:

     config FOO
     	default y

     if NETWORKING
     config SOC_ETHERNET_DRIVER
     	default y
     endif # NETWORKING

     endif # BOARD_PLANK

:file:`plank_defconfig`
  A Kconfig fragment that is merged as-is into the final build directory
  :file:`.config` whenever an application is compiled for your board.

  You should at least select your board's SOC and do any mandatory settings for
  your system clock, console, etc. The results are architecture-specific, but
  typically look something like this:

  .. code-block:: none

     CONFIG_SOC_${VENDOR_XYZ3000}=y                      /* select your SoC */
     CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=120000000   /* set up your clock, etc */
     CONFIG_SERIAL=y

:file:`plank_x_y_z.conf`
  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 generic applications
that are not board specific for your board, please follow these guidelines
while porting.

- Unless explicitly recommended otherwise by this section, leave peripherals
  and their drivers disabled by default.

- Configure and enable a system clock, along with a tick source.

- Provide pin and driver configuration that matches the board's valuable
  components such as sensors, buttons or LEDs, and communication interfaces
  such as USB, Ethernet connector, or Bluetooth/Wi-Fi chip.

- If your board uses a well-known connector standard (like Arduino, Mikrobus,
  Grove, or 96Boards connectors), add connector nodes to your DTS and configure
  pin muxes accordingly.

- Configure components that enable the use of these pins, such as
  configuring an SPI instance to use the usual Arduino SPI pins.

- If available, configure and enable a serial output for the console
  using the ``zephyr,console`` chosen node in the devicetree.

- If your board supports networking, configure a default interface.

- Enable all GPIO ports connected to peripherals or expansion connectors.

- If available, enable pinmux and interrupt controller drivers.

- It is recommended to enable the MPU by default, if there is support for it
  in hardware. For boards with limited memory resources it is acceptable to
  disable it. When the MPU is enabled, it is recommended to also enable
  hardware stack protection (CONFIG_HW_STACK_PROTECTION=y) and, thus, allow the
  kernel to detect stack overflows when the system is running in privileged
  mode.

.. _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/nrfjprog.board.cmake)
   include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
   include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake)

This example configures the ``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:

- Run ``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.
- Run ``west debug --context`` and ``west debug --context <RUNNER>`` to get
  the same output for runners which support debugging.
- Run ``west flash --help`` and ``west debug --help`` for top-level options
  for flashing and debugging.
- See :ref:`west-runner` for Python APIs.
- Look for :file:`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.

To create a new board revision for the ``plank`` board, create these additional
files in the board folder:

.. code-block:: none

   boards/<ARCH>/plank
   ├── plank_<revision>.conf     # optional
   ├── plank_<revision>.overlay  # optional
   └── revision.cmake

When the user builds for board ``plank@<revision>``:

- The optional Kconfig settings specified in the file
  :file:`plank_<revision>.conf` will be merged into the board's default Kconfig
  configuration.

- The optional devicetree overlay :file:`plank_<revision>.overlay` will be added
  to the common :file:`plank.dts` devicetree file

- The :file:`revision.cmake` file controls how the Zephyr build system matches
  the ``<board>@<revision>`` string specified by the user when building an
  application for the board.

Currently, ``<revision>`` can be either a numeric ``MAJOR.MINOR.PATCH`` style
revision like ``1.5.0``, an integer number like ``1``, or single letter like
``A``, ``B``, etc. Zephyr provides a CMake board extension function,
``board_check_revision()``, to make it easy to match either style from
:file:`revision.cmake`.

Valid board revisions may be specified as arguments to the
``board_check_revision()`` function, like:

.. code-block:: cmake

   board_check_revision(FORMAT MAJOR.MINOR.PATCH
                        VALID_REVISIONS 0.1.0 0.3.0 ...
   )

.. note::
   ``VALID_REVISIONS`` can be omitted if all valid revisions have specific
   Kconfig fragments, such as ``<board>_0_1_0.conf``, ``<board>_0_3_0.conf``.
   This allows you to just place Kconfig revision fragments in the board
   folder and not have to keep the corresponding ``VALID_REVISIONS`` in sync.

The following sections describe how to support these styles of revision
numbers.

MAJOR.MINOR.PATCH revisions
===========================

Let's say you want to add support for revisions ``0.5.0``, ``1.0.0``, and
``1.5.0`` of the ``plank`` board with both Kconfig fragments and devicetree
overlays. Create :file:`revision.cmake` with
``board_check_revision(FORMAT MAJOR.MINOR.PATCH)``, and create the following
additional files in the board directory:

.. code-block:: none

   boards/<ARCH>/plank
   ├── plank_0_5_0.conf
   ├── plank_0_5_0.overlay
   ├── plank_1_0_0.conf
   ├── plank_1_0_0.overlay
   ├── plank_1_5_0.conf
   ├── plank_1_5_0.overlay
   └── revision.cmake

Notice how the board files have changed periods (".") in the revision number to
underscores ("_").

Fuzzy revision matching
-----------------------

To support "fuzzy" ``MAJOR.MINOR.PATCH`` revision matching for the ``plank``
board, use the following code in :file:`revision.cmake`:

.. code-block:: cmake

   board_check_revision(FORMAT MAJOR.MINOR.PATCH)

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
user builds for ``plank@0.7.0``, 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.

Any revision less than the minimum defined will be treated as an error.

You may use ``0.0.0`` as a minimum revision to build for by creating the file
:file:`plank_0_0_0.conf` in the board directory. This will be used for any
revision lower than ``0.5.0``, for example if the user builds for
``plank@0.1.0``.

Exact revision matching
-----------------------

Alternatively, the ``EXACT`` keyword can be given to ``board_check_revision()``
in :file:`revision.cmake` to allow exact matches only, like this:

.. code-block:: cmake

   board_check_revision(FORMAT MAJOR.MINOR.PATCH EXACT)

With this :file:`revision.cmake`, building for ``plank@0.7.0`` 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.

Letter revision matching
========================

Let's say instead that you need to support revisions ``A``, ``B``, and ``C`` of
the ``plank`` board. Create the following additional files in the board
directory:

.. code-block:: none

   boards/<ARCH>/plank
   ├── plank_A.conf
   ├── plank_A.overlay
   ├── plank_B.conf
   ├── plank_B.overlay
   ├── plank_C.conf
   ├── plank_C.overlay
   └── revision.cmake

And add the following to :file:`revision.cmake`:

.. code-block:: cmake

   board_check_revision(FORMAT LETTER)

Number revision matching
========================

Let's say instead that you need to support revisions ``1``, ``2``, and ``3`` of
the ``plank`` board. Create the following additional files in the board
directory:

.. code-block:: none

   boards/<ARCH>/plank
   ├── plank_1.conf
   ├── plank_1.overlay
   ├── plank_2.conf
   ├── plank_2.overlay
   ├── plank_3.conf
   ├── plank_3.overlay
   └── revision.cmake

And add the following to :file:`revision.cmake`:

.. code-block:: cmake

   board_check_revision(FORMAT NUMBER)

board_check_revision() details
==============================

.. code-block:: cmake

   board_check_revision(FORMAT <LETTER | NUMBER | MAJOR.MINOR.PATCH>
                        [OPTIONAL EXACT]
                        [DEFAULT_REVISION <revision>]
                        [HIGHEST_REVISION <revision>]
                        [VALID_REVISIONS <revision> [<revision> ...]]
   )

This function supports the following arguments:

* ``FORMAT LETTER``: matches single letter revisions from ``A`` to ``Z`` only
* ``FORMAT NUMBER``: matches integer revisions
* ``FORMAT MAJOR.MINOR.PATCH``: matches exactly three digits. The command line
  allows for loose typing, that is ``-DBOARD=<board>@1`` and
  ``-DBOARD=<board>@1.0`` will be handled as ``-DBOARD=<board>@1.0.0``.
  Kconfig fragment and devicetree overlay files must use full numbering to avoid
  ambiguity, so only :file:`<board>_1_0_0.conf` and
  :file:`<board>_1_0_0.overlay` are allowed.

* ``OPTIONAL``: if given, a revision is not required to be specified.
  If the revision is not supplied, the base board is used with no overlays.
  Can be combined with ``EXACT``, in which case providing the revision is
  optional, but if given the ``EXACT`` rules apply. Mutually exclusive with
  ``DEFAULT_REVISION``.

* ``EXACT``: if given, the revision is required to be an exact match.
  Otherwise, the closest matching revision not greater than the user's choice
  will be selected.

* ``DEFAULT_REVISION <revision>``: if given, ``<revision>`` is the default
  revision to use when user has not selected a revision number. If not given,
  the build system prints an error when the user does not specify a board
  revision.

* ``HIGHEST_REVISION``: if given, specifies the highest valid revision for a
  board. This can be used to ensure that a newer board cannot be used with an
  older Zephyr. For example, if the current board directory supports revisions
  0.x.0-0.99.99 and 1.0.0-1.99.99, and it is expected that the implementation
  will not work with board revision 2.0.0, then giving ``HIGHEST_REVISION
  1.99.99`` causes an error if the user builds using ``<board>@2.0.0``.

* ``VALID_REVISIONS``: if given, specifies a list of revisions that are valid
  for this board. If this argument is not given, then each Kconfig fragment of
  the form ``<board>_<revision>.conf`` in the board folder will be used as a
  valid revision for the board.

.. _porting_custom_board_revisions:

Custom revision.cmake files
***************************

Some boards may not use board revisions supported by
``board_check_revision()``. To support revisions of any type, the file
:file:`revision.cmake` can implement custom revision matching without calling
``board_check_revision()``.

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>.conf` and
:file:`<board>_<ACTIVE_BOARD_REVISION>.overlay`.

For example, if the user builds for ``plank@zero``, :file:`revision.cmake` can
set ``ACTIVE_BOARD_REVISION`` to ``one`` to use the files
:file:`plank_one.conf` and :file:`plank_one.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`.
