Feedback
Feedback

If you are having issues with the exercises, please create a ticket on DevZone: devzone.nordicsemi.com
Click or drag files to this area to upload. You can upload up to 2 files.

Creating board files

v3.0.0

Note

This lesson covers how to define boards in the nRF Connect SDK using both hardware models v1 and v2 (HWMv1 and HWMv2 respectively).

This exercise tab covers nRF Connect SDK where HWMv2 is used, which is recommended for all new designs.

In this topic, we will explore the different options for creating custom board files and the guidelines for naming your custom board.

We will cover the mandatory and optional files required to define a custom board in HWMv2, as well as how to create a revision of the board. We will study these files one by one and understand their role.

In Exercise 1 of this lesson, we will use the Create a new board GUI in the nRF Connect for VS Code extension to define a new board, and populate most of the mandatory files’ content.

Board terminology (in HWMv2)

In Hardware Model version 2, each board has a unique board name (sometimes referred to as the board ID).

The Create a new board GUI function in the nRF Connect for VS Code extension will ask you to provide both a board name and a human-readable name for your board. The human-readable name can include white spaces or capital letters (e.g., My nRF54L DK, DevAcademyL3E1), and is intended for display purposes and documentation. The board name is commonly a lower-case and underscore-separated version of the human-readable name (e.g., my_nrf54l_dk, devacademyl3e1).

Definition

Human-readable name (full_name) is the descriptive name for the board, which can include spaces and capital letters. The full name is intended for display purposes and documentation, making it easier for users to recognize the board.

Board name is typically a lowercase, underscore-separated version of the human-readable name, with all whitespaces replaced by underscores. The board name uniquely and descriptively identifies a particular system, but does not include additional information that may be required to actually build an image.

When naming your custom board, you need to give your board a unique name. Run west boards in the nRF Connect Terminal for a list of names that have already been taken; you can’t name your custom board with a name that is already in use.

Below is an example of the output:

esp32c3_042_oled
96b_aerocore2
nrf52840dongle
nrf5340dk
nrf54l15dk
thingy53
nrf52_sparkfun
Terminal

Note

In HWMv2, the name of the SoC is no longer needed at the end of the board name. Instead, this is specified explicitly in one of the files in the board definition (board.yml file).

In addition to the board name, a board will have one or more board qualifiers.

Let’s examine the board terminology used in HWMv2, using the BL5340 DVK from Ezurio as an example, which is based on the nRF5340 SoC.

  • Board target: The full string that can be provided to any of the Zephyr build tools (e.g., west) to compile and link an image for a particular hardware system. Boards with single-core SoCs typically have one board target, while more advanced boards with multiple SoCs or multi-core SoCs will have several board targets.
  • Board name: The name of the board without spaces.
  • Board revision (optional): This is used to capture new changes in new hardware versions (new schematics, new PCB).
  • Board qualifiers: The set of additional tokens, separated by a forward slash / that follows the board name (and optionally board revision).
    • SoC: The specific SoC used on the board.
    • CPU cluster: This is defined by the SoC layer. If the SoC does not have any clusters, this is omitted.
    • Variant: In the context of board qualifiers, a variant designates a particular type or configuration of a build for a combination of SoC and CPU clusters. Common uses of the variant concept include introducing both secure and non-secure builds for platforms with Trusted Firmware-M support, or selecting the type of RAM used in a build. Another use of variants is for different builds of hardware (not a revision). For example, if you have a board that includes sensors and another exact one that does not include sensors.

Consider a board with the human-readable name DevAcademy L3E1, based on the nRF52833 SoC. The board will have the board name devacademyl3e1, and the board target devacademyl3e1/nrf52833. The board can have an optional revision that can be specified as [email protected]/nrf52833 and it could have an optional variant [email protected]/nrf52833/sense.

Note

The CPU clusters are defined by the SoC layer, and the nRF52833 SoC does not have any clusters.

Location of custom board

Before diving into the board files that make up the custom board definition, we need to know where to put the files.

When working with custom boards, you have three main options for where to place the board definition files. Each option has its own advantages and limitations:

  • Out-of-Tree (dedicated directory): In this approach, your board files are stored outside of the nRF Connect SDK/Zephyr tree in a separate directory. You’ll configure the build system to locate and use these external board files. This method is ideal for closed-source projects where you want to keep board definitions private. This is the method we’ll focus on in this lesson.
  • Upstream in Zephyr: Choose this option if you’re developing a development kit, module, reference design, or prototyping platform that you intend to share with the Zephyr community. It’s also appropriate for open-source products. Board definitions submitted upstream must include documentation and go through a review and approval process by the Zephyr maintainers.
  • Inside the application’s boards folder: This option is suitable for quick prototyping or debugging. You can place the board files directly in a boards subdirectory within your application folder. This is a convenient approach for temporary or experimental work.

Board files

