Interaction with Kconfig

The devicetree is closely related to kconfig. On one side, the devicetree aims to describe the hardware and on the other side, kconfig aims to tell what to do with it.

Kconfig is used to define a set of options to configure the GAP SDK environnement via a graphical interface: menuconfig. The following section explains how it interacts with the devicetree.

Hardware selection

As a first step, Menuconfig provides a Board menu containing a list of supported boards.

../../../_images/kconfig_select_hardware.png

Menuconfig board menu

Each board option in this list refers to a devicetree source file. Depending on which chip a board is based on, a related chip option (hidden from the user) will be automatically enabled and so its related devicetree source file.

Such kind of option must respect the following syntax to be correctly parsed after :

CONFIG_CHIP_<CHIPNAME> for a chip (hidden)

CONFIG_BOARD_<BOARDNAME> for a board

Warning

The CONFIG prefix is automatically added to the option name. Please, name your options without this prefix in Kconfig files.

Warning

Chip and board names must match their related .dts file name to be correctly linked.

Here is an example of the integration of the gap9mod board :

gap9mod_v1_0_b

As a result, depending on what option has been selected in the board menu, we get a list of dts files that will be compiled then merged to get a global and unique device tree blob (.dtb file) containing all data.

This devicetree blob file will be the input of the parser that will generate the C representation of the device tree.

../../../_images/from_menuconfig_to_main_dtb_file.png

Process to build the main devicetree blob file

Drivers selection

Menuconfig provides a Drivers menu where all the supported drivers of the selected hardware can be enabled. This menu adapt itself depending on the selected hardware in the board menu.

../../../_images/menuconfig_drivers_menu.png

Menuconfig drivers menu

Note

Enabling a driver means that the parser will pick the devicetree content refering to the physical peripheral with all its configuration data.

Such kind of option must respect the following syntax to be correctly parsed after :

CONFIG_DRIVER_<DRIVERNAME>

Note

Having CONFIG_DRIVER_MX25U51245G option enabled will select the mx25u51245g device from your board.

Default driver

For some driver categories, a default driver mechanism is implemented. It consists in automatically enable the driver of the category which is implemented on the selected board. This way, it is possible for an application to avoid making reference to a specific hardware.

As an example, if an application requires a flash but not one in particular, instead of having CONFIG_DRIVER_MX25U51245G option enabled (which is the flash of the Gap9mod board), CONFIG_DRIVER_TYPE_FLASH option can be enabled to get rid of the gap9mod reference.

Note

A driver category option name is build as the following : CONFIG_DRIVER_TYPE_<CATEGORYNAME>

Overriding devicetree configuration property

Menuconfig interface provides a way to override a property from the devicetree. As an example, the MX25U51245G flash device has a baudrate property set to 0 in the GAP9MOD dts file. This is the default value from the driver point of view (the frequency domain is applied n this case). When selecting the MX25U51245G driver, an user has the possibility to choose between the default setting or a custom one. In the second case, the value provided in the menuconfig interface will override the one from the device tree and will be outputed in the C-coded output file.

../../../_images/menuconfig_override_baudrate.png

Menuconfig interface - Overriding the MX25U51245G baudrate property

To create an option that override a device tree property, it must respect the following constraints:

  • Its name must be build as the following DRIVER_<DRIVERNAME>_CONF_PROPERTY_<PROPERTYNAME>

  • The property name must match the devicetree property name (but in capital letters)

  • The driver must possess such conf property to override

  • Its value must be compatible with C macro value

  • To get the devicetree’s property value, such option must not be defined.

As an example, here is the uart1 conf node in devicetree file :

conf
    {
        uart_id         = "1";
        baudrate_bps    = "CONFIG_DRIVER_UART1_CONF_PROPERTY_BAUDRATE_BPS";
        stop_bit_count  = "CONFIG_DRIVER_UART1_CONF_PROPERTY_STOP_BIT_COUNT";
        parity_mode     = "CONFIG_DRIVER_UART1_CONF_PROPERTY_PARITY_MODE";
        word_size       = "CONFIG_DRIVER_UART1_CONF_PROPERTY_WORD_SIZE";
        enable_tx       = "CONFIG_DRIVER_UART1_CONF_PROPERTY_ENABLE_TX";
        enable_rx       = "CONFIG_DRIVER_UART1_CONF_PROPERTY_ENABLE_RX";
        use_ctrl_flow   = "CONFIG_DRIVER_UART1_CONF_PROPERTY_USE_CTRL_FLOW";
        is_usart        =  "0";
        usart_polarity  = "CONFIG_DRIVER_UART1_CONF_PROPERTY_USART_POLARITY";
        usart_phase     = "CONFIG_DRIVER_UART1_CONF_PROPERTY_USART_PHASE";
        use_fast_clk    = "CONFIG_DRIVER_UART1_CONF_PROPERTY_USE_FAST_CLK";
    };

