### 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


---
#### 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

---
### 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}]"}