Consider our new development kit DevAcademy L3E1 which is based on the nRF52833 SoC. The board name for this board will be devacademyl3e1.

When creating a custom board definition, remember that the SDK provides the hardware layer files from Architecture up to SoC. So, we only need to populate the board layer. The board layer consists of these four mandatory files.

boards/<vendor>/devacademyl3e1
├── board.yml
├── Kconfig.devacademyl3e1
├── devacademyl3e1.dts
└── devacademyl3e1-pinctrl.dtsi 

The term <vendor> serves as a placeholder for the vendor name.

Mandatory files

Let’s take a close look at the four mandatory files in the board layer.

1. board.yml

The board.yml file is a required component introduced in Hardware Model v2 (HWMv2). Each board folder must contain one board.yml, and it serves as a central configuration file that defines key properties for your board.

  • Board name: Defines the board name or names.
  • SoC selection: At least one SoC must be specified.
  • Revisions: Optional; used to define specific hardware versions.
  • Variants: Used for special configurations, such as enabling TF-M or using a different CPU core.

While it’s technically possible to define multiple boards in one folder using a single board.yml, this is not a common use case.

When you use the extension tool and input the board name, SoC, SoC variant, and vendor, the board.yml file is generated automatically. In most cases, you won’t need to manually edit it.

Here is what a board.yml file typically looks like. You could also include full_name: in board.yml to specify the human-readable name of your board.

Let’s take a look at the board.yml files for some Nordic development kits.

board.yml examples
  1. Single board target: The nRF52840 dongle is based on the nRF52840 SoC, a single-core device with no CPU clusters.
  2. Quad board target: The nRF54L15 has two CPU clusters defined by the SoC layer, cpuapp and cpuflpr. The board.yml defines a new variant, xip, which is associated with cpuflpr. It also defines another variant called ns (TF-M enabled) associated with the cpuapp. So in total, there are 4 board targets.
  3. Dual board target with revisions: The nRF9161 DK has no CPU clusters defined by the nRF9161 SiP. There is a variant, ns. It also defines two revisions: 0.9.0 (default) and 0.7.0.

2. Kconfig.devacademyl3e1

This file serves a specific and essential purpose: it selects the SoC(s) used by the board. By doing so, it pulls in the appropriate hardware layer files from Architecture up to SoC. It also defines a Kconfig symbol for the board, which is the board name prefixed with BOARD_ .

  • It contains select statement(s) 
    • Only select is needed for a single-board target
    • select … if statements are needed for multi-core SoCs or multi-SoC boards

Here are some examples:

Below is an example of our devacademyl3e1 (single board target) that we will develop in Exercise 1, which is based on the nRF52833 QIAA.

config BOARD_DEVACADEMYL3E1
	select SOC_NRF52833_QIAA

Here is another example for the nRF54L15 DK (quad board target). The file selects the appropriate SoC support layer based on the normalized board target triggered from the build system.

3. devacademyl3e1.dts

The board-level devicetree file is a hardware description written in the devicetree format. It represents the schematics of your board, detailing its physical components and connections.

It includes connectors and any other hardware components such as LEDs, buttons, sensors, or communication peripherals (USB, BLE controller, etc). Memory partitioning is also done in this file. We will rely heavily on the automation provided by the nRF Connect for VS Code extension, including the Devicetree Visual Editor, to help us populate this file.

If your board has multiple board qualifiers (i.e., different board targets or variants), you need to create a separate board-level devicetree file for each board target. You can structure the board-level devicetree file into multiple files to improve readability and maintainability.

4. devacademyl3e1-pinctrl.dtsi

This file defines the pin-mapping of your board’s peripherals.

If your board has multiple board qualifiers (i.e., different board targets or variants), you need to create a separate pin-mapping file for each board target.

Optional files

Now that we’ve covered the four mandatory files in the board layer, let’s take a look at the optional files.

Below is a board layer consisting of all mandatory files, optional, and special use cases files:

boards/<vendor>/devacademyl3e1
├── board.yml
├── Kconfig.devacademyl3e1
├── devacademyl3e1_<qualifiers>.dts 
├── devacademyl3e1_<qualifiers>-pinctrl.dtsi
├── devacademyl3e1_<qualifiers>_defconfig
├── Kconfig.defconfig
├── board.cmake # Used for flash and debug
├── CMakeLists.txt  # Needed in special cases 
├── c_files.c  # Needed in special cases
├── doc # Optional 
│   ├── devacademyl3e1.png
│   └── index.rst
├── Kconfig # Optional to create a board Kconfig options menu
├── devacademyl3e1_<qualifiers>.yml # Optional for Test Runner (Twister)
├── devacademyl3e1_<qualifiers>_<revision>.conf # Needed to support hardware revisions
├── devacademyl3e1_<qualifiers>_<revision>.overlay  #Needed to support hardware revisions
└── dts # Optional 
    └── bindings