Here, some fields are fully handled by Kconfig. It means that the devicetree do not know any default configuration (because it is not its responsability). Only obvious fields like uart_id are set to a specific value.

Control a devicetree pad definition from Kconfig

As configuration options, it is possible to configure a pad from Kconfig interface and take advantage of the devicetree parser (auto SDK configuration).

To create an option that override a device tree pad property, it must respect the following syntax:

DRIVER_<DRIVERNAME>_PAD_PROPERTY_<PADNAME>

As an example, here is the pad subnode of the uart1 device :

pads
{
    tx  = "CONFIG_DRIVER_UART1_PAD_PROPERTY_TX";
    rx  = "CONFIG_DRIVER_UART1_PAD_PROPERTY_RX";
    rts = "CONFIG_DRIVER_UART1_PAD_PROPERTY_RTS";
    cts = "CONFIG_DRIVER_UART1_PAD_PROPERTY_CTS";
};

Here, the device has no default value set for its pad. One reason explaining this is they are not wired to exposed pads. Another reason is the devicetree is not responible of choosing the default configuration among several ones.

On Kconfig side, here are the definition of such options :

config DRIVER_UART1_PAD_PROPERTY_RX
    string
    default "GAP9_PADMUX(44, 0, PI_PAD_MUX_GROUP_UART1_RX)" if DRIVER_UART1_PAD_RX_DEFAULT || DRIVER_UART1_PAD_RX_DEFAULT
    default "GAP9_PADMUX(34, 0, PI_PAD_MUX_GROUP_UART1_RX)" if DRIVER_UART1_PAD_RX_34 || DRIVER_UART1_PAD_RX_34
    default "GAP9_PADMUX(35, 0, PI_PAD_MUX_GROUP_UART1_RX)" if DRIVER_UART1_PAD_RX_35 || DRIVER_UART1_PAD_RX_35
    default "GAP9_PADMUX(40, 0, PI_PAD_MUX_GROUP_UART1_RX)" if DRIVER_UART1_PAD_RX_40 || DRIVER_UART1_PAD_RX_40
    default "GAP9_PADMUX(41, 0, PI_PAD_MUX_GROUP_UART1_RX)" if DRIVER_UART1_PAD_RX_41 || DRIVER_UART1_PAD_RX_41
    default "GAP9_PADMUX(42, 0, PI_PAD_MUX_GROUP_UART1_RX)" if DRIVER_UART1_PAD_RX_42 || DRIVER_UART1_PAD_RX_42
    default "GAP9_PADMUX(43, 0, PI_PAD_MUX_GROUP_UART1_RX)" if DRIVER_UART1_PAD_RX_43 || DRIVER_UART1_PAD_RX_43
    default "GAP9_PADMUX(44, 0, PI_PAD_MUX_GROUP_UART1_RX)" if DRIVER_UART1_PAD_RX_44 || DRIVER_UART1_PAD_RX_44
    default "GAP9_PADMUX(45, 0, PI_PAD_MUX_GROUP_UART1_RX)" if DRIVER_UART1_PAD_RX_45 || DRIVER_UART1_PAD_RX_45
    default "GAP9_PADMUX(60, 0, PI_PAD_MUX_GROUP_UART1_RX)" if DRIVER_UART1_PAD_RX_60 || DRIVER_UART1_PAD_RX_60
    default "GAP9_PADMUX(61, 0, PI_PAD_MUX_GROUP_UART1_RX)" if DRIVER_UART1_PAD_RX_61 || DRIVER_UART1_PAD_RX_61
    default "GAP9_PADMUX(62, 0, PI_PAD_MUX_GROUP_UART1_RX)" if DRIVER_UART1_PAD_RX_62 || DRIVER_UART1_PAD_RX_62
    default "GAP9_PADMUX(63, 0, PI_PAD_MUX_GROUP_UART1_RX)" if DRIVER_UART1_PAD_RX_63 || DRIVER_UART1_PAD_RX_63
    default "GAP9_PADMUX(67, 0, PI_PAD_MUX_GROUP_UART1_RX)" if DRIVER_UART1_PAD_RX_67 || DRIVER_UART1_PAD_RX_67
    default "GAP9_PADMUX(68, 0, PI_PAD_MUX_GROUP_UART1_RX)" if DRIVER_UART1_PAD_RX_68 || DRIVER_UART1_PAD_RX_68

