rlvgl 0.1.9

A modular, idiomatic Rust reimplementation of the LVGL graphics library for embedded and simulator use.
Documentation

rlvgl is a modular, idiomatic Rust reimplementation of LVGL (Light and Versatile Graphics Library).

rlvgl preserves the widget-based UI paradigm of LVGL while eliminating unsafe C-style memory management and global state. This library is structured to support no_std environments, embedded targets (e.g., STM32H7), and simulator backends for rapid prototyping.

The C version of LVGL is included as a git submodule for reference and test vector extraction, but not linked or compiled into this library.

Goals

Package: rlvgl

  • Preserve LVGL architecture and layout system
  • Replace C memory handling with idiomatic Rust ownership
  • Support embedded display flush/input via embedded-hal
  • Enable widget hierarchy, styles, and events using Rust traits
  • Use existing Rust crates where possible (e.g., embedded-graphics, heapless, tinybmp)

Features

  • no_std + allocator support with simulator-friendly std features
  • Modular workspace crates for core widgets, platform backends, UI helpers, API bindings, and i18n
  • rlvgl-creator support for asset preparation, vendor database browsing, and STM32 BSP generation from CubeMX .ioc files
  • Vendor chip database crates and generated STM BSP crates for board-aware tooling
  • Flagship STM32H747I-DISCO demo covering DSI display, touch, SDRAM, SD/MMC, audio, and DMA2D-assisted rendering
  • Motion, compositor, dirty-region, and accelerated blitting primitives for richer embedded UIs
  • Pluggable display and input backends for both embedded targets and host simulation
  • Optional Lottie support for dynamic playback and offline asset conversion workflows

Project Structure

  • core – Widget base trait, layout, event dispatch
  • widgets – Rust-native reimplementations of LVGL widgets
  • platform – Display/input traits and HAL adapters
  • ui – Higher-level UI components
  • examples/apps/demo – Packaged demo application crate
  • api – Shared ABI types for bindings and coprocessor integrations
  • i18n – Compile-time translations with runtime-selectable locale blobs
  • chipdb – Vendor chip databases used by creator and BSP generation
  • chips/stm/bsps – Generated STM32 BSP modules
  • rlvgl-creator – Asset and BSP workflows for command-line and UI tooling
  • examples – Sample applications and board demos
  • docs – Project documentation and task lists
  • lvgl – C submodule (reference only)

What's New in 0.1.9

  • rlvgl-creator now covers vendor import, board IR generation, and Rust BSP rendering with bundled alternate-function databases.
  • STM32H747I-DISCO moved from bring-up into a flagship demo path with dual-core startup, DSI display, touch, storage, audio, and richer UI flows.
  • The rendering stack gained EventWindow, compositor/save-under behavior, motion helpers, DMA2D acceleration, and display-pipeline fixes for smoother presentation.
  • The workspace now includes first-class i18n, API, chip database, and generated BSP crates alongside the core UI crates.

Vendor chip databases

Vendor-specific board definitions live in the chipdb/ crates. The tools/gen_pins.py helper aggregates raw vendor inputs into JSON blobs, while tools/build_vendor.sh orchestrates generation and stamps license files. When building a vendor crate, set RLVGL_CHIP_SRC to the directory containing these JSON files so the build script can embed them via include_bytes!.

STM32CubeMX BSP generation 🆕

rlvgl-creator 🆕 converts STM32 CubeMX .ioc projects into board support stubs. Generated modules ship in rlvgl-bsps-stm 🆕. The older board overlay support remains but is deprecated.

BSP Generator (rlvgl-creator 🆕)

rlvgl-creator 🆕 offers a two-stage pipeline for board support packages:

  1. Import vendor project files (e.g., STM32CubeMX .ioc, NXP .mex, RP2040 YAML). Each adapter mines the vendor data and emits a small, vendor-neutral YAML IR describing clocks, pins, DMA and peripherals.
  2. Generate Rust initialization code by rendering MiniJinja templates against the IR. Users may choose from built-in template packs or provide their own.

The STM32CubeMX adapter also parses PLL multipliers and peripheral kernel clock selections so that clock setup can be generated alongside pin configuration.

No per-chip tables are maintained. Class-level rules are reused across instances and vendors. Alternate functions are derived from embedded vendor databases generated from the official XML sources; no external JSON is required at generation time. Reserved SWD pins (PA13, PA14) are rejected unless explicitly allowed.