The term <vendor> serves as a placeholder for the vendor name. If the board has qualifiers (<qualifiers>), such as multiple SoCs, CPU clusters, or variants (e.g., multi-board target), these qualifiers must be appended to the board name to clearly indicate where you want these files to apply.

devacademyl3e1_defconfig

The devacademyl3e1_defconfig file is a Kconfig fragment that is merged as-is into the final build of any application built for the specified board.

Here is the default devacademyl3e1_defconfig file generated by the tool (differs from one SoC to another).

# Copyright (c) 2024 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

CONFIG_ARM_MPU=y
CONFIG_HW_STACK_PROTECTION=y

In addition to the default Kconfig symbols, we need to manually include any additional Kconfig symbols that we want to be enabled for all applications built for the board.

In the case of our board, DevAcademy L3E1, it’s a development kit, so we want to add UART, RTT and GPIO support. Therefore, we will append the following:

# Enable RTT
CONFIG_USE_SEGGER_RTT=y

# enable GPIO
CONFIG_GPIO=y

# enable uart driver
CONFIG_SERIAL=y

# enable console
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

Note

<boardname>_defconfig is a Kconfig fragment merged as-is into the final build of any application built for the specified board, and must enable the bare minimum. It’s the application configuration’s (prj.conf) responsibility to configure what is needed.

If your board has multiple board qualifiers (i.e., different board targets or variants), you need to specify the qualifiers in the name of the file (e.g., devacademyl3e1_<qualifiers>_defconfig) for it to take effect when a certain qualifier is passed to the build system.

Kconfig.defconfig

The Kconfig.defconfig file defines board-specific default values for Kconfig options. The content of this file is wrapped in if /endif blocks that correspond to specific board targets. This file is automatically generated by the tool and complements the defconfig file by setting defaults that only apply when building for a particular board.

Let’s see the example for our board which has a single board target devacademyl3e1/nrf52833.

if BOARD_DEVACADEMYL3E1

config BT_CTLR
	default BT

endif # BOARD_DEVACADEMYL3E1
Kconfig

The CONFIG_BT_CTLR Kconfig option, which enables support for the SoC native Bluetooth LE controller implementation, is only enabled if CONFIG_BT is selected by the application.

If the board has multiple board targets, you can have multiple if/endif blocks for the different board targets.

For example, in the Kconfig.defconfig file for the nRF54L15 DK.

The remaining optional files are:

  • board.cmake: Used to add Flash and debug support to the board.
  • CMakeLists.txt: Used to include source files that should be executed pre- or post-kernel. For example, if your hardware requires custom mux configurations or needs to be configured in a particular way, it can be added to this file. This is done for the nRF52840 Dongle where board_nrf52840dongle_nrf52840_init() is executed at PRE_KERNEL_1 before the kernel. Note that the extension does not create the CMakeLists.txt file; you need to manually create it if needed.
  • doc/index.rst, doc/devacademyl3e1.png: Documentation and image of the board, only needed if you are Contributing your board to Zephyr.
  • Kconfig: Allows you to create a custom Kconfig menu specific to your board.
  • devacademyl3e1.yml: A YAML file with miscellaneous metadata used by Zephyr’s Test Runner (Twister). If your board has multiple qualifiers, you need to have a .yml for each.

Board revisions

When you create new hardware revisions for your board, such as changes to the schematics or a new PCB layout, you do not need to create a completely new board definition. Instead, you can simply add the revision-specific files within the same board folder, devacademyl3e1_<revision>.conf and devacademyl3e1_<revision>.overlay, and update board.yml to include the revision.

Keep in mind that if your board has multiple board qualifiers, you need to specify the .conf and .overlay files to the affected qualifiers, e.g., devacademyl3e1_<qualifiers>_<revision>.conf, devacademyl3e1_<qualifiers>_<revision>.overlay.

  • devacademyl3e1_<revision>.conf: The optional Kconfig settings specified here will be merged into the board’s default Kconfig configuration.
  • devacademyl3e1_<revision>.overlay: The optional devicetree overlay will be overlayed with the board-level devacademyl3e1.dts devicetree file.
  • board.yml: The revision: property controls how the Zephyr build system matches the <board_name>@<revision> string specified by the user when building an application for the board.

Note

When creating a new custom board, it is always a good idea to start looking into the SDK-defined boards with the same SoC/SiP as your custom board for inspiration. There is a long list of Development Kits, Prototyping Platforms, and Reference designs already shipped in the SDK that can serve as a good starting point.

They are available in two locations <install_path>/zephyr/boards/nordic/ and <install_path>/nrf/boards/nordic/

See the Zephyr Board Porting Guide.

v2.9.0 – v2.7.0

Note

This lesson covers how to define boards in the nRF Connect SDK using both hardware models v1 and v2 (HWMv1 and HWMv2 respectively).

This exercise tab covers nRF Connect SDK where HWMv2 is used, which is recommended for all new designs.

