Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions content/workshops/slint-esp32-workshop/_index.md
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 content/workshops/slint-esp32-workshop/assignment-1/index.md
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
---
Copy link
Member

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.


## 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 content/workshops/slint-esp32-workshop/assignment-2/index.md
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/)
Loading
Loading