1.. _board_porting_guide:
2
3Board Porting Guide
4###################
5
6To add Zephyr support for a new :term:`board`, you at least need a *board
7directory* with various files in it. Files in the board directory inherit
8support for at least one SoC and all of its features. Therefore, Zephyr must
9support your :term:`SoC` as well.
10
11Boards, SoCs, etc.
12******************
13
14Zephyr's hardware support hierarchy has these layers, from most to least
15specific:
16
17- Board: a particular CPU instance and its peripherals in a concrete hardware
18  specification
19- SoC: the exact system on a chip the board's CPU is part of
20- SoC series: a smaller group of tightly related SoCs
21- SoC family: a wider group of SoCs with similar characteristics
22- CPU core: a particular CPU in an architecture
23- Architecture: an instruction set architecture
24
25You can visualize the hierarchy like this:
26
27.. figure:: board/hierarchy.png
28   :width: 500px
29   :align: center
30   :alt: Configuration Hierarchy
31
32   Configuration Hierarchy
33
34Here are some examples. Notice how the SoC series and family levels are
35not always used.
36
37.. list-table::
38   :header-rows: 1
39
40   * - Board
41     - SoC
42     - SoC series
43     - SoC family
44     - CPU core
45     - Architecture
46   * - :ref:`nrf52dk_nrf52832 <nrf52dk_nrf52832>`
47     - nRF52832
48     - nRF52
49     - Nordic nRF5
50     - Arm Cortex-M4
51     - Arm
52   * - :ref:`frdm_k64f <frdm_k64f>`
53     - MK64F12
54     - Kinetis K6x
55     - NXP Kinetis
56     - Arm Cortex-M4
57     - Arm
58   * - :ref:`stm32h747i_disco <stm32h747i_disco_board>`
59     - STM32H747XI
60     - STM32H7
61     - STMicro STM32
62     - Arm Cortex-M7
63     - Arm
64   * - :ref:`rv32m1_vega_ri5cy <rv32m1_vega>`
65     - RV32M1
66     - (Not used)
67     - (Not used)
68     - RI5CY
69     - RISC-V
70
71Make sure your SoC is supported
72*******************************
73
74Start by making sure your SoC is supported by Zephyr. If it is, it's time to
75:ref:`create-your-board-directory`. If you don't know, try:
76
77- checking :ref:`boards` for names that look relevant, and reading individual
78  board documentation to find out for sure.
79- asking your SoC vendor
80
81If you need to add SoC, CPU core, or even architecture support, this is the
82wrong page, but here is some general advice.
83
84Architecture
85============
86
87See :ref:`architecture_porting_guide`.
88
89CPU Core
90========
91
92CPU core support files go in ``core`` subdirectories under :zephyr_file:`arch`,
93e.g. :zephyr_file:`arch/x86/core`.
94
95See :ref:`gs_toolchain` for information about toolchains (compiler, linker,
96etc.) supported by Zephyr. If you need to support a new toolchain,
97:ref:`build_overview` is a good place to start learning about the build system.
98Please reach out to the community if you are looking for advice or want to
99collaborate on toolchain support.
100
101SoC
102===
103
104Zephyr SoC support files are in architecture-specific subdirectories of
105:zephyr_file:`soc`. They are generally grouped by SoC family.
106
107When adding a new SoC family or series for a vendor that already has SoC
108support within Zephyr, please try to extract common functionality into shared
109files to avoid duplication. If there is no support for your vendor yet, you can
110add it in a new directory ``zephyr/soc/<YOUR-ARCH>/<YOUR-SOC>``; please use
111self-explanatory directory names.
112
113.. _create-your-board-directory:
114
115Create your board directory
116***************************
117
118Once you've found an existing board that uses your SoC, you can usually start
119by copy/pasting its board directory and changing its contents for your
120hardware.
121
122You need to give your board a unique name. Run ``west boards`` for a list of
123names that are already taken, and pick something new. Let's say your board is
124called ``plank`` (please don't actually use that name).
125
126Start by creating the board directory ``zephyr/boards/<ARCH>/plank``, where
127``<ARCH>`` is your SoC's architecture subdirectory. (You don't have to put your
128board directory in the zephyr repository, but it's the easiest way to get
129started. See :ref:`custom_board_definition` for documentation on moving your
130board directory to a separate repository once it's working.)
131
132.. note::
133
134  The board directory name does not need to match the name of the board.
135  Multiple boards can even defined be in one directory.
136  For example, for boards with multi-core SoC, a logical board might be created
137  for each core following the naming scheme `<board>_<soc-core>`, with definitions
138  for all of these different boards defined inside the same directory. This and
139  similar schemes are common for upstream vendor boards.
140
141Your board directory should look like this:
142
143.. code-block:: none
144
145   boards/<ARCH>/plank
146   ├── board.cmake
147   ├── CMakeLists.txt
148   ├── doc
149   │   ├── plank.png
150   │   └── index.rst
151   ├── Kconfig.board
152   ├── Kconfig.defconfig
153   ├── plank_defconfig
154   ├── plank.dts
155   └── plank.yaml
156
157Replace ``plank`` with your board's name, of course.
158
159The mandatory files are:
160
161#. :file:`plank.dts`: a hardware description in :ref:`devicetree
162   <dt-guide>` format. This declares your SoC, connectors, and any
163   other hardware components such as LEDs, buttons, sensors, or communication
164   peripherals (USB, BLE controller, etc).
165
166#. :file:`Kconfig.board`, :file:`Kconfig.defconfig`, :file:`plank_defconfig`:
167   software configuration in :ref:`kconfig` formats. This provides default
168   settings for software features and peripheral drivers.
169
170The optional files are:
171
172- :file:`board.cmake`: used for :ref:`flash-and-debug-support`
173- :file:`CMakeLists.txt`: if you need to add additional source files to
174  your build.
175- :file:`doc/index.rst`, :file:`doc/plank.png`: documentation for and a picture
176  of your board. You only need this if you're :ref:`contributing-your-board` to
177  Zephyr.
178- :file:`plank.yaml`: a YAML file with miscellaneous metadata used by the
179  :ref:`twister_script`.
180
181.. _default_board_configuration:
182
183Write your devicetree
184*********************
185
186The devicetree file :file:`boards/<ARCH>/plank/plank.dts` describes your board
187hardware in the Devicetree Source (DTS) format (as usual, change ``plank`` to
188your board's name). If you're new to devicetree, see :ref:`devicetree-intro`.
189
190In general, :file:`plank.dts` should look like this:
191
192.. code-block:: devicetree
193
194   /dts-v1/;
195   #include <your_soc_vendor/your_soc.dtsi>
196
197   / {
198   	model = "A human readable name";
199   	compatible = "yourcompany,plank";
200
201   	chosen {
202   		zephyr,console = &your_uart_console;
203   		zephyr,sram = &your_memory_node;
204   		/* other chosen settings  for your hardware */
205   	};
206
207   	/*
208   	 * Your board-specific hardware: buttons, LEDs, sensors, etc.
209   	 */
210
211   	leds {
212   		compatible = "gpio-leds";
213   		led0: led_0 {
214   			gpios = < /* GPIO your LED is hooked up to */ >;
215   			label = "LED 0";
216   		};
217   		/* ... other LEDs ... */
218   	};
219
220   	buttons {
221   		compatible = "gpio-keys";
222   		/* ... your button definitions ... */
223   	};
224
225   	/* These aliases are provided for compatibility with samples */
226   	aliases {
227   		led0 = &led0; /* now you support the blinky sample! */
228   		/* other aliases go here */
229   	};
230   };
231
232   &some_peripheral_you_want_to_enable { /* like a GPIO or SPI controller */
233   	status = "okay";
234   };
235
236   &another_peripheral_you_want {
237   	status = "okay";
238   };
239
240If you're in a hurry, simple hardware can usually be supported by copy/paste
241followed by trial and error. If you want to understand details, you will need
242to read the rest of the devicetree documentation and the devicetree
243specification.
244
245.. _dt_k6x_example:
246
247Example: FRDM-K64F and Hexiwear K64
248===================================
249
250.. Give the filenames instead of the full paths below, as it's easier to read.
251   The cramped 'foo.dts<path>' style avoids extra spaces before commas.
252
253This section contains concrete examples related to writing your board's
254devicetree.
255
256The FRDM-K64F and Hexiwear K64 board devicetrees are defined in
257:zephyr_file:`frdm_k64fs.dts <boards/arm/frdm_k64f/frdm_k64f.dts>` and
258:zephyr_file:`hexiwear_k64.dts <boards/arm/hexiwear_k64/hexiwear_k64.dts>`
259respectively. Both boards have NXP SoCs from the same Kinetis SoC family, the
260K6X.
261
262Common devicetree definitions for K6X are stored in :zephyr_file:`nxp_k6x.dtsi
263<dts/arm/nxp/nxp_k6x.dtsi>`, which is included by both board :file:`.dts`
264files. :zephyr_file:`nxp_k6x.dtsi<dts/arm/nxp/nxp_k6x.dtsi>` in turn includes
265:zephyr_file:`armv7-m.dtsi<dts/arm/armv7-m.dtsi>`, which has common definitions
266for Arm v7-M cores.
267
268Since :zephyr_file:`nxp_k6x.dtsi<dts/arm/nxp/nxp_k6x.dtsi>` is meant to be
269generic across K6X-based boards, it leaves many devices disabled by default
270using ``status`` properties.  For example, there is a CAN controller defined as
271follows (with unimportant parts skipped):
272
273.. code-block:: devicetree
274
275   can0: can@40024000 {
276	...
277	status = "disabled";
278	...
279   };
280
281It is up to the board :file:`.dts` or application overlay files to enable these
282devices as desired, by setting ``status = "okay"``. The board :file:`.dts`
283files are also responsible for any board-specific configuration of the device,
284such as adding nodes for on-board sensors, LEDs, buttons, etc.
285
286For example, FRDM-K64 (but not Hexiwear K64) :file:`.dts` enables the CAN
287controller and sets the bus speed:
288
289.. code-block:: devicetree
290
291   &can0 {
292	status = "okay";
293	bus-speed = <125000>;
294   };
295
296The ``&can0 { ... };`` syntax adds/overrides properties on the node with label
297``can0``, i.e. the ``can@4002400`` node defined in the :file:`.dtsi` file.
298
299Other examples of board-specific customization is pointing properties in
300``aliases`` and ``chosen`` to the right nodes (see :ref:`dt-alias-chosen`), and
301making GPIO/pinmux assignments.
302
303Write Kconfig files
304*******************
305
306Zephyr uses the Kconfig language to configure software features. Your board
307needs to provide some Kconfig settings before you can compile a Zephyr
308application for it.
309
310Setting Kconfig configuration values is documented in detail in
311:ref:`setting_configuration_values`.
312
313There are three mandatory Kconfig files in the board directory for a board
314named ``plank``:
315
316.. code-block:: none
317
318   boards/<ARCH>/plank
319   ├── Kconfig.board
320   ├── Kconfig.defconfig
321   └── plank_defconfig
322
323:file:`Kconfig.board`
324  Included by :zephyr_file:`boards/Kconfig` to include your board
325  in the list of options.
326
327  This should at least contain a definition for a ``BOARD_PLANK`` option,
328  which looks something like this:
329
330  .. code-block:: kconfig
331
332     config BOARD_PLANK
333     	bool "Plank board"
334     	depends on SOC_SERIES_YOUR_SOC_SERIES_HERE
335     	select SOC_PART_NUMBER_ABCDEFGH
336
337:file:`Kconfig.defconfig`
338  Board-specific default values for Kconfig options.
339
340  The entire file should be inside an ``if BOARD_PLANK`` / ``endif`` pair of
341  lines, like this:
342
343  .. code-block:: kconfig
344
345     if BOARD_PLANK
346
347     # Always set CONFIG_BOARD here. This isn't meant to be customized,
348     # but is set as a "default" due to Kconfig language restrictions.
349     config BOARD
350     	default "plank"
351
352     # Other options you want enabled by default go next. Examples:
353
354     config FOO
355     	default y
356
357     if NETWORKING
358     config SOC_ETHERNET_DRIVER
359     	default y
360     endif # NETWORKING
361
362     endif # BOARD_PLANK
363
364:file:`plank_defconfig`
365  A Kconfig fragment that is merged as-is into the final build directory
366  :file:`.config` whenever an application is compiled for your board.
367
368  You should at least select your board's SOC and do any mandatory settings for
369  your system clock, console, etc. The results are architecture-specific, but
370  typically look something like this:
371
372  .. code-block:: cfg
373
374     CONFIG_SOC_${VENDOR_XYZ3000}=y                # select your SoC
375     CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=120000000  # set up your clock, etc
376     CONFIG_SERIAL=y
377
378:file:`plank_x_y_z.conf`
379  A Kconfig fragment that is merged as-is into the final build directory
380  :file:`.config` whenever an application is compiled for your board revision
381  ``x.y.z``.
382
383Build, test, and fix
384********************
385
386Now it's time to build and test the application(s) you want to run on your
387board until you're satisfied.
388
389For example:
390
391.. code-block:: console
392
393   west build -b plank samples/hello_world
394   west flash
395
396For ``west flash`` to work, see :ref:`flash-and-debug-support` below. You can
397also just flash :file:`build/zephyr/zephyr.elf`, :file:`zephyr.hex`, or
398:file:`zephyr.bin` with any other tools you prefer.
399
400.. _porting-general-recommendations:
401
402General recommendations
403***********************
404
405For consistency and to make it easier for users to build generic applications
406that are not board specific for your board, please follow these guidelines
407while porting.
408
409- Unless explicitly recommended otherwise by this section, leave peripherals
410  and their drivers disabled by default.
411
412- Configure and enable a system clock, along with a tick source.
413
414- Provide pin and driver configuration that matches the board's valuable
415  components such as sensors, buttons or LEDs, and communication interfaces
416  such as USB, Ethernet connector, or Bluetooth/Wi-Fi chip.
417
418- If your board uses a well-known connector standard (like Arduino, Mikrobus,
419  Grove, or 96Boards connectors), add connector nodes to your DTS and configure
420  pin muxes accordingly.
421
422- Configure components that enable the use of these pins, such as
423  configuring an SPI instance to use the usual Arduino SPI pins.
424
425- If available, configure and enable a serial output for the console
426  using the ``zephyr,console`` chosen node in the devicetree.
427
428- If your board supports networking, configure a default interface.
429
430- Enable all GPIO ports connected to peripherals or expansion connectors.
431
432- If available, enable pinmux and interrupt controller drivers.
433
434- It is recommended to enable the MPU by default, if there is support for it
435  in hardware. For boards with limited memory resources it is acceptable to
436  disable it. When the MPU is enabled, it is recommended to also enable
437  hardware stack protection (CONFIG_HW_STACK_PROTECTION=y) and, thus, allow the
438  kernel to detect stack overflows when the system is running in privileged
439  mode.
440
441.. _flash-and-debug-support:
442
443Flash and debug support
444***********************
445
446Zephyr supports :ref:`west-build-flash-debug` via west extension commands.
447
448To add ``west flash`` and ``west debug`` support for your board, you need to
449create a :file:`board.cmake` file in your board directory. This file's job is
450to configure a "runner" for your board. (There's nothing special you need to
451do to get ``west build`` support for your board.)
452
453"Runners" are Zephyr-specific Python classes that wrap :ref:`flash and debug
454host tools <flash-debug-host-tools>` and integrate with west and the zephyr build
455system to support ``west flash`` and related commands. Each runner supports
456flashing, debugging, or both. You need to configure the arguments to these
457Python scripts in your :file:`board.cmake` to support those commands like this
458example :file:`board.cmake`:
459
460.. code-block:: cmake
461
462   board_runner_args(jlink "--device=nrf52" "--speed=4000")
463   board_runner_args(pyocd "--target=nrf52" "--frequency=4000000")
464
465   include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
466   include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
467   include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake)
468
469This example configures the ``nrfjprog``, ``jlink``, and ``pyocd`` runners.
470
471.. warning::
472
473   Runners usually have names which match the tools they wrap, so the ``jlink``
474   runner wraps Segger's J-Link tools, and so on. But the runner command line
475   options like ``--speed`` etc. are specific to the Python scripts.
476
477.. note::
478
479   Runners and board configuration should be created without being targeted to
480   a single operating system if the tool supports multiple operating systems,
481   nor should it rely upon special system setup/configuration. For example; do
482   not assume that a user will have prior knowledge/configuration or (if using
483   Linux) special udev rules installed, do not assume one specific ``/dev/X``
484   device for all platforms as this will not be compatible with Windows or
485   macOS, and allow for overriding of the selected device so that multiple
486   boards can be connected to a single system and flashed/debugged at the
487   choice of the user.
488
489For more details:
490
491- Run ``west flash --context`` to see a list of available runners which support
492  flashing, and ``west flash --context -r <RUNNER>`` to view the specific options
493  available for an individual runner.
494- Run ``west debug --context`` and ``west debug --context <RUNNER>`` to get
495  the same output for runners which support debugging.
496- Run ``west flash --help`` and ``west debug --help`` for top-level options
497  for flashing and debugging.
498- See :ref:`west-runner` for Python APIs.
499- Look for :file:`board.cmake` files for other boards similar to your own for
500  more examples.
501
502To see what a ``west flash`` or ``west debug`` command is doing exactly, run it
503in verbose mode:
504
505.. code-block:: sh
506
507   west --verbose flash
508   west --verbose debug
509
510Verbose mode prints any host tool commands the runner uses.
511
512The order of the ``include()`` calls in your :file:`board.cmake` matters. The
513first ``include`` sets the default runner if it's not already set. For example,
514including ``nrfjprog.board.cmake`` first means that ``nrfjprog`` is the default
515flash runner for this board. Since ``nrfjprog`` does not support debugging,
516``jlink`` is the default debug runner.
517
518.. _porting_board_revisions:
519
520Multiple board revisions
521************************
522
523See :ref:`application_board_version` for basics on this feature from the user
524perspective.
525
526To create a new board revision for the ``plank`` board, create these additional
527files in the board folder:
528
529.. code-block:: none
530
531   boards/<ARCH>/plank
532   ├── plank_<revision>.conf     # optional
533   ├── plank_<revision>.overlay  # optional
534   └── revision.cmake
535
536When the user builds for board ``plank@<revision>``:
537
538- The optional Kconfig settings specified in the file
539  :file:`plank_<revision>.conf` will be merged into the board's default Kconfig
540  configuration.
541
542- The optional devicetree overlay :file:`plank_<revision>.overlay` will be added
543  to the common :file:`plank.dts` devicetree file
544
545- The :file:`revision.cmake` file controls how the Zephyr build system matches
546  the ``<board>@<revision>`` string specified by the user when building an
547  application for the board.
548
549Currently, ``<revision>`` can be either a numeric ``MAJOR.MINOR.PATCH`` style
550revision like ``1.5.0``, an integer number like ``1``, or single letter like
551``A``, ``B``, etc. Zephyr provides a CMake board extension function,
552``board_check_revision()``, to make it easy to match either style from
553:file:`revision.cmake`.
554
555Valid board revisions may be specified as arguments to the
556``board_check_revision()`` function, like:
557
558.. code-block:: cmake
559
560   board_check_revision(FORMAT MAJOR.MINOR.PATCH
561                        VALID_REVISIONS 0.1.0 0.3.0 ...
562   )
563
564.. note::
565   ``VALID_REVISIONS`` can be omitted if all valid revisions have specific
566   Kconfig fragments, such as ``<board>_0_1_0.conf``, ``<board>_0_3_0.conf``.
567   This allows you to just place Kconfig revision fragments in the board
568   folder and not have to keep the corresponding ``VALID_REVISIONS`` in sync.
569
570The following sections describe how to support these styles of revision
571numbers.
572
573MAJOR.MINOR.PATCH revisions
574===========================
575
576Let's say you want to add support for revisions ``0.5.0``, ``1.0.0``, and
577``1.5.0`` of the ``plank`` board with both Kconfig fragments and devicetree
578overlays. Create :file:`revision.cmake` with
579``board_check_revision(FORMAT MAJOR.MINOR.PATCH)``, and create the following
580additional files in the board directory:
581
582.. code-block:: none
583
584   boards/<ARCH>/plank
585   ├── plank_0_5_0.conf
586   ├── plank_0_5_0.overlay
587   ├── plank_1_0_0.conf
588   ├── plank_1_0_0.overlay
589   ├── plank_1_5_0.conf
590   ├── plank_1_5_0.overlay
591   └── revision.cmake
592
593Notice how the board files have changed periods (".") in the revision number to
594underscores ("_").
595
596Fuzzy revision matching
597-----------------------
598
599To support "fuzzy" ``MAJOR.MINOR.PATCH`` revision matching for the ``plank``
600board, use the following code in :file:`revision.cmake`:
601
602.. code-block:: cmake
603
604   board_check_revision(FORMAT MAJOR.MINOR.PATCH)
605
606If the user selects a revision between those available, the closest revision
607number that is not larger than the user's choice is used. For example, if the
608user builds for ``plank@0.7.0``, the build system will target revision
609``0.5.0``.
610
611The build system will print this at CMake configuration time:
612
613.. code-block:: console
614
615   -- Board: plank, Revision: 0.7.0 (Active: 0.5.0)
616
617This allows you to only create revision configuration files for board revision
618numbers that introduce incompatible changes.
619
620Any revision less than the minimum defined will be treated as an error.
621
622You may use ``0.0.0`` as a minimum revision to build for by creating the file
623:file:`plank_0_0_0.conf` in the board directory. This will be used for any
624revision lower than ``0.5.0``, for example if the user builds for
625``plank@0.1.0``.
626
627Exact revision matching
628-----------------------
629
630Alternatively, the ``EXACT`` keyword can be given to ``board_check_revision()``
631in :file:`revision.cmake` to allow exact matches only, like this:
632
633.. code-block:: cmake
634
635   board_check_revision(FORMAT MAJOR.MINOR.PATCH EXACT)
636
637With this :file:`revision.cmake`, building for ``plank@0.7.0`` in the above
638example will result in the following error message:
639
640.. code-block:: console
641
642   Board revision `0.7.0` not found.  Please specify a valid board revision.
643
644Letter revision matching
645========================
646
647Let's say instead that you need to support revisions ``A``, ``B``, and ``C`` of
648the ``plank`` board. Create the following additional files in the board
649directory:
650
651.. code-block:: none
652
653   boards/<ARCH>/plank
654   ├── plank_A.conf
655   ├── plank_A.overlay
656   ├── plank_B.conf
657   ├── plank_B.overlay
658   ├── plank_C.conf
659   ├── plank_C.overlay
660   └── revision.cmake
661
662And add the following to :file:`revision.cmake`:
663
664.. code-block:: cmake
665
666   board_check_revision(FORMAT LETTER)
667
668Number revision matching
669========================
670
671Let's say instead that you need to support revisions ``1``, ``2``, and ``3`` of
672the ``plank`` board. Create the following additional files in the board
673directory:
674
675.. code-block:: none
676
677   boards/<ARCH>/plank
678   ├── plank_1.conf
679   ├── plank_1.overlay
680   ├── plank_2.conf
681   ├── plank_2.overlay
682   ├── plank_3.conf
683   ├── plank_3.overlay
684   └── revision.cmake
685
686And add the following to :file:`revision.cmake`:
687
688.. code-block:: cmake
689
690   board_check_revision(FORMAT NUMBER)
691
692board_check_revision() details
693==============================
694
695.. code-block:: cmake
696
697   board_check_revision(FORMAT <LETTER | NUMBER | MAJOR.MINOR.PATCH>
698                        [OPTIONAL EXACT]
699                        [DEFAULT_REVISION <revision>]
700                        [HIGHEST_REVISION <revision>]
701                        [VALID_REVISIONS <revision> [<revision> ...]]
702   )
703
704This function supports the following arguments:
705
706* ``FORMAT LETTER``: matches single letter revisions from ``A`` to ``Z`` only
707* ``FORMAT NUMBER``: matches integer revisions
708* ``FORMAT MAJOR.MINOR.PATCH``: matches exactly three digits. The command line
709  allows for loose typing, that is ``-DBOARD=<board>@1`` and
710  ``-DBOARD=<board>@1.0`` will be handled as ``-DBOARD=<board>@1.0.0``.
711  Kconfig fragment and devicetree overlay files must use full numbering to avoid
712  ambiguity, so only :file:`<board>_1_0_0.conf` and
713  :file:`<board>_1_0_0.overlay` are allowed.
714
715* ``OPTIONAL``: if given, a revision is not required to be specified.
716  If the revision is not supplied, the base board is used with no overlays.
717  Can be combined with ``EXACT``, in which case providing the revision is
718  optional, but if given the ``EXACT`` rules apply. Mutually exclusive with
719  ``DEFAULT_REVISION``.
720
721* ``EXACT``: if given, the revision is required to be an exact match.
722  Otherwise, the closest matching revision not greater than the user's choice
723  will be selected.
724
725* ``DEFAULT_REVISION <revision>``: if given, ``<revision>`` is the default
726  revision to use when user has not selected a revision number. If not given,
727  the build system prints an error when the user does not specify a board
728  revision.
729
730* ``HIGHEST_REVISION``: if given, specifies the highest valid revision for a
731  board. This can be used to ensure that a newer board cannot be used with an
732  older Zephyr. For example, if the current board directory supports revisions
733  0.x.0-0.99.99 and 1.0.0-1.99.99, and it is expected that the implementation
734  will not work with board revision 2.0.0, then giving ``HIGHEST_REVISION
735  1.99.99`` causes an error if the user builds using ``<board>@2.0.0``.
736
737* ``VALID_REVISIONS``: if given, specifies a list of revisions that are valid
738  for this board. If this argument is not given, then each Kconfig fragment of
739  the form ``<board>_<revision>.conf`` in the board folder will be used as a
740  valid revision for the board.
741
742.. _porting_custom_board_revisions:
743
744Custom revision.cmake files
745***************************
746
747Some boards may not use board revisions supported by
748``board_check_revision()``. To support revisions of any type, the file
749:file:`revision.cmake` can implement custom revision matching without calling
750``board_check_revision()``.
751
752To signal to the build system that it should use a different revision than the
753one specified by the user, :file:`revision.cmake` can set the variable
754``ACTIVE_BOARD_REVISION`` to the revision to use instead. The corresponding
755Kconfig files and devicetree overlays must be named
756:file:`<board>_<ACTIVE_BOARD_REVISION>.conf` and
757:file:`<board>_<ACTIVE_BOARD_REVISION>.overlay`.
758
759For example, if the user builds for ``plank@zero``, :file:`revision.cmake` can
760set ``ACTIVE_BOARD_REVISION`` to ``one`` to use the files
761:file:`plank_one.conf` and :file:`plank_one.overlay`.
762
763.. _contributing-your-board:
764
765Contributing your board
766***********************
767
768If you want to contribute your board to Zephyr, first -- thanks!
769
770There are some extra things you'll need to do:
771
772#. Make sure you've followed all the :ref:`porting-general-recommendations`.
773   They are requirements for boards included with Zephyr.
774
775#. Add documentation for your board using the template file
776   :zephyr_file:`doc/templates/board.tmpl`. See :ref:`zephyr_doc` for
777   information on how to build your documentation before submitting
778   your pull request.
779
780#. Prepare a pull request adding your board which follows the
781   :ref:`contribute_guidelines`.
782
783Board extensions
784****************
785
786Boards already supported by Zephyr can be extended by downstream users, such as
787``example-application`` or vendor SDKs. In some situations, certain hardware
788description or :ref:`choices <devicetree-chosen-nodes>` can not be added in the
789upstream Zephyr repository, but they can be in a downstream project, where
790custom bindings or driver classes can also be created. This feature may also be
791useful in development phases, when the board skeleton lives upstream, but other
792features are developed in a downstream module.
793
794Board extensions are board fragments that can be present in an out-of-tree board
795root folder, under ``${BOARD_ROOT}/boards/extensions``. Here is an example
796structure of an extension for the ``plank`` board and its revisions:
797
798.. code-block:: none
799
800   boards/extensions/plank
801   ├── plank.conf                # optional
802   ├── plank_<revision>.conf     # optional
803   ├── plank.overlay             # optional
804   └── plank_<revision>.overlay  # optional
805
806A board extension directory must follow the naming structure of the original
807board it extends. It may contain Kconfig fragments and/or devicetree overlays.
808Extensions are, by default, automatically loaded and applied on top of board
809files, before anything else. There is no guarantee on which order extensions are
810applied, in case multiple exist. This feature can be disabled by passing
811``-DBOARD_EXTENSIONS=OFF`` when building.
812
813Note that board extensions need to follow the
814:ref:`same guidelines <porting-general-recommendations>` as regular boards. For
815example, it is wrong to enable extra peripherals or subsystems in a board
816extension.
817
818.. warning::
819
820   Board extensions are not allowed in any module referenced in Zephyr's
821   ``west.yml`` manifest file. Any board changes are required to be submitted to
822   the main Zephyr repository.
823