In this topic, we will explore the different options for creating custom board files and the guidelines for naming your custom board.

We will cover the mandatory and optional files required to define a custom board in HWMv2, as well as how to create a revision of the board. We will study these files one by one and understand their role.

In Exercise 1 of this lesson, we will use the Create a new board GUI in the nRF Connect for VS Code extension to define a new board, and populate most of the mandatory files’ content.

Board terminology (in HWMv2)

In Hardware Model version 2, each board has a unique board name (sometimes referred to as the board ID).

The Create a new board GUI function in the nRF Connect for VS Code extension will ask you to provide both a board name and a human-readable name for your board. The human-readable name can include white spaces or capital letters (e.g., My nRF54L DK, DevAcademyL3E1), and is intended for display purposes and documentation. The board name is commonly a lower-case and underscore-separated version of the human-readable name (e.g., my_nrf54l_dk, devacademyl3e1).

Definition

Human-readable name (full_name) is the descriptive name for the board, which can include spaces and capital letters. The full name is intended for display purposes and documentation, making it easier for users to recognize the board.

Board name is typically a lowercase, underscore-separated version of the human-readable name, with all whitespaces replaced by underscores. The board name uniquely and descriptively identifies a particular system, but does not include additional information that may be required to actually build an image.

When naming your custom board, you need to give your board a unique name. Run west boards in the nRF Connect Terminal for a list of names that have already been taken; you can’t name your custom board with a name that is already in use.

Below is an example of the output:

esp32c3_042_oled
96b_aerocore2
nrf52840dongle
nrf5340dk
nrf54l15dk
thingy53
nrf52_sparkfun
Terminal

Note

In HWMv2, the name of the SoC is no longer needed at the end of the board name. Instead, this is specified explicitly in one of the files in the board definition (board.yml file).

In addition to the board name, a board will have one or more board qualifiers.

Let’s examine the board terminology used in HWMv2, using the BL5340 DVK from Ezurio as an example, which is based on the nRF5340 SoC.

  • Board target: The full string that can be provided to any of the Zephyr build tools (e.g., west) to compile and link an image for a particular hardware system. Boards with single-core SoCs typically have one board target, while more advanced boards with multiple SoCs or multi-core SoCs will have several board targets.
  • Board name: The name of the board without spaces.
  • Board revision (optional): This is used to capture new changes in new hardware versions (new schematics, new PCB).
  • Board qualifiers: The set of additional tokens, separated by a forward slash / that follows the board name (and optionally board revision).
    • SoC: The specific SoC used on the board.
    • CPU cluster: This is defined by the SoC layer. If the SoC does not have any clusters, this is omitted.
    • Variant: In the context of board qualifiers, a variant designates a particular type or configuration of a build for a combination of SoC and CPU clusters. Common uses of the variant concept include introducing both secure and non-secure builds for platforms with Trusted Firmware-M support, or selecting the type of RAM used in a build. Another use of variants is for different builds of hardware (not a revision). For example, if you have a board that includes sensors and another exact one that does not include sensors.

Consider a board with the human-readable name DevAcademy L3E1, based on the nRF52833 SoC. The board will have the board name devacademyl3e1, and the board target devacademyl3e1/nrf52833. The board can have an optional revision that can be specified as [email protected]/nrf52833 and it could have an optional variant [email protected]/nrf52833/sense.

Note

The CPU clusters are defined by the SoC layer, and the nRF52833 SoC does not have any clusters.

Location of custom board

Before diving into the board files that make up the custom board definition, we need to know where to put the files.

When working with custom boards, you have three main options for where to place the board definition files. Each option has its own advantages and limitations:

  • Out-of-Tree (dedicated directory): In this approach, your board files are stored outside of the nRF Connect SDK/Zephyr tree in a separate directory. You’ll configure the build system to locate and use these external board files. This method is ideal for closed-source projects where you want to keep board definitions private. This is the method we’ll focus on in this lesson.
  • Upstream in Zephyr: Choose this option if you’re developing a development kit, module, reference design, or prototyping platform that you intend to share with the Zephyr community. It’s also appropriate for open-source products. Board definitions submitted upstream must include documentation and go through a review and approval process by the Zephyr maintainers.
  • Inside the application’s boards folder: This option is suitable for quick prototyping or debugging. You can place the board files directly in a boards subdirectory within your application folder. This is a convenient approach for temporary or experimental work.

Board files

Consider our new development kit DevAcademy L3E1 which is based on the nRF52833 SoC. The board name for this board will be devacademyl3e1.

When creating a custom board definition, remember that the SDK provides the hardware layer files from Architecture up to SoC. So, we only need to populate the board layer. The board layer consists of these four mandatory files.

boards/<vendor>/devacademyl3e1
├── board.yml
├── Kconfig.devacademyl3e1
├── devacademyl3e1.dts
└── devacademyl3e1-pinctrl.dtsi 

The term <vendor> serves as a placeholder for the vendor name.

