lvgl-widgets-demo
:::warning [UNTESTED] on real hardware
native_sim proves the alp_display_open() / alp_gui_lvgl_attach() path builds, runs, and flushes real frames (alp_display_blit() is reached from LVGL's render loop). The underlying MIPI DBI Type C devicetree path on the E1M-EVK still has build-only CI coverage, and this app's target board (ensemble_e8_dk) has no alp-display0 alias checked in yet — real-hardware bring-up lands with the v1.0 HiL sweep.
:::
Wraps the upstream lv_demo_widgets() — LVGL's headline showcase of every standard widget (buttons, sliders, tabs, charts, meters, lists, animations).
Source: examples/display/lvgl-widgets-demo/.
What it shows
- The app opens the panel through the portable
<alp/display.h>surface and binds LVGL to it with<alp/gui.h>— no direct Zephyrdisplay_*calls. - The SDK's
st7789chip driver handles the panel-specific init. - Customer code stays board-portable — no vendor-specific symbols, only
<alp/*>peripheral surfaces + the portable LVGL API.
Display bring-up
This is the reference init sequence for every Zephyr LVGL example in the SDK. The app owns the ordering:
alp_display_config_t display_cfg = ALP_DISPLAY_CONFIG_DEFAULT(0);
alp_display_t *display = alp_display_open(&display_cfg);
if (display == NULL) {
LOG_ERR("display open failed (err=%d)", (int)alp_last_error());
return 1;
}
lv_init();
lv_tick_set_cb(k_uptime_get_32);
alp_status_t attach_status = alp_gui_lvgl_attach(display);
if (attach_status != ALP_OK) { /* ... */ }
lv_demo_widgets();
Then the usual pump: lv_timer_handler() followed by a bounded k_msleep().
Required Kconfig
| Knob | Where | Why |
|---|---|---|
CONFIG_LV_Z_AUTO_INIT=n | prj.conf | LVGL must not auto-create its own lv_display_t — the app owns the panel via alp_display_open(). Without this you get a second, unbound display. |
CONFIG_DISPLAY=y | prj.conf | Enables the display driver class. |
CONFIG_DUMMY_DISPLAY=y | native_sim.conf | Host runs render into a dummy device… |
CONFIG_SDL_DISPLAY=n | native_sim.conf | …rather than opening an SDL2 window. |
The alp-display0 alias
alp_display_open() resolves its panel from an alp-display0 devicetree alias. The native_sim overlay provides one:
/ {
chosen {
zephyr,display = &dummy_dc;
};
aliases {
alp-display0 = &dummy_dc;
};
dummy_dc: dummy_dc {
compatible = "zephyr,dummy-dc";
height = <320>;
width = <240>;
};
};
The other Zephyr LVGL examples reuse this same overlay shape.
Hardware needed
- An E1M-AEN-family SoM (E8 is the reference target — SRAM headroom for LVGL).
- E1M-EVK board (or any board exposing SPI + two GPIOs).
- 240×320 ST7789 TFT panel wired to SPI + reset/DC GPIOs.
board.yaml
libraries:
- name: lvgl
cores: [m55_hp]
som:
sku: E1M-AEN801
preset: e1m-evk
pins:
- { e1m: E1M_SPI1, macro: EVK_SPI_BUS_ARDUINO, doc: "Arduino UNO header SPI" }
cores:
a32_cluster:
os: "off"
m55_hp:
app: ./src
peripherals:
- spi
- gpio
chips:
- st7789
diagnostics:
log_level: info
See also
<alp/display.h>·<alp/gui.h>lvgl-benchmark·lvgl-music-playerlvgl-dashboard-x-evk— the Linux/DRM counterpart, which bypasses this path- Examples overview