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
11.. _hw_model_v2:
12
13Transition to the current hardware model
14****************************************
15
16Shortly after Zephyr 3.6.0 was released, a new hardware model was introduced to
17Zephyr. This new model overhauls the way both SoCs and boards are named and
18defined, and adds support for features that had been identified as important
19over the years. Among them:
20
21- Support for multi-core, multi-arch AMP (Asymmetrical Multi Processing) SoCs
22- Support for multi-SoC boards
23- Support for reusing the SoC and board Kconfig trees outside of the Zephyr
24  build system
25- Support for advanced use cases with :ref:`sysbuild`
26- Removal of all existing arbitrary and inconsistent uses of Kconfig and folder
27  names
28
29All the documentation in this page refers to the current hardware model. Please
30refer to the documentation in Zephyr v3.6.0 (or earlier) for information on the
31previous, now obsolete, hardware model.
32
33More information about the rationale, development and concepts behind the new
34model can be found in the :github:`original issue <51831>`, the
35:github:`original Pull Request <50305>` and, for a complete set of changes
36introduced, the `hardware model v2 commit`_.
37
38Some non-critical features, enhancements and improvements of the new hardware
39model are still in development. Check the
40:github:`hardware model v2 enhancements issue <69546>` for a complete list.
41
42The transition from the previous hardware model to the current one (commonly
43referred to as "hardware model v2") requires modifications to all existing board
44and SoC definitions. A decision was made not to provide direct backwards
45compatibility for the previous model, which leaves users transitioning from a
46previous version of Zephyr to one including the new model (v3.7.0 and onwards)
47with two options if they have an out-of-tree board (or SoC):
48
49#. Convert the out-of-tree board to the current hardware model (recommended)
50#. Take the SoC definition from Zephyr v3.6.0 and copy it to your downstream
51   repository (ensuring that the build system can find it via a
52   :ref:`zephyr module <modules>` or ``SOC_ROOT``). This will allow your board,
53   defined in the previous hardware model, to continue to work
54
55When converting your board from the previous to the current hardware model, we
56recommend first reading through this page to understand the model in detail. You
57can then use the `example-application conversion Pull Request`_ as an example on
58how to port a simple board. Additionally, a `conversion script`_ is available
59and works reliably in many cases (though multi-core SoCs may not be handled
60entirely). Finally, the `hardware model v2 commit`_ contains the full conversion
61of all existing boards from the old to the current model, so you can use it as a
62complete conversion reference.
63
64.. _hardware model v2 commit: https://github.com/zephyrproject-rtos/zephyr/commit/8dc3f856229ce083c956aa301c31a23e65bd8cd8
65.. _example-application conversion Pull Request: https://github.com/zephyrproject-rtos/example-application/pull/58
66.. _conversion script: https://github.com/zephyrproject-rtos/zephyr/blob/main/scripts/utils/board_v1_to_v2.py
67
68.. _hw_support_hierarchy:
69
70Hardware support hierarchy
71**************************
72
73Zephyr's hardware support is based on a series of hierarchical abstractions.
74Primarily, each :term:`board` has one or more :term:`SoC`.
75Each SoC can be optionally classed into an :term:`SoC series`, which in turn may optionally belong to an :term:`SoC family`.
76Each SoC has one or more :term:`CPU cluster`, each containing one or more :term:`CPU core` of a particular :term:`architecture`.
77
78You can visualize the hierarchy in the diagram below:
79
80.. figure:: board/hierarchy.png
81   :width: 500px
82   :align: center
83   :alt: Hardware support Hierarchy
84
85   Hardware support Hierarchy
86
87Below are some examples of the hierarchy described in this section, in the form
88of a :term:`board` per row with its corresponding hierarchy entries. Notice how
89the :term:`SoC series` and :term:`SoC family` levels are not always used.
90
91.. table::
92
93   +--------------------------------------------+--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
94   | :term:`board name`                         | :term:`board qualifiers` | :term:`SoC` | :term:`SoC Series` | :term:`SoC family` | CPU core       | :term:`architecture` |
95   +============================================+==========================+=============+====================+====================+================+======================+
96   | :ref:`nrf52dk <nrf52dk_nrf52832>`          | nrf52832                 | nRF52832    | nRF52              | Nordic nRF         | Arm Cortex-M4  | ARMv7-M              |
97   +--------------------------------------------+--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
98   | :zephyr:board:`frdm_k64f <frdm_k64f>`      | mk64f12                  | MK64F12     | Kinetis K6x        | NXP Kinetis        | Arm Cortex-M4  | ARMv7-M              |
99   +--------------------------------------------+--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
100   | :zephyr:board:`rv32m1_vega <rv32m1_vega>`  | openisa_rv32m1/ri5cy     | RV32M1      | (Not used)         | (Not used)         | RI5CY          | RISC-V RV32          |
101   +--------------------------------------------+--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
102   | :ref:`nrf5340dk <nrf5340dk_nrf5340>`       | nrf5340/cpuapp           | nRF5340     | nRF53              | Nordic nRF         | Arm Cortex-M33 | ARMv8-M              |
103   |                                            +--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
104   |                                            | nrf5340/cpunet           | nRF5340     | nRF53              | Nordic nRF         | Arm Cortex-M33 | ARMv8-M              |
105   +--------------------------------------------+--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
106   | :zephyr:board:`mimx8mp_evk <imx8mp_evk>`   | mimx8ml8/a53             | i.MX8M Plus | i.MX8M             | NXP i.MX           | Arm Cortex-A53 | ARMv8-A              |
107   |                                            +--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
108   |                                            | mimx8ml8/m7              | i.MX8M Plus | i.MX8M             | NXP i.MX           | Arm Cortex-M7  | ARMv7-M              |
109   |                                            +--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
110   |                                            | mimx8ml8/adsp            | i.MX8M Plus | i.MX8M             | NXP i.MX           | Cadence HIFI4  | Xtensa LX6           |
111   +--------------------------------------------+--------------------------+-------------+--------------------+--------------------+----------------+----------------------+
112
113Additional details about terminology can be found in the next section.
114
115.. _board_terminology:
116
117Board terminology
118*****************
119
120The previous section introduced the hierarchical manner in which Zephyr
121classifies and implements hardware support.
122This section focuses on the terminology used around hardware support, and in
123particular when defining and working with boards and SoCs.
124
125The overall set of terms used around the concept of board in Zephyr is depicted
126in the image below, which uses the :zephyr:board:`bl5340_dvk` board as reference.
127
128.. figure:: board/board-terminology.svg
129   :width: 500px
130   :align: center
131   :alt: Board terminology diagram
132
133   Board terminology diagram
134
135The diagram shows the different terms that are used to describe boards:
136
137- The :term:`board name`: ``bl5340_dvk``
138- The optional :term:`board revision`: ``1.2.0``
139- The :term:`board qualifiers`, that optionally describe the :term:`SoC`,
140  :term:`CPU cluster` and :term:`variant`: ``nrf5340/cpuapp/ns``
141- The :term:`board target`, which uniquely identifies a combination of the above
142  and can be used to specify the hardware to build for when using the tooling
143  provided by Zephyr: ``bl5340_dvk@1.2.0/nrf5340/cpuapp/ns``
144
145Formally this can also be seen as
146:samp:`{board name}[@{revision}][/{board qualifiers}]`, which can be extended to
147:samp:`{board name}[@{revision}][/{SoC}[/{CPU cluster}][/{variant}]]`.
148
149If a board contains only one single-core SoC, then the SoC can be omitted from
150the board target. This implies that if the board does not define any board
151qualifiers, the board name can be used as a board target. Conversely, if
152board qualifiers are part of the board definition, then the SoC can be omitted
153by leaving it out but including the corresponding forward-slashes: ``//``.
154
155Continuing with the example above, The board :zephyr:board:`bl5340_dvk` is a single SoC
156board where the SoC defines two CPU clusters: ``cpuapp`` and ``cpunet``. One of
157the CPU clusters, ``cpuapp``, additionally defines a non-secure board variant,
158``ns``.
159
160The board qualifiers ``nrf5340/cpuapp/ns`` can be read as:
161
162
163- ``nrf5340``: The SoC, which is a Nordic nRF5340 dual-core SoC
164- ``cpuapp``: The CPU cluster ``cpuapp``, which consists of a single Cortex-M33
165  CPU core. The number of cores in a CPU cluster cannot be determined from the
166  board qualifiers.
167- ``ns``: a variant, in this case ``ns`` is a common variant name is
168  Zephyr denoting a non-secure build for boards supporting :ref:`tfm`.
169
170Not all SoCs define CPU clusters or variants. For example a simple board
171like the :ref:`thingy52_nrf52832` contains a single SoC with no CPU clusters and
172no variants.
173For ``thingy52`` the board target ``thingy52/nrf52832`` can be read as:
174
175- ``thingy52``: board name.
176- ``nrf52832``: The board qualifiers, in this case identical to the SoC, which
177  is a Nordic nRF52832.
178
179
180Make sure your SoC is supported
181*******************************
182
183Start by making sure your SoC is supported by Zephyr. If it is, it's time to
184:ref:`create-your-board-directory`. If you don't know, try:
185
186- checking :ref:`boards` for names that look relevant, and reading individual
187  board documentation to find out for sure.
188- asking your SoC vendor
189
190If you need to add a SoC, CPU cluster, or even architecture support, this is the
191wrong page, but here is some general advice.
192
193Architecture
194============
195
196See :ref:`architecture_porting_guide`.
197
198CPU Core
199========
200
201CPU core support files go in ``core`` subdirectories under :zephyr_file:`arch`,
202e.g. :zephyr_file:`arch/x86/core`.
203
204See :ref:`gs_toolchain` for information about toolchains (compiler, linker,
205etc.) supported by Zephyr. If you need to support a new toolchain,
206:ref:`build_overview` is a good place to start learning about the build system.
207Please reach out to the community if you are looking for advice or want to
208collaborate on toolchain support.
209
210SoC
211===
212
213Zephyr SoC support files are in architecture-specific subdirectories of
214:zephyr_file:`soc`. They are generally grouped by SoC family.
215
216When adding a new SoC family or series for a vendor that already has SoC
217support within Zephyr, please try to extract common functionality into shared
218files to avoid duplication. If there is no support for your vendor yet, you can
219add it in a new directory ``zephyr/soc/<VENDOR>/<YOUR-SOC>``; please use
220self-explanatory directory names.
221
222.. _create-your-board-directory:
223
224Create your board directory
225***************************
226
227Once you've found an existing board that uses your SoC, you can usually start
228by copy/pasting its board directory and changing its contents for your
229hardware.
230
231You need to give your board a unique name. Run ``west boards`` for a list of
232names that are already taken, and pick something new. Let's say your board is
233called ``plank`` (please don't actually use that name).
234
235Start by creating the board directory ``zephyr/boards/<VENDOR>/plank``, where
236``<VENDOR>`` is your vendor subdirectory. (You don't have to put your
237board directory in the zephyr repository, but it's the easiest way to get
238started. See :ref:`custom_board_definition` for documentation on moving your
239board directory to a separate repository once it's working.)
240
241.. note::
242  A ``<VENDOR>`` subdirectory is mandatory if contributing your board
243  to Zephyr, but if your board is placed in a local repo, then any folder
244  structure under ``<your-repo>/boards`` is permitted.
245  If the vendor is defined in the list in
246  :zephyr_file:`dts/bindings/vendor-prefixes.txt` then you must use
247  that vendor prefix as ``<VENDOR>``. ``others`` may be used as vendor prefix if
248  the vendor is not defined.
249
250.. note::
251
252  The board directory name does not need to match the name of the board.
253  Multiple boards can even defined be in one directory.
254
255Your board directory should look like this:
256
257.. code-block:: none
258
259   boards/<VENDOR>/plank
260   ├── board.yml
261   ├── board.cmake
262   ├── CMakeLists.txt
263   ├── doc
264   │   ├── plank.webp
265   │   └── index.rst
266   ├── Kconfig.plank
267   ├── Kconfig.defconfig
268   ├── plank_<qualifiers>_defconfig
269   ├── plank_<qualifiers>.dts
270   └── plank_<qualifiers>.yaml
271
272Replace ``plank`` with your board's name, of course.
273
274The mandatory files are:
275
276#. :file:`board.yml`: a YAML file describing the high-level meta data of the
277   boards such as the boards names, their SoCs, and variants.
278   CPU clusters for multi-core SoCs are not described in this file as they are
279   inherited from the SoC's YAML description.
280
281#. :file:`plank_<qualifiers>.dts`: a hardware description
282   in :ref:`devicetree <dt-guide>` format. This declares your SoC, connectors,
283   and any other hardware components such as LEDs, buttons, sensors, or
284   communication peripherals (USB, BLE controller, etc).
285
286#. :file:`Kconfig.plank`: the base software configuration for selecting SoC and
287   other board and SoC related settings. Kconfig settings outside of the board
288   and SoC tree must not be selected. To select general Zephyr Kconfig settings
289   the :file:`Kconfig` file must be used.
290
291
292The optional files are:
293
294- :file:`Kconfig`, :file:`Kconfig.defconfig` software configuration in
295  :ref:`kconfig` formats. This provides default settings for software features
296  and peripheral drivers.
297- :file:`plank_defconfig` and :file:`plank_<qualifiers>_defconfig`: software
298  configuration in Kconfig ``.conf`` format.
299- :file:`board.cmake`: used for :ref:`flash-and-debug-support`
300- :file:`CMakeLists.txt`: if you need to add additional source files to
301  your build.
302- :file:`doc/index.rst`, :file:`doc/plank.webp`: documentation for and a picture
303  of your board. You only need this if you're :ref:`contributing-your-board` to
304  Zephyr.
305- :file:`plank_<qualifiers>.yaml`: a YAML file with miscellaneous metadata used
306  by the :ref:`twister_script`.
307
308Board qualifiers of the form ``<soc>/<cpucluster>/<variant>`` are normalized so
309that ``/`` is replaced with ``_`` when used for filenames, for example:
310``soc1/foo`` becomes ``soc1_foo`` when used in filenames.
311
312.. _board_description:
313
314Write your board YAML
315*********************
316
317The board YAML file describes the board at a high level.
318This includes the SoC, board variants, and board revisions.
319
320Detailed configurations, such as hardware description and configuration are done
321in devicetree and Kconfig.
322
323The skeleton of the board YAML file is:
324
325.. code-block:: yaml
326
327   board:
328     name: <board-name>
329     vendor: <board-vendor>
330     revision:
331       format: <major.minor.patch|letter|number|custom>
332       default: <default-revision-value>
333       exact: <true|false>
334       revisions:
335       - name: <revA>
336       - name: <revB>
337         ...
338     socs:
339     - name: <soc-1>
340       variants:
341       - name: <variant-1>
342       - name: <variant-2>
343         variants:
344         - name: <sub-variant-2-1>
345           ...
346     - name: <soc-2>
347       ...
348
349It is possible to have multiple boards located in the board folder.
350If multiple boards are placed in the same board folder, then the file
351:file:`board.yml` must describe those in a list as:
352
353.. code-block:: yaml
354
355   boards:
356   - name: <board-name-1>
357     vendor: <board-vendor>
358     ...
359   - name: <board-name-2>
360     vendor: <board-vendor>
361     ...
362   ...
363
364
365.. _default_board_configuration:
366
367Write your devicetree
368*********************
369
370The devicetree file :file:`boards/<vendor>/plank/plank.dts` or
371:file:`boards/<vendor>/plank/plank_<qualifiers>.dts` describes your board
372hardware in the Devicetree Source (DTS) format (as usual, change ``plank`` to
373your board's name). If you're new to devicetree, see :ref:`devicetree-intro`.
374
375In general, :file:`plank.dts` should look like this:
376
377.. code-block:: devicetree
378
379   /dts-v1/;
380   #include <your_soc_vendor/your_soc.dtsi>
381
382   / {
383           model = "A human readable name";
384           compatible = "yourcompany,plank";
385
386           chosen {
387                   zephyr,console = &your_uart_console;
388                   zephyr,sram = &your_memory_node;
389                   /* other chosen settings  for your hardware */
390           };
391
392           /*
393            * Your board-specific hardware: buttons, LEDs, sensors, etc.
394            */
395
396           leds {
397                   compatible = "gpio-leds";
398                   led0: led_0 {
399                           gpios = < /* GPIO your LED is hooked up to */ >;
400                           label = "LED 0";
401                   };
402                   /* ... other LEDs ... */
403           };
404
405           buttons {
406                   compatible = "gpio-keys";
407                   /* ... your button definitions ... */
408           };
409
410           /* These aliases are provided for compatibility with samples */
411           aliases {
412                   led0 = &led0; /* now you support the blinky sample! */
413                   /* other aliases go here */
414           };
415   };
416
417   &some_peripheral_you_want_to_enable { /* like a GPIO or SPI controller */
418           status = "okay";
419   };
420
421   &another_peripheral_you_want {
422           status = "okay";
423   };
424
425Only one ``.dts`` file will be used, and the most specific file which exists
426will be used.
427
428This means that if both :file:`plank.dts` and :file:`plank_soc1_foo.dts` exist,
429then when building for ``plank`` / ``plank/soc1``, then :file:`plank.dts` is
430used. When building for ``plank//foo`` / ``plank/soc1/foo`` the
431:file:`plank_soc1_foo.dts` is used.
432
433This allows board maintainers to write a base devicetree file for the board
434or write specific devicetree files for a given board's SoC or variant.
435
436If you're in a hurry, simple hardware can usually be supported by copy/paste
437followed by trial and error. If you want to understand details, you will need
438to read the rest of the devicetree documentation and the devicetree
439specification.
440
441.. _dt_k6x_example:
442
443Example: FRDM-K64F and Hexiwear K64
444===================================
445
446.. Give the filenames instead of the full paths below, as it's easier to read.
447   The cramped 'foo.dts<path>' style avoids extra spaces before commas.
448
449This section contains concrete examples related to writing your board's
450devicetree.
451
452The FRDM-K64F and Hexiwear K64 board devicetrees are defined in
453:zephyr_file:`frdm_k64fs.dts <boards/nxp/frdm_k64f/frdm_k64f.dts>` and
454:zephyr_file:`hexiwear_k64.dts <boards/nxp/hexiwear/hexiwear_mk64f12.dts>`
455respectively. Both boards have NXP SoCs from the same Kinetis SoC family, the
456K6X.
457
458Common devicetree definitions for K6X are stored in :zephyr_file:`nxp_k6x.dtsi
459<dts/arm/nxp/nxp_k6x.dtsi>`, which is included by both board :file:`.dts`
460files. :zephyr_file:`nxp_k6x.dtsi<dts/arm/nxp/nxp_k6x.dtsi>` in turn includes
461:zephyr_file:`armv7-m.dtsi<dts/arm/armv7-m.dtsi>`, which has common definitions
462for Arm v7-M cores.
463
464Since :zephyr_file:`nxp_k6x.dtsi<dts/arm/nxp/nxp_k6x.dtsi>` is meant to be
465generic across K6X-based boards, it leaves many devices disabled by default
466using ``status`` properties.  For example, there is a CAN controller defined as
467follows (with unimportant parts skipped):
468
469.. code-block:: devicetree
470
471   can0: can@40024000 {
472        ...
473        status = "disabled";
474        ...
475   };
476
477It is up to the board :file:`.dts` or application overlay files to enable these
478devices as desired, by setting ``status = "okay"``. The board :file:`.dts`
479files are also responsible for any board-specific configuration of the device,
480such as adding nodes for on-board sensors, LEDs, buttons, etc.
481
482For example, FRDM-K64 (but not Hexiwear K64) :file:`.dts` enables the CAN
483controller and sets the bus speed:
484
485.. code-block:: devicetree
486
487   &can0 {
488        status = "okay";
489   };
490
491The ``&can0 { ... };`` syntax adds/overrides properties on the node with label
492``can0``, i.e. the ``can@4002400`` node defined in the :file:`.dtsi` file.
493
494Other examples of board-specific customization is pointing properties in
495``aliases`` and ``chosen`` to the right nodes (see :ref:`dt-alias-chosen`), and
496making GPIO/pinmux assignments.
497
498.. _board_kconfig_files:
499
500Write Kconfig files
501*******************
502
503Zephyr uses the Kconfig language to configure software features. Your board
504needs to provide some Kconfig settings before you can compile a Zephyr
505application for it.
506
507Setting Kconfig configuration values is documented in detail in
508:ref:`setting_configuration_values`.
509
510There is one mandatory Kconfig file in the board directory, and several optional
511files for a board named ``plank``:
512
513.. code-block:: none
514
515   boards/<vendor>/plank
516   ├── Kconfig
517   ├── Kconfig.plank
518   ├── Kconfig.defconfig
519   ├── plank_defconfig
520   └── plank_<qualifiers>_defconfig
521
522:file:`Kconfig.plank`
523  A shared Kconfig file which can be sourced both in Zephyr Kconfig and sysbuild
524  Kconfig trees.
525
526  This file selects the SoC in the Kconfig tree and potential other SoC related
527  Kconfig settings. This file must not select anything outside the re-usable
528  Kconfig board and SoC trees.
529
530  A :file:`Kconfig.plank` may look like this:
531
532  .. code-block:: kconfig
533
534     config BOARD_PLANK
535             select SOC_SOC1
536
537  The Kconfig symbols :samp:`BOARD_{board}` and
538  :samp:`BOARD_{normalized_board_target}` are constructed by the build
539  system, therefore no type shall be defined in above code snippet.
540
541:file:`Kconfig`
542  Included by :zephyr_file:`boards/Kconfig`.
543
544  This file can add Kconfig settings which are specific to the current board.
545
546  Not all boards have a :file:`Kconfig` file.
547
548  A board specific setting should be defining a custom setting and usually with
549  a prompt, like this:
550
551  .. code-block:: kconfig
552
553     config BOARD_FEATURE
554             bool "Board specific feature"
555
556  If the setting name is identical to an existing Kconfig setting in Zephyr and
557  only modifies the default value of said setting, then
558  :file:`Kconfig.defconfig` should be used  instead.
559
560:file:`Kconfig.defconfig`
561  Board-specific default values for Kconfig options.
562
563  Not all boards have a :file:`Kconfig.defconfig` file.
564
565  The entire file should be inside an ``if BOARD_PLANK`` / ``endif`` pair of
566  lines, like this:
567
568  .. code-block:: kconfig
569
570     if BOARD_PLANK
571
572     config FOO
573             default y
574
575     if NETWORKING
576     config SOC_ETHERNET_DRIVER
577             default y
578     endif # NETWORKING
579
580     endif # BOARD_PLANK
581
582:file:`plank_defconfig` / :file:`plank_<qualifiers>_defconfig`
583  A Kconfig fragment that is merged as-is into the final build directory
584  :file:`.config` whenever an application is compiled for your board.
585
586  If both the common :file:`plank_defconfig` file and one or more board
587  qualifiers specific :file:`plank_<qualifiers>_defconfig` files exist, then
588  all matching files will be used.
589  This allows you to place configuration which is common for all board SoCs,
590  CPU clusters, and board variants in the base :file:`plank_defconfig` and only
591  place the adjustments specific for a given SoC or board variant in the
592  :file:`plank_<qualifiers>_defconfig`.
593
594  The ``_defconfig`` should contain mandatory settings for your system clock,
595  console, etc. The results are architecture-specific, but typically look
596  something like this:
597
598  .. code-block:: cfg
599
600     CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=120000000  # set up your clock, etc
601     CONFIG_SERIAL=y
602
603:file:`plank_x_y_z_defconfig` / :file:`plank_<qualifiers>_x_y_z_defconfig`
604  A Kconfig fragment that is merged as-is into the final build directory
605  :file:`.config` whenever an application is compiled for your board revision
606  ``x.y.z``.
607
608Build, test, and fix
609********************
610
611Now it's time to build and test the application(s) you want to run on your
612board until you're satisfied.
613
614For example:
615
616.. code-block:: console
617
618   west build -b plank samples/hello_world
619   west flash
620
621For ``west flash`` to work, see :ref:`flash-and-debug-support` below. You can
622also just flash :file:`build/zephyr/zephyr.elf`, :file:`zephyr.hex`, or
623:file:`zephyr.bin` with any other tools you prefer.
624
625.. _porting-general-recommendations:
626
627General recommendations
628***********************
629
630For consistency and to make it easier for users to build generic applications
631that are not board specific for your board, please follow these guidelines
632while porting.
633
634- Unless explicitly recommended otherwise by this section, leave peripherals
635  and their drivers disabled by default.
636
637- Configure and enable a system clock, along with a tick source.
638
639- Provide pin and driver configuration that matches the board's valuable
640  components such as sensors, buttons or LEDs, and communication interfaces
641  such as USB, Ethernet connector, or Bluetooth/Wi-Fi chip.
642
643- If your board uses a well-known connector standard (like Arduino, Mikrobus,
644  Grove, or 96Boards connectors), add connector nodes to your DTS and configure
645  pin muxes accordingly.
646
647- Configure components that enable the use of these pins, such as
648  configuring an SPI instance to use the usual Arduino SPI pins.
649
650- If available, configure and enable a serial output for the console
651  using the ``zephyr,console`` chosen node in the devicetree.
652  Development boards with a built-in debug adapter or USB-to-UART adapter should
653  by default configure and use the UART controller connected to that adapter.
654  For boards like :ref:`nRF52840 Dongle <nrf52840dongle_nrf52840>`, that do not
655  have a debug adapter, but a USB device controller, there is a common
656  :zephyr_file:`Kconfig file <boards/common/usb/Kconfig.cdc_acm_serial.defconfig>`
657  that must be included in the board's Kconfig.defconfig file and
658  :zephyr_file:`devicetree file <boards/common/usb/cdc_acm_serial.dtsi>`
659  that must be included if the board's devicetree, if the board want to use the
660  CDC ACM UART as the default backend for logging and shell.
661
662- If your board supports networking, configure a default interface.
663
664- Enable all GPIO ports connected to peripherals or expansion connectors.
665
666- If available, enable pinmux and interrupt controller drivers.
667
668- It is recommended to enable the MPU by default, if there is support for it
669  in hardware. For boards with limited memory resources it is acceptable to
670  disable it. When the MPU is enabled, it is recommended to also enable
671  hardware stack protection (CONFIG_HW_STACK_PROTECTION=y) and, thus, allow the
672  kernel to detect stack overflows when the system is running in privileged
673  mode.
674
675.. _flash-and-debug-support:
676
677Flash and debug support
678***********************
679
680Zephyr supports :ref:`west-build-flash-debug` via west extension commands.
681
682To add ``west flash`` and ``west debug`` support for your board, you need to
683create a :file:`board.cmake` file in your board directory. This file's job is
684to configure a "runner" for your board. (There's nothing special you need to
685do to get ``west build`` support for your board.)
686
687"Runners" are Zephyr-specific Python classes that wrap :ref:`flash and debug
688host tools <flash-debug-host-tools>` and integrate with west and the zephyr build
689system to support ``west flash`` and related commands. Each runner supports
690flashing, debugging, or both. You need to configure the arguments to these
691Python scripts in your :file:`board.cmake` to support those commands like this
692example :file:`board.cmake`:
693
694.. code-block:: cmake
695
696   board_runner_args(jlink "--device=nrf52" "--speed=4000")
697   board_runner_args(pyocd "--target=nrf52" "--frequency=4000000")
698
699   include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
700   include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
701   include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake)
702
703This example configures the ``nrfjprog``, ``jlink``, and ``pyocd`` runners.
704
705.. warning::
706
707   Runners usually have names which match the tools they wrap, so the ``jlink``
708   runner wraps Segger's J-Link tools, and so on. But the runner command line
709   options like ``--speed`` etc. are specific to the Python scripts.
710
711.. note::
712
713   Runners and board configuration should be created without being targeted to
714   a single operating system if the tool supports multiple operating systems,
715   nor should it rely upon special system setup/configuration. For example; do
716   not assume that a user will have prior knowledge/configuration or (if using
717   Linux) special udev rules installed, do not assume one specific ``/dev/X``
718   device for all platforms as this will not be compatible with Windows or
719   macOS, and allow for overriding of the selected device so that multiple
720   boards can be connected to a single system and flashed/debugged at the
721   choice of the user.
722
723For more details:
724
725- Run ``west flash --context`` to see a list of available runners which support
726  flashing, and ``west flash --context -r <RUNNER>`` to view the specific options
727  available for an individual runner.
728- Run ``west debug --context`` and ``west debug --context <RUNNER>`` to get
729  the same output for runners which support debugging.
730- Run ``west flash --help`` and ``west debug --help`` for top-level options
731  for flashing and debugging.
732- See :ref:`west-runner` for Python APIs.
733- Look for :file:`board.cmake` files for other boards similar to your own for
734  more examples.
735
736To see what a ``west flash`` or ``west debug`` command is doing exactly, run it
737in verbose mode:
738
739.. code-block:: sh
740
741   west --verbose flash
742   west --verbose debug
743
744Verbose mode prints any host tool commands the runner uses.
745
746The order of the ``include()`` calls in your :file:`board.cmake` matters. The
747first ``include`` sets the default runner if it's not already set. For example,
748including ``nrfjprog.board.cmake`` first means that ``nrfjprog`` is the default
749flash runner for this board. Since ``nrfjprog`` does not support debugging,
750``jlink`` is the default debug runner.
751
752.. _porting_board_revisions:
753
754Multiple board revisions
755************************
756
757See :ref:`application_board_version` for basics on this feature from the user
758perspective.
759
760Board revisions are described in the ``revision`` entry of the
761:file:`board.yml`.
762
763.. code-block:: yaml
764
765   board:
766     revision:
767       format: <major.minor.patch|letter|number|custom>
768       default: <default-revision-value>
769       exact: <true|false>
770       revisions:
771       - name: <revA>
772       - name: <revB>
773
774Zephyr natively supports the following revision formats:
775
776- ``major.minor.patch``: match a three digit revision, such as ``1.2.3``.
777- ``number``: matches integer revisions
778- ``letter``: matches single letter revisions from ``A`` to ``Z`` only
779
780.. _board_fuzzy_revision_matching:
781
782Fuzzy revision matching
783=======================
784
785Fuzzy revision matching is enabled per default.
786
787If the user selects a revision between those available, the closest revision
788number that is not larger than the user's choice is used. For example, if the
789board ``plank`` defines revisions ``0.5.0``, and ``1.5.0`` and the user builds
790for ``plank@0.7.0``, the build system will target revision ``0.5.0``.
791
792The build system will print this at CMake configuration time:
793
794.. code-block:: console
795
796   -- Board: plank, Revision: 0.7.0 (Active: 0.5.0)
797
798This allows you to only create revision configuration files for board revision
799numbers that introduce incompatible changes.
800
801Similar for ``letter`` where revision ``A``, ``D``, and ``F`` could be defined
802and the user builds for ``plank@E``, the build system will target revision ``D``
803.
804
805Exact revision matching
806=======================
807
808Exact revision matching is enabled when ``exact: true`` is specified in the
809revision section in :file:`board.yml`.
810
811When exact is defined then building for ``plank@0.7.0`` in the above example
812will result in the following error message:
813
814.. code-block:: console
815
816   Board revision `0.7.0` not found.  Please specify a valid board revision.
817
818Board revision configuration adjustment
819=======================================
820
821When the user builds for board ``plank@<revision>`` it is possible to make
822adjustments to the board's normal configuration.
823
824As described in the :ref:`default_board_configuration` and
825:ref:`board_kconfig_files` sections the board default configuration is created
826from the files :file:`<board>.dts` / :file:`<board>_<qualifiers>.dts` and
827:file:`<board>_defconfig` / :file:`<board>_<qualifiers>_defconfig`.
828When building for a specific board revision, the above files are used as a
829starting point and the following board files will be used in addition:
830
831- :file:`<board>_<qualifiers>_<revision>_defconfig`: a specific revision
832  defconfig which is only used for the board and SOC / variants identified by
833  ``<board>_<qualifiers>``.
834
835- :file:`<board>_<revision>_defconfig`: a specific revision defconfig which is
836  used for the board regardless of the SOC / variants.
837
838- :file:`<board>_<qualifiers>_<revision>.overlay`: a specific revision dts
839  overlay which is only used for the board and SOC / variants identified by
840  ``<board>_<qualifiers>``.
841
842- :file:`<board>_<revision>.overlay`: a specific revision dts overlay which is
843  used for the board regardless of the SOC / variants.
844
845This split allows boards with multiple SoCs, multi-core SoCs, or variants to
846place common revision adjustments which apply to all SoCs and variants in a
847single file, while still providing the ability to place SoC or variant specific
848adjustments in a dedicated revision file.
849
850Using the ``plank`` board from previous sections, then we could have the following
851revision adjustments:
852
853.. code-block:: none
854
855   boards/zephyr/plank
856   ├── plank_0_5_0_defconfig          # Kconfig adjustment for all plank board qualifiers on revision 0.5.0
857   ├── plank_0_5_0.overlay            # DTS overlay for all plank board qualifiers on revision 0.5.0
858   └── plank_soc1_foo_1_5_0_defconfig # Kconfig adjustment for plank board when building for soc1 variant foo on revision 1.5.0
859
860Custom revision.cmake files
861***************************
862
863Some boards may not use board revisions supported natively by Zephyr.
864For example string revisions.
865
866One reason why Zephyr doesn't support string revisions is that strings can take
867many forms and it's not always clear if the given strings are just strings, such
868as ``blue``, ``green``, ``red``, etc. or if they provide an order which can be
869matched against higher or lower revisions, such as ``alpha``, ``beta```,
870``gamma``.
871
872Due to the sheer number of possibilities with strings, including the possibility
873of doing regex matches internally, then string revisions must be done using
874``custom`` revision type.
875
876To indicate to the build system that ``custom`` revisions are used, the format
877field in the ``revision`` section of the :file:`board.yml` must be written as:
878
879.. code-block:: yaml
880
881   board:
882     revision:
883       format: custom
884
885When using custom revisions then a :file:`revision.cmake` must be created in the
886board directory.
887
888The :file:`revision.cmake` will be included by the build system when building
889for the board and it is the responsibility of the file to validate the revision
890specified by the user.
891
892The :makevar:`BOARD_REVISION` variable holds the revision value specified by the
893user.
894
895To signal to the build system that it should use a different revision than the
896one specified by the user, :file:`revision.cmake` can set the variable
897``ACTIVE_BOARD_REVISION`` to the revision to use instead. The corresponding
898Kconfig files and devicetree overlays must be named
899:file:`<board>_<ACTIVE_BOARD_REVISION>_defconfig` and
900:file:`<board>_<ACTIVE_BOARD_REVISION>.overlay`.
901
902.. _contributing-your-board:
903
904Contributing your board
905***********************
906
907If you want to contribute your board to Zephyr, first -- thanks!
908
909There are some extra things you'll need to do:
910
911#. Make sure you've followed all the :ref:`porting-general-recommendations`.
912   They are requirements for boards included with Zephyr.
913
914#. Add documentation for your board using the template file
915   :zephyr_file:`doc/templates/board.tmpl`. See :ref:`zephyr_doc` for
916   information on how to build your documentation before submitting
917   your pull request.
918
919#. Prepare a pull request adding your board which follows the
920   :ref:`contribute_guidelines`.
921
922.. _extend-board:
923
924Board extensions
925****************
926
927The board hardware model in Zephyr allows you to extend an existing board with
928new board variants. Such board extensions can be done in your custom repository
929and thus outside of the Zephyr repository.
930
931Extending an existing board with an extra variant allows you to adjust an
932existing board and thereby during build to select building for the existing,
933unmodified board, or the new variant.
934
935To extend an existing board, first create a :file:`board.yml` in your extended
936board. Make sure to use the directory structure described in
937:ref:`create-your-board-directory`.
938
939The skeleton of the board YAML file for extending a board is:
940
941.. code-block:: yaml
942
943   board:
944     extend: <existing-board-name>
945      variants:
946       - name: <new-variant>
947         qualifier: <existing-qualifier>
948
949When extending a board, your board directory should look like:
950
951.. code-block:: none
952
953   boards/<VENDOR>/plank
954   ├── board.yml
955   ├── plank_<new-qualifiers>_defconfig
956   └── plank_<new-qualifiers>.dts
957
958Replace ``plank`` with the real name of the board you extend.
959
960In some cases you might want to also adjust additional settings, like the
961:file:`Kconfig.defconfig` or :file:`Kconfig.{board}`.
962Therefore it is also possible to provide the following in addition when
963extending a board.
964
965.. code-block:: none
966
967   boards/<VENDOR>/plank
968   ├── board.cmake
969   ├── Kconfig
970   ├── Kconfig.plank
971   ├── Kconfig.defconfig
972   └── plank_<new-qualifiers>.yaml
973
974Board extensions (Old hardware model)
975*************************************
976
977.. note::
978
979  This extension mechanism is intended for boards in old hardware description
980  format. For boards described in new hardware model format, use the extension
981  feature described in :ref:`extend-board`.
982
983Boards already supported by Zephyr can be extended by downstream users, such as
984``example-application`` or vendor SDKs. In some situations, certain hardware
985description or :ref:`choices <devicetree-chosen-nodes>` can not be added in the
986upstream Zephyr repository, but they can be in a downstream project, where
987custom bindings or driver classes can also be created. This feature may also be
988useful in development phases, when the board skeleton lives upstream, but other
989features are developed in a downstream module.
990
991Board extensions are board fragments that can be present in an out-of-tree board
992root folder, under ``${BOARD_ROOT}/boards/extensions``. Here is an example
993structure of an extension for the ``plank`` board and its revisions:
994
995.. code-block:: none
996
997   boards/extensions/plank
998   ├── plank.conf                # optional
999   ├── plank_<revision>.conf     # optional
1000   ├── plank.overlay             # optional
1001   └── plank_<revision>.overlay  # optional
1002
1003A board extension directory must follow the naming structure of the original
1004board it extends. It may contain Kconfig fragments and/or devicetree overlays.
1005Extensions are, by default, automatically loaded and applied on top of board
1006files, before anything else. There is no guarantee on which order extensions are
1007applied, in case multiple exist. This feature can be disabled by passing
1008``-DBOARD_EXTENSIONS=OFF`` when building.
1009
1010Note that board extensions need to follow the
1011:ref:`same guidelines <porting-general-recommendations>` as regular boards. For
1012example, it is wrong to enable extra peripherals or subsystems in a board
1013extension.
1014
1015.. warning::
1016
1017   Board extensions are not allowed in any module referenced in Zephyr's
1018   ``west.yml`` manifest file. Any board changes are required to be submitted to
1019   the main Zephyr repository.
1020