Mandatory files

Let’s take a close look at the four mandatory files in the board layer.

1. board.yml

The board.yml file is a required component introduced in Hardware Model v2 (HWMv2). Each board folder must contain one board.yml, and it serves as a central configuration file that defines key properties for your board.

  • Board name: Defines the board name or names.
  • SoC selection: At least one SoC must be specified.
  • Revisions: Optional; used to define specific hardware versions.
  • Variants: Used for special configurations, such as enabling TF-M or using a different CPU core.

While it’s technically possible to define multiple boards in one folder using a single board.yml, this is not a common use case.

When you use the extension tool and input the board name, SoC, SoC variant, and vendor, the board.yml file is generated automatically. In most cases, you won’t need to manually edit it.

Here is what a board.yml file typically looks like. You could also include full_name: in board.yml to specify the human-readable name of your board.

Let’s take a look at the board.yml files for some Nordic development kits.

board.yml examples
  1. Single board target: The nRF52840 dongle is based on the nRF52840 SoC, a single-core device with no CPU clusters.
  2. Quad board target: The nRF54L15 has two CPU clusters defined by the SoC layer, cpuapp and cpuflpr. The board.yml defines a new variant, xip, which is associated with cpuflpr. It also defines another variant called ns (TF-M enabled) associated with the cpuapp. So in total, there are 4 board targets.
  3. Dual board target with revisions: The nRF9161 DK has no CPU clusters defined by the nRF9161 SiP. There is a variant, ns. It also defines two revisions: 0.9.0 (default) and 0.7.0.

2. Kconfig.devacademyl3e1

This file serves a specific and essential purpose: it selects the SoC(s) used by the board. By doing so, it pulls in the appropriate hardware layer files from Architecture up to SoC. It also defines a Kconfig symbol for the board, which is the board name prefixed with BOARD_ .

  • It contains select statement(s) 
    • Only select is needed for a single-board target
    • select … if statements are needed for multi-core SoCs or multi-SoC boards

Here are some examples:

Below is an example of our devacademyl3e1 (single board target) that we will develop in Exercise 1, which is based on the nRF52833 QIAA.

config BOARD_DEVACADEMYL3E1
	select SOC_NRF52833_QIAA

Here is another example for the nRF54L15 DK (quad board target). The file selects the appropriate SoC support layer based on the normalized board target triggered from the build system.

3. devacademyl3e1.dts

The board-level devicetree file is a hardware description written in the devicetree format. It represents the schematics of your board, detailing its physical components and connections.

It includes connectors and any other hardware components such as LEDs, buttons, sensors, or communication peripherals (USB, BLE controller, etc). Memory partitioning is also done in this file. We will rely heavily on the automation provided by the nRF Connect for VS Code extension, including the Devicetree Visual Editor, to help us populate this file.

If your board has multiple board qualifiers (i.e., different board targets or variants), you need to create a separate board-level devicetree file for each board target. You can structure the board-level devicetree file into multiple files to improve readability and maintainability.

4. devacademyl3e1-pinctrl.dtsi

This file defines the pin-mapping of your board’s peripherals.

If your board has multiple board qualifiers (i.e., different board targets or variants), you need to create a separate pin-mapping file for each board target.

Optional files

Now that we’ve covered the four mandatory files in the board layer, let’s take a look at the optional files.

Below is a board layer consisting of all mandatory files, optional, and special use cases files:

boards/<vendor>/devacademyl3e1
├── board.yml
├── Kconfig.devacademyl3e1
├── devacademyl3e1_<qualifiers>.dts 
├── devacademyl3e1_<qualifiers>-pinctrl.dtsi
├── devacademyl3e1_<qualifiers>_defconfig
├── Kconfig.defconfig
├── board.cmake # Used for flash and debug
├── CMakeLists.txt  # Needed in special cases 
├── c_files.c  # Needed in special cases
├── doc # Optional 
│   ├── devacademyl3e1.png
│   └── index.rst
├── Kconfig # Optional to create a board Kconfig options menu
├── devacademyl3e1_<qualifiers>.yml # Optional for Test Runner (Twister)
├── devacademyl3e1_<qualifiers>_<revision>.conf # Needed to support hardware revisions
├── devacademyl3e1_<qualifiers>_<revision>.overlay  #Needed to support hardware revisions
└── dts # Optional 
    └── bindings

The term <vendor> serves as a placeholder for the vendor name. If the board has qualifiers (<qualifiers>), such as multiple SoCs, CPU clusters, or variants (e.g., multi-board target), these qualifiers must be appended to the board name to clearly indicate where you want these files to apply.

devacademyl3e1_defconfig

The devacademyl3e1_defconfig file is a Kconfig fragment that is merged as-is into the final build of any application built for the specified board.

Here is the default devacademyl3e1_defconfig file generated by the tool (differs from one SoC to another).

# Copyright (c) 2024 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