Typical flow:

rlvgl-creator platform import --vendor st --input board.ioc --out board.yaml
rlvgl-creator platform gen --spec board.yaml --templates templates/stm32h7 \
  --out src/generated.rs

Alternate-function numbers are computed from the embedded database at runtime by rlvgl-creator, so there is no need to generate or pass a JSON file.

To package vendor chip databases for testing or publishing, run:

tools/build_vendor.sh
RLVGL_CHIP_SRC=chipdb/rlvgl-chips-stm/generated cargo build -p rlvgl-chips-stm

For a full asset workflow overview see the rlvgl-creator 🆕 README. Command details live in docs/CREATOR-CLI.md.

IR schema

The import step emits a concise YAML specification describing the board:

mcu: STM32H747XIHx
package: LQFP176
power: { supply: smps, vos: scale1 }
clocks:
  sources: { hse_hz: 25000000 }
  pll:
    pll1: { m: 5, n: 400, p: 2, q: 4, r: 2 }
  kernels: { usart1: pclk2 }
pinctrl:
  - group: usart1-default
    signals:
      - { pin: PA9,  func: USART1_TX, af: 7, pull: none, speed: veryhigh }
      - { pin: PA10, func: USART1_RX, af: 7, pull: up,   speed: veryhigh }
peripherals:
  usart1:
    class: serial
    params: { baud: 115200, parity: none, stop_bits: 1 }
    pinctrl: [ usart1-default ]
reserved_pins: [ PA13, PA14 ]

Field summary:

  • mcu, package – identifiers from the vendor project.
  • power – supply configuration; values map directly to HAL calls.
  • clocks – input frequencies (sources), PLL multipliers (pll) and per‑peripheral kernel selections (kernels).
  • pinctrl – groups of pins with their functions, alternate functions, pulls and speeds.
  • peripherals – map of peripheral instances keyed by name (usart1), each with a class (e.g. serial) and optional params.
  • dma, interrupts – optional arrays describing DMA requests and IRQ priorities.
  • reserved_pins – pins that must not be reconfigured (e.g. SWD).

Template helpers

MiniJinja templates can use the following filters:

  • pin_var – convert a pin like PA9 into the variable name pa9.
  • periph_num – extract trailing digits from a peripheral name (usart1212).
  • af_alt – render an alternate-function number for into_alternate::<AF>() (7<7>).

Users may supply custom templates by pointing --templates at any directory; the filters above are always available.

See docs/TODO-CREATOR-BSP.md for remaining work.

Status

As-built. See docs for component-by-component progress and outstanding tasks.

v0.1.9 shifts rlvgl from a core-library-first workspace toward a fuller embedded UI product stack. The main areas of growth are the creator/BSP pipeline, the STM32H747I-DISCO showcase target, and the runtime pieces needed for more polished embedded applications.

Quick Example

use rlvgl_core::widget::Rect;
use rlvgl_widgets::label::Label;

fn main() {
    let mut label = Label::new(
        "hello",
        Rect {
            x: 0,
            y: 0,
            width: 100,
            height: 20,
        },
    );
    label.style.bg_color = rlvgl_core::widget::Color(0, 0, 255, 255);
    // Rendering would use a DisplayDriver implementation.
}

Testing

Run host-based tests with the default toolchain:

cargo test --workspace

Cross-target tests (e.g., thumbv7em-none-eabihf) require a linker. Cargo defaults to arm-none-eabi-gcc, but you can avoid installing GCC by adding the rust-lld component and configuring:

rustup component add rust-lld
[target.thumbv7em-none-eabihf]
linker = "rust-lld"

See docs/CROSS-TESTING.md for troubleshooting tips.

Coverage

LLVM coverage instrumentation is configured via .cargo/config.toml and the coverage target in the Makefile. Run make coverage to execute the tests with instrumentation and generate an HTML report under ./coverage/.

rlvgl crate

Run the following Cargo command in your project directory:

cargo add rlvgl

Or add the following line to your Cargo.toml:

rlvgl = "0.1.9"

Community

Dockerhub

The build image used by the Github worflow for this repo is publiclly available on Dockerhub.

docker pull iraa/rlvgl:latest

Consult the Dockerfile for details on the build environment.

Other useful helper scripts may be found in /scripts.

License

rlvgl is licensed under the MIT license. See LICENSE for more details. Third-party license notices are summarized in NOTICES.md.

More Information

For more information, visit softoboros.com.