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