CONFIG_ARM_MPU=y
CONFIG_HW_STACK_PROTECTION=y

In addition to the default Kconfig symbols, we need to manually include any additional Kconfig symbols that we want to be enabled for all applications built for the board.

In the case of our board, DevAcademy L3E1, it’s a development kit, so we want to add UART, RTT and GPIO support. Therefore, we will append the following:

# Enable RTT
CONFIG_USE_SEGGER_RTT=y

# enable GPIO
CONFIG_GPIO=y

# enable uart driver
CONFIG_SERIAL=y

# enable console
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

Note

<boardname>_defconfig is a Kconfig fragment merged as-is into the final build of any application built for the specified board, and must enable the bare minimum. It’s the application configuration’s (prj.conf) responsibility to configure what is needed.

If your board has multiple board qualifiers (i.e., different board targets or variants), you need to specify the qualifiers in the name of the file (e.g., devacademyl3e1_<qualifiers>_defconfig) for it to take effect when a certain qualifier is passed to the build system.

Kconfig.defconfig

The Kconfig.defconfig file defines board-specific default values for Kconfig options. The content of this file is wrapped in if /endif blocks that correspond to specific board targets. This file is automatically generated by the tool and complements the defconfig file by setting defaults that only apply when building for a particular board.

Let’s see the example for our board which has a single board target devacademyl3e1/nrf52833.

if BOARD_DEVACADEMYL3E1

config BT_CTLR
	default BT

endif # BOARD_DEVACADEMYL3E1
Kconfig

The CONFIG_BT_CTLR Kconfig option, which enables support for the SoC native Bluetooth LE controller implementation, is only enabled if CONFIG_BT is selected by the application.

If the board has multiple board targets, you can have multiple if/endif blocks for the different board targets.

For example, in the Kconfig.defconfig file for the nRF54L15 DK.

The remaining optional files are:

  • board.cmake: Used to add Flash and debug support to the board.
  • CMakeLists.txt: Used to include source files that should be executed pre- or post-kernel. For example, if your hardware requires custom mux configurations or needs to be configured in a particular way, it can be added to this file. This is done for the nRF52840 Dongle where board_nrf52840dongle_nrf52840_init() is executed at PRE_KERNEL_1 before the kernel. Note that the extension does not create the CMakeLists.txt file; you need to manually create it if needed.
  • doc/index.rst, doc/devacademyl3e1.png: Documentation and image of the board, only needed if you are Contributing your board to Zephyr.
  • Kconfig: Allows you to create a custom Kconfig menu specific to your board.
  • devacademyl3e1.yml: A YAML file with miscellaneous metadata used by Zephyr’s Test Runner (Twister). If your board has multiple qualifiers, you need to have a .yml for each.

Board revisions

When you create new hardware revisions for your board, such as changes to the schematics or a new PCB layout, you do not need to create a completely new board definition. Instead, you can simply add the revision-specific files within the same board folder, devacademyl3e1_<revision>.conf and devacademyl3e1_<revision>.overlay, and update board.yml to include the revision.

Keep in mind that if your board has multiple board qualifiers, you need to specify the .conf and .overlay files to the affected qualifiers, e.g., devacademyl3e1_<qualifiers>_<revision>.conf, devacademyl3e1_<qualifiers>_<revision>.overlay.

  • devacademyl3e1_<revision>.conf: The optional Kconfig settings specified here will be merged into the board’s default Kconfig configuration.
  • devacademyl3e1_<revision>.overlay: The optional devicetree overlay will be overlayed with the board-level devacademyl3e1.dts devicetree file.
  • board.yml: The revision: property controls how the Zephyr build system matches the <board_name>@<revision> string specified by the user when building an application for the board.

Note

When creating a new custom board, it is always a good idea to start looking into the SDK-defined boards with the same SoC/SiP as your custom board for inspiration. There is a long list of Development Kits, Prototyping Platforms, and Reference designs already shipped in the SDK that can serve as a good starting point.

They are available in two locations <install_path>/zephyr/boards/nordic/ and <install_path>/nrf/boards/nordic/

See the Zephyr Board Porting Guide.

v2.6.2 – v2.5.2

Important

This lesson covers how to define boards in the nRF Connect SDK using both hardware models v1 and v2 (HWMv1 and HWMv2 respectively).

This exercise tab is for nRF Connect SDK v2.6.2 – v2.5.2, where HWMv1 is used. HWMv1 is deprecated and removed in nRF Connect SDK v3.0.0. We recommend using HWMv2 for all new designs (other tabs).

In this topic, we will explore the different options for creating custom board files and the guidelines for naming your custom board. You can watch the video below or read the lesson text.

We will cover the mandatory and optional files required to define a custom board, as well as how to create a revision of the board. We will study these files one by one and understand their role.

In Exercise 1 of this lesson, we will use the Create a new board GUI in the nRF Connect for VS Code extension to define a new board, and populate most of the mandatory files’ content.

