### Compile Time Configuration for RIOT --- ### Agenda - Current state - Proposal - Let's talk about it --- ### Current state (I) - Configuration of modules using **macros**, overwritten in Makefiles or passed as CFLAGS. ```shell CFLAGS=-DGNRC_PKTBUF_SIZE=1500 make all term ``` - Checking of values and logic between options are handled using C pre-processor. --- ### Current state (II) - Board hardware configuration (clocks, peripherals, pinmux) for boards is defined in `periph_conf.h` files. - External devices (radios, sensors, actuators) are configured with `xxx_params.h` files. --- ### Motivation (I) - Many configuration parameters are not validated. - It's hard to describe inter-dependency logic using pre-processor. - Lack of conditional exposure of parameters: - If a module is not used or hardware not available its configuration options should not be exposed. - It's not easy to get the applied configurations for a particular build. --- ### Motivation (II) - Knowledge of CPU specific params is required in order to port a new board. - Lots of code duplication. - Few checks of valid hardware configurations. --- ## Requirements (I) - Conditional exposure of configuration options. - Check invalid configurations. - Conditional default values and inter-dependency logic. --- ## Requirements (II) - Get the applied configurations for a given build. - Reuse configurations among similar hardware. - Expose only relevant information to the user. --- ## Proposed approach --- ### Kconfig - It is a [language](https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt) used, together with tools, to configure software (Linux Kernel). - Solves exposure, restriction and dependencies between parameters. - Reference tools maintained in the Kernel repo. - Has proven to work for many years. --- ### Kconfig - Some features - Conditional (with complex logic expressions) and dynamic handling of default values. - Restrictions (ranges, choices, etc.) and type validation of parameters. - The output is a header file (or a `.config` file with `make` syntax). --- ### How can it be used in RIOT? #### <span> <!-- .element: class="fragment" data-fragment-index="1" --> Let's see examples </span> --- #### Kconfig for Gcoap ```config menuconfig KCONFIG_MODULE_GCOAP bool "Configure Gcoap" help "Enable this to configure Gcoap module using Kconfig." if KCONFIG_MODULE_GCOAP menu "Buffer Sizes" config GCOAP_PDU_BUF_SIZE int "Request or response buffer size" default 128 config GCOAP_REQ_OPTIONS_BUF int "Request buffer reduction" default 4 help "Reduce payload length by this value for a request." ``` --- #### Menuconfig for Gcoap ![menuconfig-gcoap-1](https://i.imgur.com/7XZHCEM.png) ![menuconfig-gcoap-2](https://i.imgur.com/XHM6Gic.png) --- #### Kconfig for GNRC IPv6 nib ```config menuconfig KCONFIG_MODULE_GNRC_IPV6_NIB bool "GNRC IPv6 NIB" help "Enable to configure GNRC IPv6 NIB with Kconfig." if KCONFIG_MODULE_GNRC_IPV6_NIB config GNRC_IPV6_NIB_NUMOF int "Number of entries in NIB" default 16 if MODULE_GNRC_IPV6_NIB_6LBR default 1 if MODULE_GNRC_IPV6_NIB_6LN && !GNRC_IPV6_NIB_CONF_6LR default 4 help "Number of entries in NIB." endif # KCONFIG_MODULE_GNRC_IPV6_NIB ``` --- #### Menuconfig for GNRC IPv6 nib ![menuconfig](https://i.imgur.com/wVB2kMB.png) --- ### Integration with the build system - **Opt-in**: Allow to configure RIOT as usual, explicitly enable Kconfig. - **Progressive adoption**: No need to migrate all modules at once. - Dependencies are resolved by the build system (`USEMODULE`), during the first phase. - Generated artifacts in `bin` folder. - Kconfig file structure mirrors modules structure. --- ### How things could look like after migration? - Kconfig allows to select needed modules and solves dependencies. - Modules can be configured using Kconfig (menuconfig, guiconfig or `.config` files). - Tools can be built on top of this (e.g. web visualizations). - ~~Hardware can be configured using Kconfig~~ --- ### Why not use this for **hardware** configuration? - Not scalable and lots of code duplication. - Exposes too much information that the user shouldn't see. - Has already been [tried](https://elinux.org/images/b/b8/DTWorkshop2017_Zephyr.pdf), and failed. - This problem was already solved some years ago... --- ## Approach: **Device Tree** --- ### Device Tree - Data structure to describe multi-platform hardware. - [Standarized](https://github.com/devicetree-org/devicetree-specification/releases/download/v0.3-rc2/devicetree-specification-changebars-v0.3-rc2.pdf) and OS agnostic. - Broadly used and developed. --- ### How does it work? - Hardware is described using the **DTS** language: - The device is defined by a tree of nodes (CPUs, peripherals, external devices, etc.). - Each node has a set of properties, and may have children. --- ### Flatten Device Tree ```graphviz digraph hierarchy { // Global styles nodesep=1.0 // increases the separation between nodes splines=curved node [color=darkolivegreen4, fontname=Courier,shape=box] edge [color=grey40] // Definition of nodes b1[fillcolor=darkseagreen3, style=filled, label="board (nucleo-l452re)"] b2[fillcolor=darkseagreen3, style=filled, label="board (nucleo-l476rg)"] m1[label="stm32l452re"] m2[label="stm32l476rg"] fam[label="stm32l4"] u1[label="USART1"] s1[label="SPI1"] i1[label="I2C1"] g[label="GPIO"] o[label="Others"] // Connection of nodes b1->m1->fam b2->m2->fam fam->{u1 s1 i1 g o} } ``` --- ### How does it work? - `.dts` files can include other files (`.dtsi`) - Reuse node definitions (e.g. Linux) - It's possible to override previously defined functionalities: - Change properties values, add/delete nodes. - e.g. the root DTS file (usually the board) can configure peripherals. --- ### Let's see it in action --- ### How does it work? - Device Tree Binary (DTB) generated from a root DTS file: - C preprocessor - [Device Tree Compiler](https://git.kernel.org/pub/scm/utils/dtc/dtc.git) (maintained by Linux Kernel) - The DTB holds all the information that describes the hardware - In Linux this blob file is read on boot --- ### Bindings - Set of usage conventions (schema) - Define how data should appear in the tree to describe typical hardware characteristics: - SPI nodes are described by MISO, MOSI, memory addresses. - AT86RF2XX nodes are described by the used SPI bus, CS, pins (reset, sleep, interrupt) - A sensor connected to the I2C bus would be described with an address, interrupt pin, etc. --- ### Bindings Could be for example: - Documentation - YAML - Python classes --- ### Device Tree compilation ```graphviz digraph hierarchy { // Global styles nodesep=1.0 // increases the separation between nodes splines=curved rankdir="LR" node [color=darkolivegreen4, fontname=Courier,shape=box] edge [color=grey40] // Definition of nodes dtsi[label=".dtsi files (CPU, devices...)"] dts[label="<board>.dts"] cp[label="C preprocessor"] dtc[label="Device Tree Compiler"] dtb[label="Flatten DT Blob"] {dtsi dts}->cp->dtc->dtb } ``` --- ### How can it be used on RIOT? ```graphviz digraph hierarchy { // Global styles nodesep=1.0 // increases the separation between nodes splines=curved rankdir="LR" node [color=darkolivegreen4, fontname=Courier,shape=box] edge [color=grey40] // Definition of nodes dtb[label="Flatten DT Blob"] bd[label="Bindings"] proc[label="Processing and validation"] doc[label="Documentation"] bm[label="periph_conf.h"] {dtb bd}->proc->{doc bm} } ``` --- ### Advantages - Scalable. - Define only once. - Can easily add support for new hardware: - A rev board or a shield can be described as an overlay - Reuse hardware description: - Family, peripheral. - External DTS files. - Changes on peripheral structures shouldn't change the hardware description. --- ### Pitfalls - It's necessary to write DTS files for every CPU family and board. - Parsing using bindings is necessary as DTB is not loaded during boot time. - Migration would take some time. --- ### Integration with KConfig 1. Device tree declares the hardware. 2. Kconfig exposes software configurations for the needed modules for that hardware. --- ### How it could look after migration - Generate board pinout - Check pin conflicts - Generate periph conf - DT not mandatory --- ## Let's talk about it!
{"metaMigratedAt":"2023-06-14T23:42:24.044Z","metaMigratedFrom":"YAML","title":"Compile Time configuration proposal","breaks":true,"slideOptions":"{\"theme\":\"solarized\"}","contributors":"[{\"id\":\"4a906b41-6f8f-48ef-8454-9d6aadfab718\",\"add\":13103,\"del\":9996},{\"id\":\"0ded3a8a-00f6-4140-89f0-0f18fa004fdf\",\"add\":3761,\"del\":603}]"}
    453 views