Configuration¶
What this page covers: All Kconfig options, DeviceTree partition setup, and sizing guidelines for UBI.
Prerequisites: What is UBI? and Quick Start.
UBI is configured via Zephyr’s Kconfig system and DeviceTree overlays.
Kconfig Options¶
Enable UBI and pick its options in your prj.conf:
CONFIG_UBI_ENABLE=y
The full enumerated list of every Kconfig symbol — type, default, range, and description — lives in Kconfig Reference. The subsections below cover only the guide-shaped material: backend selection, sizing trade-offs, what each knob actually affects in production, and log levels.
Memory Backend¶
UBI supports two memory backends, selected at compile time via a Kconfig choice:
Static (
CONFIG_UBI_MEM_BACKEND_STATIC, default): All allocations usek_mem_slabpools sized at compile time. Provides deterministic RAM budget and full isolation from the application heap. Pool sizes are derived fromCONFIG_UBI_MAX_NR_OF_DEVICES,CONFIG_UBI_MAX_NR_OF_DATA_PEBS, andCONFIG_UBI_MAX_NR_OF_VOLUMES.Heap (
CONFIG_UBI_MEM_BACKEND_HEAP): Delegates tok_malloc/k_free(legacy behaviour). Useful for prototyping or when pool sizing is unknown.
When to use each:
Use case |
Recommended backend |
|---|---|
Production deployment |
STATIC — deterministic, no fragmentation |
Prototyping / unknown flash geometry |
HEAP — no pool sizing required |
Multiple UBI devices |
STATIC — set |
Memory Sizing Guide¶
Under the static backend, all pool memory is pre-allocated at compile time. The total RAM budget is:
Pool |
Formula |
Example (D=14, V=2) |
|---|---|---|
Device slab |
|
1 × 136 = 136 B |
Volume slab |
|
1 × 10 × 44 = 440 B |
Leaf slab |
|
1 × (14+10) × 16 = 384 B |
Scratch slab |
|
32 + 10 × 48 = 512 B (or 2×4096+16 = 8208 B with chunked) |
Total |
~1,464 B |
At init time, ubi_device_init() verifies that the actual flash geometry fits within the configured pools. If the flash partition has more data PEBs than CONFIG_UBI_MAX_NR_OF_DATA_PEBS, init returns -ENOMEM.
Impact Analysis¶
Option |
Flash layout |
RAM usage |
Recovery / robustness |
Performance |
|---|---|---|---|---|
|
No impact |
Pre-allocated pools (known at compile time) |
No fragmentation risk |
O(1) slab alloc |
|
No impact |
Dynamic; proportional to PEBs + volumes |
Subject to heap fragmentation |
k_malloc overhead |
|
No impact |
Multiplies all pool sizes |
No impact |
No impact |
|
No impact |
16 B per PEB in leaf slab |
Init fails if flash has more data PEBs |
No impact |
|
More reserved PEBs = fewer data PEBs |
+16 B per additional reserved PEB (RBT node) |
Higher = more redundancy for metadata; 3–4 adds cold spares |
No measurable impact |
|
Limits volume headers stored in reserved PEBs |
+48 B per volume + 16 B per volume RBT node |
No direct impact |
No measurable impact |
|
No impact |
No impact |
Higher = more chances to recover from transient write errors |
Higher = slower failure path (more retries) |
|
No impact |
No impact |
Higher = more aggressive bad block recovery attempts |
Higher = longer |
|
No impact |
No impact |
Higher = more erase attempts per bad PEB |
Higher = longer per-PEB torture |
Log Level¶
UBI uses Zephyr’s logging subsystem. Set the log level in prj.conf:
# Show only errors
CONFIG_UBI_LOG_LEVEL_ERR=y
# Debug everything
CONFIG_UBI_LOG_LEVEL_DBG=y
Flash Partition (DeviceTree)¶
UBI requires a named flash partition defined in a DeviceTree overlay. The partition label is referenced at compile time via FIXED_PARTITION_ID() and FIXED_PARTITION_DEVICE().
native_sim (simulator)¶
&flash0 {
erase-block-size = <8192>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
ubi_partition: partition@0 {
label = "ubi_partition";
reg = <0x00000000 DT_SIZE_K(128)>;
};
};
};
b_u585i_iot02a (STM32U5)¶
&flash0 {
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
ubi_partition: partition@d0000 {
label = "ubi_partition";
reg = <0x000d0000 DT_SIZE_K(128)>;
};
};
};
nrf5340dk/nrf5340/cpuapp (nRF5340 DK)¶
&flash0 {
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
ubi_partition: partition@f0000 {
label = "ubi_partition";
reg = <0x000f0000 DT_SIZE_K(64)>;
};
};
};
nRF5340 has 4 KB erase blocks (vs 8 KB on STM32U5). With 64 KB the partition yields 16 PEBs (2 reserved, 14 data), matching the default CONFIG_UBI_MAX_NR_OF_DATA_PEBS.
Sizing Guidelines¶
Minimum: At least
N + 2PEBs (N reserved + 2 data), where N =CONFIG_UBI_DEV_HDR_NR_OF_RES_PEBS. In practice, use >= 8 PEBs.Reserved PEBs: The first N PEBs are reserved for device/volume metadata (configurable via
CONFIG_UBI_DEV_HDR_NR_OF_RES_PEBS, default 2). Only PEBs N..total-1 are available for volume data.LEB size:
erase_block_size - 48bytes (48 bytes are consumed by EC + VID headers on each data PEB).Example (STM32U5): With 8 KB erase blocks and 128 KB partition: 16 total PEBs, 2 reserved, 14 data PEBs, each with 8144 B usable per LEB.
Example (nRF5340): With 4 KB erase blocks and 64 KB partition: 16 total PEBs, 2 reserved, 14 data PEBs, each with 4048 B usable per LEB.
Zephyr Module Integration¶
UBI registers as a Zephyr module via zephyr/module.yml. When using west, add UBI as a project in your west.yml:
manifest:
projects:
- name: ubi
url: https://github.com/kamil-kielbasa/ubi
revision: main
path: module/lib/ubi
Then initialize and update:
west init -l .
west update --narrow -o=--depth=1