Naming your custom board

When naming your custom board, there are some conventions that you need to follow.

  • You need to give your board a unique name. Run west boards in the nRF Connect Terminal for a list of names that have already been taken; you can’t name your custom board with a name that is already in use.
  • It’s recommended that your board name include the name of the SoC at the end. For instance, suppose we want to make a new board called DevAcademy, which is based on the nRF52833 SoC. It’s highly recommended that you call your board “DevAcademy nRF52833”.

Note that the Create a new board GUI in nRF Connect for VS Code extension will ask you to provide a human-readable name for your board (e.g., DevAcademy nRF52833), and it will automatically generate the board name (devacademy_nrf52833).

Definition

Human-readable name (full_name) is the descriptive name for the board, which can include spaces and capital letters. The full name is intended for display purposes and documentation, making it easier for users to recognize the board.

Board name is typically a lowercase, underscore-separated version of the human-readable name, with all whitespaces replaced by underscores. The board name uniquely and descriptively identifies a particular system, but does not include additional information that may be required to actually build an image.

Location of custom board

Before diving into the board files that make up the custom board definition, we need to know where to put the files.

When working with custom boards, you have three main options for where to place the board definition files. Each option has its own advantages and limitations:

  • Out-of-Tree (dedicated directory): In this approach, your board files are stored outside of the nRF Connect SDK/Zephyr tree in a separate directory. You’ll configure the build system to locate and use these external board files. This method is ideal for closed-source projects where you want to keep board definitions private. This is the method we’ll focus on in this lesson.
  • Upstream in Zephyr: Choose this option if you’re developing a development kit, module, reference design, or prototyping platform that you intend to share with the Zephyr community. It’s also appropriate for open-source products. Board definitions submitted upstream must include documentation and go through a review and approval process by the Zephyr maintainers.
  • Inside the application’s boards folder: This option is suitable for quick prototyping or debugging. You can place the board files directly in a boards subdirectory within your application folder. This is a convenient approach for temporary or experimental work.

Board files

Consider our new development kit DevAcademy nRF52833, which is based on the nRF52833 SoC. The board name generated for this board will be devacademy_nrf52833.

When creating a custom board definition, remember that the SDK provides the hardware layer files from Architecture up to SoC. So, we only need to populate the board layer. The board layer consists of these five mandatory files.

boards/<ARCH>/devacademy_nrf52833
├── Kconfig.board
├── Kconfig.defconfig
├── devacademy_nrf52833_defconfig
├── devacademy_nrf52833.dts
└── devacademy_nrf52833-pinctrl.dtsi 

The term <ARCH> serves as a placeholder for the architecture. The extension will automatically populate this with the architecture used by the SoC, as we will see in exercise 1.

Mandatory files

Let’s take a close look at the five mandatory files in the board layer.

1. Kconfig.board

The Kconfig.board file is automatically generated by the extension, and we typically don’t need to change anything inside it. This file defines a Kconfig symbol for your board BOARD_DEVACADEMY_NRF52833 and it specifies a dependency to the SoC hardware support layer (through the depends on keyword).

# Copyright (c) 2023 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

config BOARD_DEVACADEMY_NRF52833
	bool "DevAcademy nRF52833"
	depends on SOC_NRF52833_QIAA

2. Kconfig.defconfig

The Kconfig.defconfig file defines board-specific default values for Kconfig options. The extension automatically generates this file, and we typically don’t need to change anything inside it.

The content of this file is wrapped in if /endif blocks that correspond to specific board targets, as shown below.

When the developer passes the selected target board, BOARD_DEVACADEMY_NRF52833 is set, along with CONFIG_BOARD. The CONFIG_BT_CTLR Kconfig option, which enables support for the SoC native Bluetooth LE controller implementation, is only enabled if CONFIG_BT is selected by the application. This is added here because the nRF52833 SoC is widely used for Bluetooth LE applications.

# Copyright (c) 2023 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

if BOARD_DEVACADEMY_NRF52833

config BOARD
	default "devacademy_nrf52833"

config BT_CTLR
   default BT

endif

3. devacademy_nrf52833_defconfig

The devacademyl3e1_nrf52833_defconfig file is a Kconfig fragment that is merged as-is into the final build of any application built for the specified board.

The default Kconfig symbols that are generated by the extension are:

  • Series hardware support, in the case of the nRF52833 SoC, this is CONFIG_SOC_SERIES_NRF52X , which will enable the CPU and architecture support.
  • SoC hardware support, CONFIG_SOC_NRF52833_QIAA
  • Board hardware support
  • MPU, if the hardware supports it.

Below is the default devacademy_nrf52833_defconfig file generated by the tool.

# Copyright (c) 2023 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

CONFIG_SOC_SERIES_NRF52X=y
CONFIG_SOC_NRF52833_QIAA=y
CONFIG_BOARD_DEVACADEMY_NRF52833=y