This option holds the classic pad syntax known from devicetree. Each value is conditionned by another option which is used by Kconfig internal mechanisms.

How to output a specific device node from a list using the same driver

By default, devicetree nodes are selected to be outputed in c files if a kconfig option match the right syntax with the device’s “driver_name” field from the sys node :

sys
{
    device_name     = "uart1";
    driver_name     = "uart";
    device_type     = "uart";
    device_driver   = "pmsis/drivers/uart.h";
};
config DRIVER_UART
    bool "Enable UART driver"

Since uart is a common driver for multiple physical peripheral, enabling such option will output all uart devices which is not wanted in almost all cases.

In devicetree files, the “sys” node of each device has a field name device_instance which can be targeted as the driver_name field. That way, it is possible to create a specific Kconfig option per driver instance and still be associated to the same driver.

sys
{
    device_name     = "uart1";
    driver_name     = "uart";
    device_type     = "uart";
    device_driver   = "pmsis/drivers/uart.h";
    driver_instance = "uart1";
};
config DRIVER_UART1
    bool "Enable UART1 driver"
  • Device driver : uart

  • Device instance : uart1

  • Kconfig option : CONFIG_DRIVER_UART1

Control a device name from Kconfig

For some application, a device may have a specific name for abstraction purpose. As an example, the gap9 chip devicetree offers 4 uart nodes. Their names are by default uart0, uart1, uart2, uart3, uart4.

Let’s say an application needs to stream some data via UART using the GAP9EVK USB cable. This feature’s configuration is first handled by Kconfig to specify the baudrate, other UART properties and finally which physical uart peripheral is used for that. On application side, the most convenient scenario is to have a device name that refer to the feature itself rather than the physical UART name in case the UART id changes in the future.

Devicetree parser and Kconfig offer a way to manage such situation:

Here is the sys node of the uart1 device from gap9 devicetree

sys
{
    device_name     = "uart1";
    driver_name     = "uart";
    driver_instance = "uart1";
    device_type     = "uart";
    device_driver   = "pmsis/drivers/uart.h";
    device_data     = "NULL";
};

By default, uart1 will be outputed PI_UART_UART1 in the code (PI_<DEVICE_TYPE>_<DEVICE_NAME>)

In Kconfig, it is possible to override the device_name by creating an string type option that respect the following syntax :

  • DRIVER_<DRIVER_NAME>_SYS_PROPERTY_<PROPERTY_NAME>

In our case, the option will be called : DRIVER_UART1_SYS_PROPERTY_DEVICE_NAME

Here is the option definition :

config DRIVER_UART1_SYS_PROPERTY_DEVICE_NAME
    string
    default "usb" if DRIVER_UARTUSB_ID_1_CHOICE
    default "uart1"

You can notice that this option has a default value “usb” that depends to another option : DRIVER_UARTUSB_ID_1_CHOICE and another one that depends on nothing. The independant is here to always manage the devicetree option. Therefore, the devicetree node can be written as the following :

sys
{
    device_name     = "CONFIG_DRIVER_UART1_SYS_PROPERTY_DEVICE_NAME";
    driver_name     = "uart";
    driver_instance = "uart1";
    device_type     = "uart";
    device_driver   = "pmsis/drivers/uart.h";
    device_data     = "NULL";
};

As a result, if DRIVER_UARTUSB_ID_1_CHOICE option is selected, the uart1 device name will be : usb. The outputed device enum that can be used by the application will be named PI_UART_USB.

If DRIVER_UARTUSB_ID_1_CHOICE option is not selected, the uart1 device name will be : uart1. The outputed device enum that can be used by the application will be named PI_UART_UART1.