How to use Kconfig

Description

KConfig is a language that describe application’s settings. It is used here to describe how we want the SDK to behave.

KConfig comes with a graphical interface, menuconfig, to configure these settings according to your application.

This release of KConfig features works only by building your application with CMake. See How to use CMake guide for more information.

Prerequisites

  • Kconfig uses GAP_SDK_HOME environnement. Be sure that it has been set before running menuconfig command.

  • You need to export the following environnement variable. Please add it to your .bashrc or its equivalent.

export KCONFIG_CONFIG="sdk.config"

How it works

Menuconfig graphical interface is built from SDK’s Kconfig files. Each one describes a list of options. It is recommended to distribute KConfig options into several Kconfig files, one per SDK stage.

KConfig files are organized as a tree. It means that a root Kconfig file will call sub Kconfig files and so on. At the end, all Kconfig files’ content will be visible from menuconfig interface.

Here is an example of a KConfig file related to the RTOS folder of the SDK:

menu "RTOS Menu"
    choice PMSIS_OS
        prompt "OS Selection"
        config PMSIS_OS_FREERTOS
            bool "Freertos"
            help
                Select FreeRTOS as GAP SDK OS. Default value
    endchoice
    if PMSIS_OS_FREERTOS
        source "$(GAP_SDK_HOME)/rtos/pmsis/os/freeRTOS/Kconfig"
    endif
    menu "PMSIS Menu"
        source "$(GAP_SDK_HOME)/rtos/pmsis/Kconfig"
        source "$(GAP_SDK_HOME)/rtos/pmsis/os/freeRTOS/vendors/gwt/gap9/pmsis/Kconfig"
        source "$(GAP_SDK_HOME)/rtos/pmsis/os/freeRTOS/vendors/gwt/pmsis/rtos/Kconfig"
    endmenu
    source "$(GAP_SDK_HOME)/rtos/pmsis/bsp/Kconfig"
endmenu

Menuconfig interface is executed from CMake command. See How to use CMake guide for more information. Here, you can select what options you want to set for your application.

Once you are done, Menuconfig produces an output file named sdk.config. This file described all enabled options.

Here is an example of what the sdk.config file look like:

#
# Helloworld Menu
#
CONFIG_HELLOWORLD_CLUSTER=y
# end of Helloworld Menu
#
# GAP SDK Menu
#
# General options
#
CONFIG_CHIP_FAMILY_GAP9=y
CONFIG_PLATFORM_GVSOC=y
# CONFIG_PLATFORM_BOARD is not set
CONFIG_BOARD_GAP9_EVK=y
# CONFIG_BOARD_GAP9_EVK_AUDIO_ADDON is not set
# CONFIG_BOARD_GAP9_V2 is not set

Then, CMake uses a python script to parse this output file to be able to read it. Basically, it consists in setting variable to a specific value in a new file named cmake.config.

Here is an example of what cmake.config look like:

# Helloworld Menu
set(CONFIG_HELLOWORLD_CLUSTER y)
# GAP SDK Menu
set(CONFIG_CHIP_FAMILY_GAP9 y)
set(CONFIG_PLATFORM_GVSOC y)
set(CONFIG_BOARD_GAP9_EVK y)

These variables are then tested in CMake configuration process to add sources to compile and add flags to the compilation process.

How to add a new option

Depending on what is the purpose of your option, you need first to identify where it belong. Usually, it will be discribed in a Kconfig file located next to the files that will be impacted by your option.

  • Assuming that you will create an option for a SDK’s software component that has not been covered yet, you need first to create the Kconfig file.

  • In it, create a menu with a revelant name and describe your options. Check “Resources” section to learn kconfig syntax.

  • Then, you need to link your new Kconfig file with an existing one that will be its parent using the source keyword. At this point, your options are visible in the menuconfig interface.

  • Then you need to apply effects related to your option. In a CMakeLists.txt file located next to your Kconfig file and your option’s related source files, you can check your option in the following way:

if(DEFINED CONFIG_<your_option_name>)
    #Add flag
    target_compile_options(<your_target> PRIVATE "-D<your_flag_name>")
    list(APPEND TARGET_SOURCE_FILES "another_src_file_to_compile.c")
endif()

In the helloworld example, an option consists in enabling cluster cores to print hello as the fabric controller.

if(DEFINED CONFIG_HELLOWORLD_CLUSTER)
    message(STATUS "[${TARGET_NAME} Options] Cluster enabled")
    target_compile_options(${TARGET_NAME} PRIVATE "-DCONFIG_HELLOWORLD_CLUSTER=1")
else()
    message(STATUS "[${TARGET_NAME} Options] Cluster disabled")
endif()

Warning

During the generation of sdk.config, all options name are prepend by CONFIG_. Please don’t forget to add it while testing your options in CMakeList files. In the future this feature can be canceled in the python parsing process.

In the following helloworld example, the flag CONFIG_HELLOWORLD_CLUSTER is then tested in a #ifdef preprocessor macro:

#if defined(CONFIG_HELLOWORLD_CLUSTER)
void pe_entry(void *arg)
{
    printf("Hello from (%d, %d)\n", pi_cluster_id(), pi_core_id());
}

void cluster_entry(void *arg)
{
    pi_cl_team_fork(0, pe_entry, 0);
}
#endif

int main(void)
{
#if defined(CONFIG_HELLOWORLD_CLUSTER)
    pi_device_t cluster_dev;
    struct pi_cluster_conf cl_conf;
    struct pi_cluster_task cl_task;

    pi_cluster_conf_init(&cl_conf);
    pi_open_from_conf(&cluster_dev, &cl_conf);
    if (pi_cluster_open(&cluster_dev))
    {
        return -1;
    }
    pi_cluster_send_task_to_cl(&cluster_dev, pi_cluster_task(&cl_task, cluster_entry, NULL));
    pi_cluster_close(&cluster_dev);
#endif

    printf("Hello\n");

    return 0;
}

Resources

Kconfig documentation : https://www.kernel.org/doc/html/latest/kbuild/kconfig-language.html