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-creatorsupport for asset preparation, vendor database browsing, and STM32 BSP generation from CubeMX.iocfiles- Application Schema (
rlvgl-app/v0) — declarativeapp.yamlmanifest plusrlvgl-creator app from-yamlorchestrator emit a buildable Cargo crate from one source of truth (BSP, assets, state machine, i18n, theme, layouts, per-prong main glue). Seedocs/app-schema/. - 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
- docs/disco-tutorial – Progressive, chapter-by-chapter guide to building the STM32H747I-DISCO demo from scratch
- docs/disco-platform-guide – Volume II: bare-metal STM32H747I-DISCO platform bring-up, SVD/PAC limits, AXI holdoff, and the star crawl in full detail
- docs/disco-test-and-debug – Volume III: how to test and debug across the host simulator, UEFI/QEMU, and hardware, including playit automation and VS Code + probe-rs + GDB
- docs/disco-freertos-guide – Volume IV: FreeRTOS preemptive tasks, interrupt-driven I2C4 touch, single-buffer rendering, joystick navigation
- docs/disco-zephyr-guide – Volume V: Zephyr C+Rust hybrid, video mode vs adapted command mode, DMA2D pipeline, CSleep/LPENR fix
- lvgl – upstream C library (vendored as a git submodule under
lvgl/; not mirrored on the site)
Building Binary Targets
The workspace currently ships six user-facing binaries. Their package names,
required targets, and applicable feature flags differ enough that it is best to
treat them individually instead of relying on cargo build --workspace. Every
binary has a top-level make target — run make help to see them all, or
make build-all-bins to build every binary in one command.
Host tools and simulators
| Binary | Package | Make target | Cargo command |
|---|---|---|---|
rlvgl-creator |
rlvgl |
make build-creator |
cargo build -p rlvgl --bin rlvgl-creator --features creator |
rlvgl-sim |
rlvgl-example-sim |
make build-sim |
cargo build -p rlvgl-example-sim --bin rlvgl-sim --features png,jpeg,gif,qrcode,fontdue |
rlvgl-disco-sim |
rlvgl-example-disco-sim |
make build-disco-sim |
cargo build -p rlvgl-example-disco-sim --bin rlvgl-disco-sim |
rlvgl-uefi-disco |
rlvgl-example-uefi-disco |
make build-uefi-disco |
cargo build --manifest-path examples/uefi-disco/Cargo.toml --target aarch64-unknown-uefi --bin rlvgl-uefi-disco |
Notes: rlvgl-creator is gated behind the creator feature; add creator_ui
for the desktop UI. rlvgl-sim accepts --no-default-features for a lean
build. rlvgl-uefi-disco is intentionally excluded from the workspace.
STM32H747I-DISCO firmware
The firmware package is rlvgl-example-disco and it produces two binaries from
the same crate:
| Binary | Required target | Required feature | Make target | Cargo command |
|---|---|---|---|---|
rlvgl-stm32h747i-disco |
thumbv7em-none-eabihf |
cm7 |
make build-disco |
RUSTFLAGS="-C target-cpu=cortex-m7" cargo build --target thumbv7em-none-eabihf -p rlvgl-example-disco --bin rlvgl-stm32h747i-disco --features cm7,splash,desktop,dma2d,cpu_stats,qspi_flash,sd_storage,audio |
rlvgl-stm32h747i-disco-cm4 |
thumbv7em-none-eabihf |
cm4 |
make build-disco-cm4 |
RUSTFLAGS="-C target-cpu=cortex-m7" cargo build --target thumbv7em-none-eabihf -p rlvgl-example-disco --bin rlvgl-stm32h747i-disco-cm4 --features cm4 |
make build-disco{,-release} also runs rust-objcopy to emit .hex and
.bin artifacts beside the ELF.
Playit test runners
Every binary that supports the playit automation protocol has a matching make target that builds it (where applicable) and runs the playit test suite against it:
| Target | Make target | Description |
|---|---|---|
| Disco-demo controller (no_std) | make test-disco-demo |
cargo test -p rlvgl-app-disco-demo — 26 unit tests |
| Disco simulator (host) | make test-disco-sim |
Builds rlvgl-disco-sim and runs the Rust + Node.js suites over a TCP playit socket |
| UEFI disco (QEMU) | make test-uefi-disco |
Builds rlvgl-uefi-disco, boots it headless under QEMU, and runs the Node.js suite over the pl011 UART |
| STM32H747I-DISCO hardware | make test-stm32h747i-disco |
Bridges /dev/cu.usbmodem* (ST-Link VCP) to TCP and runs the Node.js suite against live firmware |
| All of the above | make test-playit-all |
Runs every suite in sequence |
The hardware runner depends on flashing make build-disco first; the UEFI
runner depends on qemu-system-aarch64 plus EDK2 firmware (brew install qemu on macOS provides both). See playit/README.md for the full wire
protocol.
Only the STM32H747I-DISCO package understands the following board-specific
feature flags: splash, desktop, dma2d, cpu_stats, audio,
qspi_flash, sd_storage, c_hal, c_hal_cm4, pac_sdram_init,
sdram_ramtest, hal_sdram, backlight_pwm, semihosting, and bsp_log.
They are all opt-in; default = [].
Where to find feature details
Every crate in the workspace now has an OPTIONS.md file next to its
Cargo.toml. Start with the umbrella crate's OPTIONS.md, then
use the crate-local file for the package you are building:
- examples/sim/OPTIONS.md
- examples/disco-sim/OPTIONS.md
- examples/stm32h747i-disco/OPTIONS.md
- examples/uefi-disco/OPTIONS.md
- src/bin/creator/README.md for CLI and UI workflow details
What's New in 0.1.9
rlvgl-creatornow 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:
- 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. - 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:
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:
RLVGL_CHIP_SRC=chipdb/rlvgl-chips-stm/generated
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:
clocks:
sources:
pll:
pll1:
kernels:
pinctrl:
- group: usart1-default
signals:
-
-
peripherals:
usart1:
class: serial
params:
pinctrl:
reserved_pins:
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 aclass(e.g.serial) and optionalparams.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 likePA9into the variable namepa9.periph_num– extract trailing digits from a peripheral name (usart12→12).af_alt– render an alternate-function number forinto_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 Rect;
use Label;
Testing
Run host-based tests with the default toolchain:
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:
[]
= "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
- The link above is for the top crate which bundles the others and includes the simulator.
- rlvgl-core crate
- rlvgl-widgets crate
- rlvgl-platform crate
- rlvgl-ui crate
- rlvgl-i18n crate
Run the following Cargo command in your project directory:
Or add the following line to your Cargo.toml:
= "0.1.9"
Community
Dockerhub
The build image used by the Github worflow for this repo is publiclly available on Dockerhub.
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.