Adding a Custom Board to Zephyr
When you are using Zephyr, you need to build your project for a specific “board”. Zephyr provides a number of boards out of the box, and you can also create your own custom boards. This tutorial shows you how to create a custom board.
Note that Zephyr’s terminology is a little confusing. A Zephyr “board” is not the same as a physical board (i.e. assembled PCB with components on it). A Zephyr board is a particular CPU instance. To quote directly from the Zephyr documentation:
Board: a particular CPU instance and its peripherals in a concrete hardware specification
Because a physical PCB may have a SoC with multiple CPUs, or even multiple SoCs which have multiple CPUs, the Zephyr definition is somewhat removed from intuition. It’s important to understand this distinction when building code.
This tutorial assumes your custom board has a nRF52840 SoC on it. However, the process is similar for other SoCs, just replace the nrf52840
with the appropriate SoC name.
Zephyr changes the way it defines boards in version ???.
Many MCU manufacturers provide example projects for their boards. These can be a great starting point for your own custom board. These boards are usually located in the Zephyr repo.
Folder Structure
There are a few different ways to structure a Zephyr project. I prefer to have the application code reside in a app/
directory, and all of the dependencies that are managed by west
inside a directory called external/
(you could this whatever you want, e.g. deps/
or libs/
). Before adding the custom board, this is what my folder structure looked like:
.west/└── configapp/├── CMakeLists.txt├── Kconfig├── Kconfig.zephyr├── main.cpp├── prj.conf└── west.ymlexternal/└── zephyr/
Having all the managed dependencies in a separate directory makes it easier to add a .gitignore
for them, reduces the clutter in your root directory, and makes it easier to wipe the directory if you suspect there might be a cache issue.
Decide on a Board Name
The board name is used to identify the board in a number of places. I recommend picking a name that is in lowercase, and contains only alphanumeric characters and underscores. For this example, we will use the name my_board
.
Add the Board Directory
Within our project root, create a boards/
directory. Inside that, create another directory called my_board/
.
There are a few required files we need to add to the board directory for it to be a valid board:
Kconfig.my_board
Kconfig.my_board
is a required file. As weird as this filename looks, yes, as per the Zephyr documentation, the extension has to be your board name! This file needs to select the correct SoC for the board.
config BOARD_MY_BOARD select SOC_NRF52840_QIAA
board.yml
board.yml
is a required file that provides metadata about the board, such as the name, vendor and SoC.
board: name: my_board full_name: My Board socs: - name: nrf52840
Specifying a Board Root
In your .west/config
file, specify the relative board root directory:
[build]cmake-args = -DBOARD_ROOT=../
This is the root directory of our project, which contains the boards
directory. My complete .west/config
file looked like this:
[manifest]path = appfile = west.yml
[build]cmake-args = -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DBOARD_ROOT=../
[zephyr]base = external/zephyr
Build
Now you should be able to build your project:
cd app/west build -b my_board/nrf52840
Note how the SoC you are building for is specified after a /
. If the SoC had multiple CPUs, the particular CPU you are building for would also be specified here.