Using Snippets in Zephyr: a Shorthand for Changing Build Configuration

Zephyr includes a concept called Snippets to assign a nickname to a set of configurations that may include both Kconfig and Devicetree changes. These are quite useful when you need to change more than one symbol and/or tweak your devicetree nodes for a particular build or test. Let’s take a tour of Zephyr Snippets today by focusing on a configuration change that enables the shell and logging.

Production Versus Testing

Snippets make a lot of sense in a bimodal atmosphere, such as the difference between production and testing. It’s unlikely that your production devices will have logging enabled, and you’ll likely disable the shell as well.

west build -p -b frdm_rw612 examples/zephyr/hello -S shell-logs

With snippets, you can configure your project to build with logging and shell disabled by default, then call your snippet to enable them for a debug session. The example above uses the -S flag to include a snippet called shell-logs in the build.

Let’s look at exactly what makes up this snippet.

Snippet: Common Configuration in a Nice Package

The example above calls a snippet that is made up of this file hierarchy.

snippets
└── shell_log
    ├── shell_log.conf
    └── snippet.yml

The snippet.yml file assigns the name of the snippet and adds the shell_log.conf file to the build as an extra config file.

name: shell-log
append:
  EXTRA_CONF_FILE: shell_log.conf

If we look in the config file, we see the symbols that are selected by this snippet:

CONFIG_LOG=y
CONFIG_LOG_MAX_LEVEL=4

CONFIG_SHELL=y
CONFIG_SHELL_BACKENDS=y
CONFIG_SHELL_BACKEND_SERIAL=y

The final piece in the puzzle is telling Zephyr where to find your snippet files. Do this by using a Zephyr module yaml file to specify where to look for the snippets folder, relative to your project’s root directory.

build:
  settings:
    snippet_root: .

While there is nothing magical happening in snippets, enabling this set of symbols with one human-readable (and memorable) snippet name is pretty nice. The same could be done by adding -- -DEXTRA_CONF_FILE=snippets/shell_log/shell_log.conf or by adding the symbols to the prj.conf file. But you can see why including the snippet argument is more convenient and less error-prone

While it is not demonstrated in this example, the concept is quite extensible. A Devicetree overlay file may be added alongside, or instead of the Kconfig file by adding EXTRA_DTC_OVERLAY_FILE: your_devicetree.overlay in the snippet file append section. Build flags are another option, and all of the additions presented by the snippet may be gated/conditionally included based on board name and domain (eg: when using sysbuild). In fact, let’s jump into some of the quirks that sysbuild brings and how to deal with them.

Using Snippets with Sysbuild (multi-domain builds)

The same snippet example above can be applied to multi-domain builds like Golioth’s firmware update sample.  The syntax looks very much the same but has some unintended consequences.

west build -p -b frdm_rw612 examples/zephyr/fw_update/ --sysbuild -S shell-log

If we look at the summary of the build for the mcuboot domain, we see our snippet grew the resource usage by quite a bit.

# mcuboot without shell-log snippet
Memory region         Used Size  Region Size  %age Used
           FLASH:       51996 B       128 KB     39.67%
             RAM:       44096 B       960 KB      4.49%
            SMU1:        510 KB       510 KB    100.00%
            SMU2:        140 KB       140 KB    100.00%
        IDT_LIST:          0 GB        32 KB      0.00%

# mcuboot with shell-log snippet
Memory region         Used Size  Region Size  %age Used
           FLASH:       77608 B       128 KB     59.21%
             RAM:       49424 B       960 KB      5.03%
            SMU1:        510 KB       510 KB    100.00%
            SMU2:        140 KB       140 KB    100.00%
        IDT_LIST:          0 GB        32 KB      0.00%

Flash usage for the bootloader is a whopping 50% more when including the snippet in the build command! Hey, that’s fine if you have the space available, which we do in this sample. However, the bootloader partition is commonly sized for the build without extra space and this snippet would cause the build to fail.

