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.
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.
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.
Start the discussion at forum.golioth.io