-
Notifications
You must be signed in to change notification settings - Fork 43
WIP: Workshop/slint #495
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
georgik
wants to merge
1
commit into
espressif:main
Choose a base branch
from
georgik:workshop/slint
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
WIP: Workshop/slint #495
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| --- | ||
| title: "Slint with Rust on ESP32 Workshop - no_std and std" | ||
| date: 2025-06-03T00:00:00+01:00 | ||
| tags: ["Workshop", "Slint", "Rust", "ESP32", "no_std", "std", "Embedded UI"] | ||
| --- | ||
|
|
||
| Welcome to the **Slint with Rust on ESP32** workshop! | ||
|
|
||
| ## About this workshop | ||
|
|
||
| This hands-on workshop is designed to introduce embedded developers to designing modern graphical user interfaces using the [Slint UI Toolkit](https://slint.dev) in Rust for the ESP32 platform. The workshop supports **both `no_std` (bare-metal) and `std` (ESP-IDF) approaches**, with **`no_std` as the primary and recommended path** due to its simplicity, better performance, and official Espressif support. | ||
|
|
||
| Unlike traditional workflows that start directly on embedded hardware, this training emphasizes a **desktop-first** approach: you begin by developing and testing the UI on your desktop, then port the same code to an embedded platform. This is made possible thanks to Slint's cross-platform design and support for Rust in both `no_std` and `std` environments. | ||
|
|
||
| While Slint supports other languages such as C++ or Python, this workshop is focused entirely on **pure Rust**. | ||
|
|
||
| > Although the examples run on the ESP32-S3, the concepts can be ported to other [ESP32 targets with display capability](https://github.com/espressif/esp-bsp). | ||
|
|
||
| ## Choosing Your Development Approach | ||
|
|
||
| This workshop supports both development approaches with **`no_std` (bare-metal) as the primary recommendation**: | ||
|
|
||
| ### `no_std` (Bare-Metal) - **RECOMMENDED** ✅ | ||
|
|
||
| **Why choose `no_std`:** | ||
| - ✅ **Much simpler setup** - No C/C++ toolchain required | ||
| - ✅ **Pure Rust** - No ESP-IDF complexity | ||
| - ✅ **Official Espressif support** - First-class citizen in esp-hal ecosystem | ||
| - ✅ Smaller binary size and memory footprint | ||
| - ✅ Better performance and lower latency | ||
| - ✅ Direct hardware control with esp-hal | ||
| - ✅ Faster compilation times | ||
| - ✅ More predictable behavior | ||
| - ✅ **Highly portable code** - Works across different embedded platforms | ||
|
|
||
| **When to choose `no_std`:** Recommended for most embedded projects, especially when you want a pure Rust experience. | ||
|
|
||
| ### `std` (ESP-IDF) - Alternative Approach | ||
|
|
||
| **When to choose `std`:** | ||
| - You specifically need existing ESP-IDF C/C++ components | ||
| - You have a large existing C/C++ codebase to integrate | ||
| - You require std-only crates that don't have no_std alternatives | ||
|
|
||
| **Considerations with `std`:** | ||
| - ❌ **Complex setup** - Requires full C/C++ ESP-IDF toolchain | ||
| - ❌ Larger binary size and higher memory usage | ||
| - ❌ Slower compilation times | ||
| - ❌ Platform-specific code - harder to port to other embedded platforms | ||
|
|
||
| **Default Choice:** Start with **`no_std`** for the best embedded Rust experience. Only switch to `std` if you have specific requirements that necessitate it. | ||
|
|
||
| ## Agenda | ||
|
|
||
| With the prerequisites in place, follow the assignments in order: | ||
|
|
||
| - [Assignment 1: Environment Setup](assignment-1) — install Rust toolchain, dependencies, and tools for Slint and ESP32. | ||
| - [Assignment 2: Run GUI on Desktop](assignment-2) — create a simple two-tab UI with the Slint logo and a placeholder for Wi-Fi list. | ||
| - [Assignment 3: Run GUI on ESP32-S3](assignment-3) — port the same app to embedded hardware such as M5Stack CoreS3, ESoPe Board (SLD_C_W_S3), ESP32-S3-BOX-3, or ESP32-S3-LCD-EV-Board. | ||
| - [Assignment 4: Add Wi-Fi list on Desktop](assignment-4) — populate the placeholder list with available networks using the OS backend. | ||
| - [Assignment 5: Add Wi-Fi scan on ESP32](assignment-5) — replace the desktop data source with live Wi-Fi scan results from the ESP32. | ||
| - [Assignment 6: Explore more Slint examples](assignment-6) — interactive demos and links to advanced usage patterns. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| **Hardware:** | ||
|
|
||
| - **[M5Stack CoreS3](https://shop.m5stack.com/products/m5stack-cores3-esp32s3-lotdevelopment-kit)** (recommended - touchscreen, speakers, microphone) | ||
| - [ESoPe Board SLD_C_W_S3 with Schukat Smartwin display-concept](https://esope.de) (RGB interface) | ||
| - Alternative boards: [ESP32-S3-BOX-3](https://github.com/espressif/esp-bsp/tree/master/bsp/esp32_s3_box_3), [ESP32-S3-LCD-EV-Board](https://github.com/espressif/esp-bsp/tree/master/bsp/esp32_s3_lcd_ev_board) | ||
| - USB-C cable for M5Stack CoreS3 and ESP32-S3-BOX-3, or USB micro cable with [ESP-Prog](https://docs.espressif.com/projects/esp-iot-solution/en/latest/hw-reference/ESP-Prog_guide.html) for ESoPe board | ||
|
|
||
| **Software:** | ||
|
|
||
| - [Rust toolchain](https://rustup.rs) (stable channel is sufficient) | ||
| - [`espup`](https://github.com/esp-rs/espup) to install and configure `esp-rust` toolchain (**recommended method**) | ||
| - `espflash` for flashing firmware | ||
| - `cargo-generate` for creating project templates | ||
| - [JetBrains RustRover](https://www.jetbrains.com/rust/) or [CLion](https://www.jetbrains.com/clion/) — **recommended IDEs**, available free for students and open source projects | ||
| - Alternatively, VS Code with Rust Analyzer, or any terminal-based Rust development setup | ||
|
|
||
| JetBrains IDEs (CLion or RustRover) are highly recommended and provide excellent Rust tooling out of the box. These tools are available free of charge for students and open source contributors. | ||
|
|
||
| Follow [Slint Embedded Setup Instructions](https://docs.slint.dev/latest/docs/slint/) for more details. | ||
|
|
||
| ## Time Estimate | ||
|
|
||
| {{< alert icon="mug-hot">}} | ||
| **Estimated time: 2–3 hours** | ||
| {{< /alert >}} | ||
|
|
||
| Pacing depends on your experience with embedded Rust and Slint. | ||
|
|
||
| ## Target Audience | ||
|
|
||
| This workshop is suitable for: | ||
|
|
||
| - Embedded developers with C/C++ background exploring Rust | ||
| - Rust developers curious about no_std embedded development | ||
| - Anyone interested in building fast, modern GUIs for microcontrollers | ||
|
|
||
| Basic knowledge of embedded systems and Rust syntax is helpful but not required. | ||
|
|
||
| ## Support and Feedback | ||
|
|
||
| If you get stuck or have feedback, please open a [discussion on GitHub](https://github.com/espressif/developer-portal/discussions) or reach out to the [Slint Discord](https://slint.dev/community.html). | ||
|
|
||
| ## Feedback and Contributions | ||
|
|
||
| This workshop is available on GitHub and welcomes contributions and improvements. If you encounter issues or want to propose updates, feel free to [open a discussion or pull request](https://github.com/espressif/developer-portal/discussions). | ||
|
|
||
| ## Goals | ||
|
|
||
| By the end of this workshop, you will: | ||
|
|
||
| - Be able to create a UI with Slint in Rust using `no_std` | ||
| - Deploy graphical apps to ESP32-S3 boards with display and optional touch | ||
| - Understand how to separate logic from presentation with properties and callbacks | ||
| - Integrate the Slint runtime with an embedded framebuffer and event loop | ||
|
|
||
| --- | ||
|
|
||
|
|
||
| ## Credits | ||
|
|
||
| This workshop was created in collaboration between [Espressif Systems](https://www.espressif.com), [Slint](https://slint.dev/esp32), [M5Stack](https://m5stack.com), [ESoPe](https://esope.de), and [Schukat](https://shop.schukat.com/de/de/EUR/search/esope). | ||
|
|
||
| If you are interested in organizing a workshop or need support, we recommend reaching out to the trainer: [Michael Winkelmann](https://winkelmann.site/). | ||
|
|
||
| Let's get started: [Assignment 1](assignment-1) |
161 changes: 161 additions & 0 deletions
161
content/workshops/slint-esp32-workshop/assignment-1/index.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,161 @@ | ||
| --- | ||
| title: "Assignment 1: Environment Setup" | ||
| date: 2025-06-03T00:00:00+01:00 | ||
| showTableOfContents: true | ||
| series: ["slint-no-std"] | ||
| series_order: 1 | ||
| showAuthor: false | ||
| --- | ||
|
|
||
| ## Assignment 1: Environment Setup | ||
|
|
||
| In this assignment, we will set up the Rust development environment for ESP32-S3 programming using the official [`espup`](https://github.com/esp-rs/espup) tool. | ||
|
|
||
| Slint supports building applications for microcontrollers like the ESP32-S3 using Rust in both `no_std` (bare-metal) and `std` (ESP-IDF) modes. **This workshop primarily uses the `no_std` approach** due to its simplicity and better performance. | ||
|
|
||
| --- | ||
|
|
||
| ### Step 1: Install Rust | ||
|
|
||
| Install the Rust stable toolchain using `rustup` if you haven't already: | ||
|
|
||
| ```sh | ||
| curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh | ||
| ``` | ||
|
|
||
| Once installed, ensure you have the latest stable toolchain: | ||
|
|
||
| ```sh | ||
| rustup update | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ### Step 2: Install `espup` | ||
|
|
||
| We recommend installing `espup` using Cargo: | ||
|
|
||
| ```sh | ||
| cargo install espup --locked | ||
| ``` | ||
|
|
||
| Alternatively, you may use pre-built binaries or `cargo-binstall` (see espup GitHub README for details). | ||
|
|
||
| --- | ||
|
|
||
| ### Step 3: Run `espup install` | ||
|
|
||
| To install the toolchain for **no_std** development (which includes the GCC linker), run: | ||
|
|
||
| ```sh | ||
| espup install | ||
| ``` | ||
|
|
||
| This will install: | ||
|
|
||
| - The Espressif Xtensa Rust toolchain | ||
| - LLVM with Xtensa backend | ||
| - GCC cross compiler | ||
| - `export-esp.sh` file containing environment variables | ||
|
|
||
| You may customize targets like so: | ||
|
|
||
| ```sh | ||
| espup install --targets esp32s3 | ||
| ``` | ||
|
|
||
| ⚠️ Do **not** use the `--std` flag — we are developing in `no_std`. | ||
|
|
||
| --- | ||
|
|
||
| ### Step 4: Source the environment variables (Unix-based systems) | ||
|
|
||
| After `espup install`, you'll find `export-esp.sh` under `$HOME`. | ||
|
|
||
| You need to load this file to correctly configure your environment: | ||
|
|
||
| #### Temporary (for current shell) | ||
|
|
||
| ```sh | ||
| . $HOME/export-esp.sh | ||
| ``` | ||
|
|
||
| #### Persistent (recommended) | ||
|
|
||
| Append the export file to your shell configuration (e.g. `.bashrc`, `.zshrc`): | ||
|
|
||
| ```sh | ||
| cat $HOME/export-esp.sh >> ~/.bashrc | ||
| ``` | ||
|
|
||
| Then: | ||
|
|
||
| ```sh | ||
| source ~/.bashrc | ||
| ``` | ||
|
|
||
| On **Windows**, this is done automatically. | ||
|
|
||
| --- | ||
|
|
||
| ### Step 5: Verify the installation | ||
|
|
||
| Check that the Rust Xtensa toolchain is active: | ||
|
|
||
| ```sh | ||
| rustc --version | ||
| cargo --version | ||
| ``` | ||
|
|
||
| Check that `espflash` is installed: | ||
|
|
||
| ```sh | ||
| cargo install espflash | ||
| ``` | ||
|
|
||
| You're now ready to compile `no_std` Rust applications targeting the ESP32-S3! | ||
|
|
||
| --- | ||
|
|
||
| ## Development Approach: `no_std` vs `std` | ||
|
|
||
| ### `no_std` Approach | ||
|
|
||
| **This workshop uses the `no_std` approach by default.** The setup above is perfect for `no_std` development. | ||
|
|
||
| **Project Directory Structure:** | ||
| ``` | ||
| esp32/no_std/ | ||
| ├── m5stack-cores3/ # M5Stack CoreS3 implementation | ||
| ├── esope-sld-c-w-s3/ # ESoPe board implementation | ||
| ├── esp32-s3-box-3/ # ESP32-S3-BOX-3 implementation | ||
| └── esp32-s3-lcd-ev-board/ # LCD-EV board implementation | ||
| ``` | ||
|
|
||
| ### `std` Approach | ||
|
|
||
| **If you specifically need ESP-IDF/std features**, you can also set up for `std` development: | ||
|
|
||
| ```sh | ||
| # For std development, install with --std flag | ||
| espup install --std | ||
| ``` | ||
|
|
||
| **Project Directory Structure:** | ||
| ``` | ||
| esp32/std/ | ||
| ├── m5stack-cores3/ # M5Stack CoreS3 std implementation | ||
| ├── esope-sld-c-w-s3/ # ESoPe board std implementation | ||
| ├── esp32-s3-box-3/ # ESP32-S3-BOX-3 std implementation | ||
| └── esp32-s3-lcd-ev-board/ # LCD-EV board std implementation | ||
| ``` | ||
|
|
||
| **Note:** `std` approach requires additional ESP-IDF setup and is more complex. **We recommend starting with `no_std`** for this workshop. | ||
|
|
||
| --- | ||
|
|
||
| ### Next Step | ||
|
|
||
| Now that your environment is ready, let’s run our first Slint GUI app on the desktop. | ||
|
|
||
| [Continue to Assignment 2](../assignment-2/) | ||
99 changes: 99 additions & 0 deletions
99
content/workshops/slint-esp32-workshop/assignment-2/index.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
|
|
||
|
|
||
| --- | ||
| title: "Assignment 2: Run GUI on Desktop" | ||
| date: 2025-06-03T00:00:00+01:00 | ||
| showTableOfContents: true | ||
| series: ["slint-no-std"] | ||
| series_order: 2 | ||
| showAuthor: false | ||
| --- | ||
|
|
||
| In this assignment, you will run your first Slint application on your desktop. This is a crucial step because Slint is designed to support a cross-platform development workflow — you can develop and preview your UI logic on a desktop machine, and later run it unmodified on an embedded device. | ||
|
|
||
| ## Goals | ||
|
|
||
| - Run a simple Slint-based GUI desktop application | ||
| - Learn about the `.slint` UI syntax | ||
| - Understand the view-model structure used in this workshop | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - Rust stable installed with `espup` (see Assignment 1) | ||
| - Git | ||
| - A desktop platform (Windows, Linux, macOS) | ||
| - Rust GUI dependencies installed via `cargo build` | ||
|
|
||
| ## Step-by-Step Instructions | ||
|
|
||
| ### 1. Clone the Example Repository | ||
|
|
||
| We will use a ready-to-run version of the project from the Slint ESP workshop: | ||
|
|
||
| ```bash | ||
| git clone https://github.com/WilstonOreo/slint-esp-workshop.git | ||
| cd slint-esp-workshop/winit | ||
| ``` | ||
|
|
||
| ### 2. Run the Application | ||
|
|
||
| Inside the `winit` directory, launch the desktop version with: | ||
|
|
||
| ```bash | ||
| cargo run --release | ||
| ``` | ||
|
|
||
| You should see a GUI window open with two tabs: | ||
|
|
||
| - **Slint logo page** – a static graphical layout | ||
| - **Wi-Fi list placeholder page** – currently empty, but will later show available access points | ||
|
|
||
| If the application launches and you can switch tabs, you're ready to proceed. | ||
|
|
||
| --- | ||
|
|
||
| ## About `.slint` Files | ||
|
|
||
| The GUI is defined in `.slint` files under the `ui/` directory. Here's a brief overview: | ||
|
|
||
| - `appwindow.slint`: the top-level window layout | ||
| - `pages.slint`: contains the individual pages (e.g. logo and Wi-Fi list) | ||
| - `widgets.slint`: reusable UI elements | ||
| - `style.slint`: styling definitions (colors, spacing, fonts) | ||
| - `viewmodel.slint`: defines properties exposed to Rust (e.g. selected tab) | ||
|
|
||
| ### Example: | ||
|
|
||
| ```slint | ||
| export component MainWindow inherits Window { | ||
| in-out property <int> current_tab: 0; | ||
|
|
||
| TabWidget { | ||
| current-tab: root.current_tab; | ||
| Tab { title: "Logo"; /* ... */ } | ||
| Tab { title: "Wi-Fi"; /* ... */ } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| This declarative syntax is both concise and powerful, making UI development intuitive. | ||
|
|
||
| --- | ||
|
|
||
| ## View Model Architecture | ||
|
|
||
| Slint supports two-way binding between Rust and UI via `in-out` properties and callbacks. The workshop uses a basic MVVM (Model-View-ViewModel) pattern: | ||
|
|
||
| - `.slint` defines structure & exposed properties | ||
| - `viewmodel.rs` or `main.rs` binds data to UI | ||
| - Events are handled in Rust and forwarded to Slint | ||
|
|
||
| This keeps rendering declarative and logic testable. | ||
|
|
||
| --- | ||
|
|
||
| ## Summary | ||
|
|
||
| You’ve now successfully launched a desktop GUI written in Slint. In the next step, you’ll bring this application to your embedded device. | ||
|
|
||
| [Continue to Assignment 3 →](../assignment-3/) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be nice to add the summary on each assignment.