Most likely you are turning on shell and logging just to work with the application. But snippets are included in all domains during a sysbuild. The solution is to namespace your snippet inclusion.

west build -p -b frdm_rw612 examples/zephyr/fw_update/ --sysbuild -- -Dfw_update_SNIPPET="shell-log"

This is a slightly different approach which leverages cmake to add a list of snippets targeting one specific domain. In this case that’s fw_update, but could also have targeted only the bootloader by using -Dmcuboot_SNIPPET="name-of-your-snippet".

During the build, Zephyr will report the conf and overlay files included in the build so you can check for the expected files to confirm the snippet worked.

Parsing /home/mike/golioth-compile/golioth-firmware-sdk/modules/lib/golioth-firmware-sdk/examples/zephyr/fw_update/Kconfig
Loaded configuration '/home/mike/golioth-compile/golioth-firmware-sdk/zephyr/boards/nxp/frdm_rw612/frdm_rw612_defconfig'
Merged configuration '/home/mike/golioth-compile/golioth-firmware-sdk/modules/lib/golioth-firmware-sdk/examples/zephyr/fw_update/prj.conf'
Merged configuration '/home/mike/golioth-compile/golioth-firmware-sdk/modules/lib/golioth-firmware-sdk/examples/zephyr/fw_update/boards/frdm_rw612.conf'
Merged configuration '/home/mike/golioth-compile/golioth-firmware-sdk/modules/lib/golioth-firmware-sdk/snippets/shell_log/shell_log.conf'
Merged configuration '/home/mike/golioth-compile/golioth-firmware-sdk/modules/lib/golioth-firmware-sdk/build/fw_update/zephyr/.config.sysbuild'
Configuration saved to '/home/mike/golioth-compile/golioth-firmware-sdk/modules/lib/golioth-firmware-sdk/build/fw_update/zephyr/.config'
Kconfig header saved to '/home/mike/golioth-compile/golioth-firmware-sdk/modules/lib/golioth-firmware-sdk/build/fw_update/zephyr/include/generated/zephyr/autoconf.h'

Using Multiple Snippets

You may add as many snippets to your snippet directory as you like.

snippets
├── dev_sectag
│   ├── dev_sectag.conf
│   └── snippet.yml
└── shell_log
    ├── shell_log.conf
    └── snippet.yml

And then use more than one in your build.

west build -p -b frdm_rw612 examples/zephyr/hello -S shell-logs -S dev-sectag

Zephyr even has some snippets built-in. Many of them are tightly coupled to vendor-specific configurations. But some are quite useful, like using -S rtt-console to turn on console output when using Segger RTT.

What do you have planned for your own snippets? We’d love to hear about it, post your details in the Golioth forum!

Mike Szczys
Mike Szczys
Mike is a Senior Firmware Engineer at Golioth. His deep love of microcontrollers began in the early 2000s, growing from the desire to make more of the BEAM robotics he was building. During his 12 years at Hackaday (eight of them as Editor in Chief), he had a front-row seat for the growth of the industry, and was active in developing a number of custom electronic conference badges. When he's not reading data sheets he's busy as an orchestra musician in Madison, Wisconsin.

Post Comments

No comments yet! Start the discussion at forum.golioth.io

More from this author

Related posts

spot_img

Latest posts

Now on NXP’s Application Code Hub: Golioth Connectivity via the FRDM-MCXW71

Golioth's Bluetooth example using Pouch on the FRDM-MCXW71 and the FRDM-RW612 is now available on NXP's Application Code Hub (ACH).

Building Zephyr for the Raspberry Pi Pico2 W

The Raspberry Pi Pico2 W is the one with a microcontroller and Wi-Fi. When most people think of Raspberry Pi as a single-board computer...

How to Convince Your Manager to Use Golioth (As an Engineer)

If you’ve ever built an IoT product from the ground up, you know how it starts. The first prototype is always easy: you wire...

Want to stay up to date with the latest news?

Subscribe to our newsletter and get updates every 2 weeks. Follow the latest blogs and industry trends.