# Enable MPU
CONFIG_ARM_MPU=y

# Enable hardware stack protection
CONFIG_HW_STACK_PROTECTION=y

In addition to the default Kconfig symbols, we need to manually include any additional Kconfig symbols that we want to be enabled for all applications built for the board.

In the case of our board, DevAcademy nRF52833, it’s a development kit, so we want to add UART, RTT and GPIO support. Therefore, we will append the following:

# Enable RTT
CONFIG_USE_SEGGER_RTT=y

# enable GPIO
CONFIG_GPIO=y

# enable uart driver
CONFIG_SERIAL=y

# enable console
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

# additional board options
CONFIG_GPIO_AS_PINRESET=y

CONFIG_PINCTRL=y

Note

<boardname>_defconfig is a Kconfig fragment merged as-is into the final build of any application built for the specified board, and must enable the bare minimum. It’s the application configuration’s (prj.conf) responsibility to configure what is needed.

4. devacademy_nrf52833.dts

The board-level devicetree file is a hardware description written in the devicetree format. It represents the schematics of your board, detailing its physical components and connections.

It includes connectors and any other hardware components such as LEDs, buttons, sensors, or communication peripherals (USB, BLE controller, etc). Memory partitioning is also done in this file. We will rely heavily on the automation provided by the nRF Connect for VS Code extension, including the Devicetree Visual Editor, to help us populate this file.

5. devacademy_nrf52833-pinctrl.dtsi

This file defines the pin-mapping of your board’s peripherals.

The extension does not create this file, so we must create it ourselves, which we will learn in Exercise 1 of this lesson.

Optional files

Now that we’ve covered the five mandatory files in the board layer, let’s take a look at the optional files.

Below is a board layer consisting of all mandatory files, optional, and special use cases files:

boards/<ARCH>/devacademy_nrf52833
├── Kconfig.board 
├── Kconfig.defconfig 
├── devacademy_nrf52833_defconfig
├── devacademy_nrf52833.dts 
├── devacademy_nrf52833-pinctrl.dtsi
├── board.cmake # Used for flash and debug
├── CMakeLists.txt  # Needed in special cases 
├── c_files.c  # Needed in special cases
├── doc # Optional 
│   ├── devacademy_nrf52833.png
│   └── index.rst
├── Kconfig # Optional to create a board Kconfig options menu
├── devacademy_nrf52833.yaml # Optional for Test Runner (Twister)
├── devacademy_nrf52833_<revision>.conf     # Needed to support multiple hardware revisions
├── devacademy_nrf52833_<revision>.overlay  # Needed to support multiple hardware revisions
└── revision.cmake # Needed to support multiple hardware revisions
└── dts # Optional 
    └── bindings

The optional files are:

  • board.cmake: Used to add Flash and debug support to the board.
  • CMakeLists.txt: Used to include source files to be executed pre- or post-kernel. For example, if your hardware requires custom mux configurations or needs to be configured in a particular way, it can be added to this file. This is done for the nRF52840 Dongle where board_nrf52840dongle_nrf52840_init() is executed at PRE_KERNEL_1 before the kernel. Note that the extension does not create the CMakeLists.txt file; you need to manually create it if needed.
  • doc/index.rst, doc/devacademy_nrf52833.png: Documentation and image of the board, only needed if you are Contributing your board to Zephyr.
  • Kconfig: Allows you to create a custom Kconfig menu specific to your board.
  • devacademy_nrf52833.yaml: A YAML file with miscellaneous metadata used by Zephyr’s Test Runner (Twister).

Board revisions

When you create new hardware revisions for your board, such as changes to the schematics or a new PCB layout, you do not need to create a completely new board definition. Instead, you can simply add the revision-specific files within the same board folder: devacademy_nrf52833_<revision>.conf, devacademy_nrf52833_<revision>.overlay and revision.cmake

  • devacademy_nrf52833_<revision>.conf: The optional Kconfig settings specified here will be merged into the board’s default Kconfig configuration.
  • devacademy_nrf52833_<revision>.overlay: The optional devicetree overlay will be added to the common devacademy_nrf52833.dts devicetree file.
  • revision.cmake: Controls how the Zephyr build system matches the <board>@<revision> string specified by the user when building an application for the board.

Note

When creating a new custom board, it is always a good idea to start looking into the SDK-defined boards with the same SoC/SiP as your custom board for inspiration. There is a long list of Development Kits, Prototyping Platforms, and Reference designs already shipped in the SDK that can serve as a good starting point.

They are available in two locations <install_path>/zephyr/boards/nordic/ and <install_path>/nrf/boards/nordic/

See the Zephyr Board Porting Guide.

Register an account
Already have an account? Log in
(All fields are required unless specified optional)

  • 8 or more characters
  • Upper and lower case letters
  • At least one number or special character

Forgot your password?
Enter the email associated with your account, and we will send you a link to reset your password.