Zephyr quick tip: Show what menuconfig changed and make changes persistent

The Zephyr project uses the KConfig system to select what subsystems and libraries are included in the build of your project. Sometime this is really simple, like adding CONFIG_GPIO=y when you need to use input/output pins. That’s easy enough to add manually. But things get more complex when you don’t know which configuration you need, or you want to fine tune a value like stack size.

In this post, we’re going to look at how to make changes in menuconfig, but also how to check those changes and make them permanent.

Turning on a watchdog timer

If you want to use the watchdog timer subsystem in Zephyr you need to add CONFIG_WATCHDOG=y to your build. That’s not entirely easy to figure out as the Watchdog entry in the Zephyr docs doesn’t mention it. There is some sample code called Task Watchdog and you can see the symbol is enable in the project configuration file, but there are other symbols related to watchdog timers in there as well. Which ones do we need?

I like to use menuconfig to work out these issue. It’s something we’ve talked about a few times before, and Marcin and Chris even filmed walkthrough of menuconfig system. The first step is to build your project before trying to enable the new configuration. This is necessary to generate the initial configuration for the project; if your project has a build error, you can’t load up menuconfig. Here I’m building for an nRF52840 feather board:

west build -b adafruit_feather_nrf52840 my_app_directory -p

Notice I’m using the -p directive for a “pristine” build. This makes sure that anything in the build directory is generated fresh so we are certain that we begin with a clean build.

Next, use west build -t menuconfig to launch the interactive configuration menu:

Zephyr menuconfig

Zephyr menuconfig

My most-used feature is the forward-slash ( / ) which brings up a text search. I searched for “watchdog” and two similar options came up.

I find that the options with helper text (“Watchdog Support” in this example) next to them are the best items to choose. Pressing enter on that entry takes me to the configuration item where I use the space bar to select it, indicated by an asterisk. That’s it, I’m not going any deeper right now. Pressing q brings up the exit menu, don’t forget to save your changes.

Zephyr kind of takes care of the rest, automatically pulling in a bunch of other options based on the top-level option I enabled. But those are actually why I’m writing this article. How can I see what changes other were made by “under the hood” by menuconfig?

Seeing changes made by menuconfig

Running a build command on a Zephyr project pulls in configurations from all over the place (eg: the board’s default configuration from the Zephyr tree, the project’s prj.conf file, and any .conf files in the boards directory). These coalesce into the build/zephyr/.config file, which is what menuconfig loads and saves to. Luckily, before this happens it makes a copy called .config.old which we can compare using the diff command:

(.venv) [email protected] ~/golioth-compile/AgTech-Soil/fw $ diff build/zephyr/.config.old build/zephyr/.config
30c30
< # CONFIG_WATCHDOG is not set
---
> CONFIG_WATCHDOG=y
179c179,180
< # CONFIG_NRFX_WDT0 is not set
---
> CONFIG_NRFX_WDT=y
> CONFIG_NRFX_WDT0=y
813a815
> CONFIG_HAS_DTS_WDT=y
1046a1049,1057
> # CONFIG_WDT_DISABLE_AT_BOOT is not set
> # CONFIG_WDT_LOG_LEVEL_OFF is not set
> # CONFIG_WDT_LOG_LEVEL_ERR is not set
> # CONFIG_WDT_LOG_LEVEL_WRN is not set
> CONFIG_WDT_LOG_LEVEL_INF=y
> # CONFIG_WDT_LOG_LEVEL_DBG is not set
> CONFIG_WDT_LOG_LEVEL=3
> # CONFIG_WDT_COUNTER is not set
> CONFIG_WDT_NRFX=y

Check that out! Enabling CONFIG_WATCHDOG automatically pulls in the CONFIG_NRFX_WDT because of the chip used in my project. Be we also learn some interesting things here. It looks like some Nordic chips have multiple watchdog timers as CONFIG_NRFX_WDT0 is selected. If we search in menuconfig for that symbol and type ? on the entry we can get more information on what that’s all about:

Nordic watchdog timer instance info

The help screen in menuconfig for CONFIG_NRFX_WDT0

You can see here that this symbol was enabled (y-selecting) by the WDT_NRFX symbol. So if you’re cruising through menuconfig and want to know why something is turned on, this is a handy way to track down those answers. Try bringing up the help screen for the CONFIG_WDT_COUNTER which is shown above but not enabled. I certainly learned something about this chip for doing so!

Making menuconfig changes persistent

Remember way back at the top of the article when I mentioned I was using a “pristine” build with the -p flag? If you do that now, you’ll lose your menuconfig changes. So make sure you do an incremental build (just don’t use the pristine flag) to test those changes out. But eventually you will want to make them persistent.

The solution for that is easy. Use the diff trick I showed above to confirm what symbols were changed by your menuconfig selections, and add those changes to the prj.conf or board-specific .conf files. Once you commit these to your revision control, you’ll be certain to compile in the options you need for future projects.

Stop by our Discord or our Forum for more quick tips about Zephyr and your next IoT project!