Kconfig

From Wiki at Neela Nurseries
Revision as of 22:00, 19 July 2023 by Ted (talk | contribs) (Add subsection "Kconfig select to conditionally set symbol")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Zephyr RTOS building blocks   ::   Device Tree Source   ::   Kconfig   ::   cmake   ::   `west` manifest files


Keywords: multi-core dual-core SECOND_CORE_BOOT_ADDRESS_MCUX code-cpu1-partition


This Neela Nurseries page dedicated to notes on Kconfig configuration system, and language. Some useful Kconfig links are given in the first section of this wiki page. One thing of note, it looks like as of 2022 Q4 Kconfig is parsed, processed, and or otherwise supported in part by Python based scripts. While Python does not have a fixed variable name length limit, Kconfig in contrast support variable names only up to forty or so characters in length. Longer variable name choices in Kconfig files appear to have an effect of silent variable assignment failures.

Another less than obvious failure during a project compilation which involves Kconfig processing as a step, is that a second assignment to an already defined and assigned variable, e.g. using Kconfig's ':=' operator or syntax, results in a syntax error message. Contributor to this article Ted surmises that this is due to the variable already being expanded to its first assigned value when the second mistakenly expressed assignment is reached during the project build process.

In both these cases, however, the error messages from Kconfig processor are not obvious pointers to the problems at hand!



^ Starting Points and Good References

A good starting point is at Zephyr's latest documentation as of Zephyr 3.2.99. The following link is itself one of five Zephyr docs pages linked from a parent doc page:

This Zephyr documentation page is linked in Ulf Magnusson's kconfiglib homepage on Github. This homepage looks to be a good starting point for a full and in depth reading about this Kconfig parser and code generator tool set.


Need to revisit this link to identify its specific topics . . .

Some more useful articles on Kconfig, hosted at Nordic Semi:

Above Kconfig articles linked to from https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/build/index.html#kconfig.


^ Ulf Magnusson kconfiglib.py

Ulf Magnusson is author of python based kconfigpy project, which is hosted on github. This utility is adopted by Zephyr Project and is responsible at build time for the parsing and provision of Kconfig related resources to a project's build steps.

On 2022-12-29 Ted encountering a strange error when attempting to `rsource` a local, small small Kconfig file from the second core firmware project of a dual-core project. First core configures fine, passing both dts and Kconfig parsing and configuration steps. Second, "external" project for core 2 fails. Ulf Magnusson's scripts support `rsource` or "source via relative path" directive. Following link shows that a community member made a pull request for this support about five years ago:


^ To Invoke Menuconfig From Other Than Project Root

If `zephyr_app` is a project, possibly a "remote" project in a multicore project, and is located two directories below the root of the larger mulitcore, effectively multi-app project, then the following invocation will succeed in opening Kconfig's interactive `menuconfig` interface:

    $ west build -b [target_board] -t menuconfig -- -DBOARD_ROOT=../..

In this command invocation "target_board" is one of Zephyr's supported boards, and or possibly Nordic Semi ncs supported boards, or a custom board of the reader's own making. Zephyr supported ARM based boards are located in `[west_workspace]/zephyr/boards/arm`. A few common name examples of these boards include `lpcxpresso55s69`, `nrf9160dk_nrf9160` and `sparkfun_thing_plus_nrf9160`.

Note also that the `BOARD_ROOT` path value passed along to cmake and not to `west` itself, may vary depending upon a given project's structure. Single core Zephyr apps generally have a simpler directory structure, while dual-core and multi-core Zephyr apps often have additional directory trees to organize firmware projects for secondary and successive cores. Sometimes the board root relative path will be just one parent directory from the current working directory. [NEED: to give example project and invocation paths showing how BOARD_ROOT is chosen.]

In case you are targeting a board or circuit design of your own, then you likely know what you're doing and what this argument needs to express.


^ Kconfig Interactive Use To Enable IIS2DH

Following messages do not show the interactive, ncurses based Kconfig configuration program. But these do show where Kconfig stores a modified configuration file in a given project:

ted@localhost:~/projects/zephyr-based/z4-sandbox-kionix-work/kionix-driver-demo$ west build -t menuconfig
-- west build: running target menuconfig
[0/1] cd /home/ted/projects/zephyr-based/z4-sandbox-kionix-work/kionix-dri...ed/projects/zephyr-based/z4-sandbox-kionix-work/kionix-driver-demo/Kconfig
Loaded configuration '/home/ted/projects/zephyr-based/z4-sandbox-kionix-work/kionix-driver-demo/build/zephyr/.config'
Configuration saved to '/home/ted/projects/zephyr-based/z4-sandbox-kionix-work/kionix-driver-demo/build/zephyr/.config'

ted@localhost:~/projects/zephyr-based/z4-sandbox-kionix-work/kionix-driver-demo$


^ Kconfig formatting and variable names

Kconfig variable name length appears to have a finite length rule, which when broken causes a silent failure of Kconfig processing tools to assign a value to the given variable. The following Expressif documentation page goes into a bit of detail on this topic:

A summary excerpt from this Expressif page is:


Kconfig Formatting Rules

The following attributes of Kconfig files are standardized:

    Within any menu, option names should have a consistent prefix. The prefix length is currently set to at least 3 characters.

    The indentation style is 4 characters created by spaces. All sub-items belonging to a parent item are indented by one level deeper. For example, menu is indented by 0 characters, the config inside of the menu by 4 characters, the help of the config by 8 characters and the text of the help by 12 characters.

    No trailing spaces are allowed at the end of the lines.

    The maximum length of options is set to 40 characters.

    The maximum length of lines is set to 120 characters.

Format checker

tools/check_kconfigs.py is provided for checking the Kconfig formatting rules. The checker checks all Kconfig and Kconfig.projbuild files in the ESP-IDF directory and generates a new file with suffix .new with some recommendations how to fix issues (if there are any). Please note that the checker cannot correct all rules and the responsibility of the developer is to check and make final corrections in order to pass the tests. For example, indentations will be corrected if there isn’t some misleading previous formatting but it cannot come up with a common prefix for options inside a menu.

Note: Expressif's Kconfig format checker looks like an interesting tool. NEED to investigate this script - 2022-12-23 Friday.


^ How To Set Kconfig Symbols

Kconfig helper symbols, like the example here in symbol `CPU_HAS_FPU`:


^ Kconfig select to conditionally set symbol

Kconfig's `select` keyword must be used carefully. It is however used in several Zephyr RTOS out-of-tree drivers for sensors which can be attached, one at a time, to two or more types of communications bus. In a local Zephyr source tree some of these examples may be located by running the following recursive grep search:

 $ ~/local_path_to_zephyr_project_root/zephyr$ grep -nr 'select I2C if'


^ Kconfig Build Time Artifacts

Following file generated by build system, most likely by kconfiglib.py and associated python scripts, lists all the Kconfig files read and parsed to form a project's kernel symbol based configuration. This file may be used to confirm or rule out that a particular Kconfig language file is included during the configuration phase of a project's build:

 $[$project_top_dir]/build/apps/cpu1/zephyr/kconfig$ ls
  include  sources.txt


^ Kconfig NXP dual core setting

In Zephyr 3.2.0 representing a Zephyr RTOS Project with several years' maturity and development, there are yet just a few projects which support multi-core micro-controllers (MCUs). This most likely reflects that a large number of 32-bit MCUs in 2022 are yet single core. Zephyr multi-core sample applications have an interesting way, in the Zephyr source tree, of obtaining the second core's boot address from device tree source.

There are a few levels of indirection to get from the original declaration and assignment of a core's firmware boot address in device tree, into the project's source code. Zephyr's build system generates a certain amount of header files and C sourced code early in a project's build process. Namely these generated C sources cover a lot of the system or MCU initialization tasks.

One of Zephyr's multi-core samples is found in `zephyr/samples/drivers/ipm/ipm_mcux`. In case this "leading edge / main branch" link goes stale for some change in Zephyr Project directory structure, we here not that v3.2.0 Zephyr release has commit hash 4256cd41df6c60f1832fd2deb14edc30ac7debab.

Searching for this Kconfig symbol from Zephyr project root:

ted@localhost1:~/projects-sandbox/workspace-out-of-tree/zephyr$ grep -nr SECOND_CORE_BOOT_ADDRESS_MCUX ./*
./boards/arm/lpcxpresso55s69/CMakeLists.txt:25:			-offset ${CONFIG_SECOND_CORE_BOOT_ADDRESS_MCUX}
./soc/arm/nxp_lpc/lpc54xxx/Kconfig.soc:54:config SECOND_CORE_BOOT_ADDRESS_MCUX
./soc/arm/nxp_lpc/lpc54xxx/soc.c:134:#define CORE_M0_BOOT_ADDRESS ((void *)CONFIG_SECOND_CORE_BOOT_ADDRESS_MCUX)
./soc/arm/nxp_lpc/lpc55xxx/Kconfig.soc:135:config SECOND_CORE_BOOT_ADDRESS_MCUX
ted@localhost1:~/projects-sandbox/workspace-out-of-tree/zephyr$

From file `zephyr/soc/arm/nxp_lpc/lpc55xxx/Kconfig.soc`:

118 code-cpu1-partition
119 config SECOND_CORE_MCUX
120         bool "LPC55xxx's second core"
121         depends on HAS_MCUX
122         help
123           Driver for second core startup
124 
125 config SECOND_IMAGE_MCUX
126         depends on SECOND_CORE_MCUX
127         string "Binary image of second core's code"
128         help
129           This points to the image file for the the binary code that will be
130           used by the second core.
131 
132 # Workaround for not being able to have commas in macro arguments
133 DT_CHOSEN_Z_CODE_CPU1_PARTITION := zephyr,code-cpu1-partition
134 
135 config SECOND_CORE_BOOT_ADDRESS_MCUX
136         depends on SECOND_CORE_MCUX
137         hex "Address the second core will boot at"
138         default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_CODE_CPU1_PARTITION))
139         help
140           This is the address the second core will boot from.
141 
142 endif # SOC_SERIES_LPC55XXX

We need to search further and understand how the Kconfig stanza at line 138 in excerpt just above works. This line appears to make use of what may be a Kconfig function, as discussed in this Zephyr 3.2.0 document on Custom Kconfig Preprocessor Functions.

ted@localhost1:~/projects-sandbox/workspace-out-of-tree/zephyr$ grep -nr DT_CHOSEN_Z_CODE_CPU1_PARTITION ./*
./soc/arm/nxp_lpc/lpc55xxx/Kconfig.soc:133:DT_CHOSEN_Z_CODE_CPU1_PARTITION := zephyr,code-cpu1-partition
./soc/arm/nxp_lpc/lpc55xxx/Kconfig.soc:138:	default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_CODE_CPU1_PARTITION))
Binary file ./soc/arm/nxp_lpc/lpc55xxx/.Kconfig.soc.swp matches

ted@localhost1:~/projects-sandbox/workspace-out-of-tree/zephyr$ grep -nr zephyr,code-cpu1-partition ./*
./boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.dts:39:		zephyr,code-cpu1-partition = &slot1_partition;
./boards/arm/lpcxpresso55s69/CMakeLists.txt:20:	#offset is taken from zephyr,code-cpu1-partition
./soc/arm/nxp_lpc/lpc55xxx/Kconfig.soc:133:DT_CHOSEN_Z_CODE_CPU1_PARTITION := zephyr,code-cpu1-partition
Binary file ./soc/arm/nxp_lpc/lpc55xxx/.Kconfig.soc.swp matches

ted@localhost1:~/projects-sandbox/workspace-out-of-tree/zephyr$ cd ./boards/arm/lpcxpresso55s69

ted@localhost1:~/projects-sandbox/workspace-out-of-tree/zephyr/boards/arm/lpcxpresso55s69$ ls
board.cmake     Kconfig.defconfig               lpcxpresso55s69_cpu1_defconfig  lpcxpresso55s69_ns_defconfig  pinmux.c
CMakeLists.txt  lpcxpresso55s69_cpu0_defconfig  lpcxpresso55s69_cpu1.dts        lpcxpresso55s69_ns.dts        pre_dt_board.cmake
doc             lpcxpresso55s69_cpu0.dts        lpcxpresso55s69_cpu1.yaml       lpcxpresso55s69_ns.yaml
Kconfig.board   lpcxpresso55s69_cpu0.yaml       lpcxpresso55s69.dtsi            lpcxpresso55s69-pinctrl.dtsi

ted@localhost1:~/projects-sandbox/workspace-out-of-tree/zephyr/boards/arm/lpcxpresso55s69$ grep -nr slot1_partition ./*
./lpcxpresso55s69_cpu0.dts:39:		zephyr,code-cpu1-partition = &slot1_partition;
./lpcxpresso55s69_cpu1.dts:23:		zephyr,code-partition = &slot1_partition;
./lpcxpresso55s69.dtsi:129:		slot1_partition: partition@30000 {
./lpcxpresso55s69_ns.dts:31:		zephyr,code-partition = &slot1_partition;

ted@localhost1:~/projects-sandbox/workspace-out-of-tree/zephyr/boards/arm/lpcxpresso55s69$

^ A Simpler Search

A search for setting and meaning of `zephyr,sram-cpu1-partition`:

The token `zephyr,code-cpu1-partition` seems important, as it is the value assigned to DT_CHOSEN_Z_CODE_CPU1_PARTITION in ./soc/arm/nxp_lpc/lpc55xxx/Kconfig.soc:133. A search for part of this token gives the following `grep` search results labeled here (1). From these results we see most lines are build artifacts from compiling a couple of samples in the local Zephyr source tree. But the very first result looks like a device tree source line, which declares a device tree alias:

Grep search results 1

ted@localhost1:~/projects-sandbox/workspace-out-of-tree/zephyr$ grep -nr code-cpu1-partition ./*
./boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.dts:39:		zephyr,code-cpu1-partition = &slot1_partition;
./boards/arm/lpcxpresso55s69/CMakeLists.txt:20:	#offset is taken from zephyr,code-cpu1-partition
./samples/drivers/ipm/ipm_mcux/build/zephyr/zephyr.dts:13:		zephyr,code-cpu1-partition = &slot1_partition;
Binary file ./samples/drivers/ipm/ipm_mcux/build/zephyr/edt.pickle matches
./samples/drivers/ipm/ipm_mcux/build/zephyr/dts.cmake:7:set_target_properties(devicetree_target PROPERTIES "DT_CHOSEN|zephyr,code-cpu1-partition" "/soc/peripheral@50000000/flash-controller@34000/flash@0/partitions/partition@30000")
./samples/drivers/ipm/ipm_mcux/build/zephyr/zephyr.dts.pre:853:  zephyr,code-cpu1-partition = &slot1_partition;
./samples/drivers/ipm/build/zephyr/zephyr.dts:13:		zephyr,code-cpu1-partition = &slot1_partition;
Binary file ./samples/drivers/ipm/build/zephyr/edt.pickle matches
./samples/drivers/ipm/build/zephyr/dts.cmake:7:set_target_properties(devicetree_target PROPERTIES "DT_CHOSEN|zephyr,code-cpu1-partition" "/soc/peripheral@50000000/flash-controller@34000/flash@0/partitions/partition@30000")
./samples/drivers/ipm/build/zephyr/zephyr.dts.pre:853:  zephyr,code-cpu1-partition = &slot1_partition;
./soc/arm/nxp_lpc/lpc55xxx/Kconfig.soc:133:DT_CHOSEN_Z_CODE_CPU1_PARTITION := zephyr,code-cpu1-partition
ted@localhost1:~/projects-sandbox/workspace-out-of-tree/zephyr$

File ./boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.dts:39 contains the following excerpted code:

 17         cpus {
 18                 /delete-node/ cpu@1;
 19         };
 20 
 21         aliases{
 22                 sw0 = &user_button_1;
 23                 sw1 = &user_button_2;
 24                 sw2 = &user_button_3;
 25                 watchdog0 = &wwdt0;
 26                 /* For pwm test suites */
 27                 pwm-0 = &sc_timer;
 28                 pwm-led0 = &red_pwm_led;
 29                 red-pwm-led = &red_pwm_led;
 30                 sdhc0 = &sdhc0;
 31                 accel0 = &mma8652fc;
 32                 sdhc0 = &sdif;
 33         };
 34 
 35         chosen {
 36                 zephyr,sram = &sram0;
 37                 zephyr,flash = &flash0;
 38                 zephyr,code-partition = &slot0_partition;
 39                 zephyr,code-cpu1-partition = &slot1_partition;
 40                 zephyr,sram-cpu1-partition = &sram3;
 41                 zephyr,console = &flexcomm0;
 42                 zephyr,shell-uart = &flexcomm0;
 43                 zephyr,entropy = &rng;
 44         };

Ahh and from this we see token `zephyr,sram-cpu1-partition` is not a device tree alias but rather a "Zephyr chosen". This looks like it may be similar to a device tree alias. Must confirm . . .