A computer chip labelled SoC has five arrows pointing to five different circuit boards

Use Zephyr SoC config files to streamline hardware types

Zephyr’s inheritance scheme for configuration (and Devicetree) is pretty slick. The RTOS already has everything set up–from the System on Chip (SoC), to the board definition–so that you just need to add a config and overlay file to your application. Boards inherit almost everything from upstream definitions, but these files make tweaks for your specific use. Did you know that you can target the SoC itself in your application? Today, let’s take a look at how to use an application socs folder to configure multiple boards that use the same processor.

Example: Golioth Reference Design Template

Golioth’s Reference Designs are open source applications you can start from when building out your IoT devices. They are based on the Reference Design Template which supports three different boards that all use the nRF9160 cellular modem.

Up to this point we’ve copied the network configuration into separate .conf files for all three boards in the boards directory of the application. Here’s what that file tree looks like:

boards
├── aludel_elixir_nrf9160_ns.conf
├── aludel_elixir_nrf9160_ns.overlay
├── aludel_mini_nrf9160_ns.conf
├── aludel_mini_nrf9160_ns.overlay
├── nrf9160dk_nrf9160_ns.conf
└── nrf9160dk_nrf9160_ns.overlay

Without focusing on the details, a visual comparison of these files shows that most of the settings are the same for all three configurations.

Three configuration files shown side by side to visually compare the similarities

We can combine the SOC-based common configuration from all three of these boards into a single file. Most likely we will still a files to configure each variant, but they will only have a few lines in them containing configuration specific to that board type.

Determining the common SOC

If you’ve kept up with recent developments in Zephyr you know that hardware model v2 was adopted this year with the release of Zephyr v3.7.0. This made a change in device names so that they take the following format:

  • aludel_elixir/ns
  • aludel_mini/nrf9160/ns
  • nrf9160dk/nrf9160/ns

In this example, we see three different pieces of information separated by forward slashes: board name, SoC, and variant. There are a few other things that could be found in your board name, but let’s focus just on these.

For two of the boards, the nRF9160 is clearly shown in the SoC portion of the board name. However, the Aludel Elixir doesn’t include an SoC. Why is that?

The Elixir board is only built for the nRF9160 with no other SoCs in mind, so it’s been omitted from the board name. However, if you look in the custom board definition you’ll see that the board.yml file defines the upstream SoC:

board:
  name: aludel_elixir
  vendor: golioth
  revision:
    format: letter
    default: B
    exact: true
    revisions:
    - name: A
    - name: B
  socs:
    - name: nrf9160
      variants:
        - name: ns

Now that we know our common SoC, let’s move the common configuration to a file targeting that chip.

Target your SoC in an application-level configuration file

Configuration for an SoC is basically the same approach for boards. Just create a configuration file and place it in an socs directory at the root of your application. The west build system will give preference to your project version.

In this example, we create socs/nrf9160_ns.conf which also targets the ns variant that is used by all three boards.

boards
├── aludel_elixir_ns.conf
├── aludel_elixir_ns.overlay
├── aludel_mini_nrf9160_ns.conf
├── aludel_mini_nrf9160_ns.overlay
├── nrf9160dk_nrf9160_ns.conf
└── nrf9160dk_nrf9160_ns.overlay
socs
└── nrf9160_ns.conf

I moved all of the networking settings common to all three boards to the SoC configuration file. Seeing the change is jarring when we once again view the board config files side by side.

Side by side display of three different Zephyr board configuration files. Each has only one or two lines in them.

Using this approach, it is easy to immediately know what is different about each of the boards.

Benefits of common configuration

When the same configuration is copied to multiple board files, you’re bound to get out of sync and make errors. In fact, while writing this article I discovered a vestigial configuration in the config file for the Aludel Elixir.

When we converted our Golioth Ostentus code for use as a Zephyr driver module, I forgot to remove the library Kconfig symbol. It’s fine that it’s still there, but whenever there is an Ostentus node in the Devicetree overlay that library will be automatically selected so it doesn’t need to be in the board config. I didn’t notice it before. Now it’s obvious since the “noise” of the common network config code has been moved to the socs folder.

Give this approach a try with your own applications. It is certainly a lot easier to manage as you make updates for new versions of Zephyr.

Talk with an Expert

Implementing an IoT project takes a team of people, and we want to help out as part of your team. If you want to troubleshoot a current problem or talk through a new project idea, we're here for you.

Start the discussion at forum.golioth.io