LOADING
1249 字
6 分钟
基于 ESP-IDF 的 Rust + Slint + ESP32-S3 快速上手

引言

为什么选择 ESP-IDF ?

使用的系统环境

  • 操作系统: macOS 15.7.4
  • 开发版: 正点原子 ESP32 AI BOX1
Tip

我们以后将频繁参考的正点原子官方资料 http://www.openedv.com/docs/boards/esp32/ATK-DNESP32S3BVXX.html

配置开发环境

安装 Rust

Tip

官方更推荐使用 Rustup 安装 Rust, 而非通过第三方包管理工具 brew. ESP-IDF-Template 也更推荐使用 Rustup 进行安装 [^1] https://rust-lang.org/tools/install/

Terminal window
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

随后运行 source "$HOME/.cargo/env" 或重启你的 Shell, 校验安装:

Terminal window
rustup update

给 Rust 包管理工具 Cargo 换源

国内特殊的网络环境需要换源才能实现高速的依赖下载, 笔者这里推荐 北京外国语大学开源软件镜像站, 详见:

安装 ESP-IDF 及其工具链

根据 ESP-IDF-Template 中 Prerequisites 部分

In particular, do NOT clone, install and activate the ESP-IDF which is mentioned further down this page, as it is not necessary at all (though supported, but not for a beginner setup)

作为初学者的我们应让 ESP-IDF-SYS 来管理 ESP-IDF, 而非自己手动安装

安装系统级依赖

Terminal window
brew install libgcrypt glib pixman sdl2 libslirp dfu-util cmake

安装 Python

笔者电脑里面有一套 Python 开发环境, 所以使用 pyenv 来管理 Python 环境来避免环境紊乱

Terminal window
brew install pyenv

若重启 Shell 后无法检测到 pyenv 命令, 请参考 PyENV 官方文档

Terminal window
pyenv install -l # 查看最新版本
pyenv install 3.14 # 安装目前的最新版本
pyenv global 3.14
pyenv rehash
python --version # 校验安装
Tip

python --version 版本不对? 看看 pyenv versions 命令结果输出的版本由何设置, 或尝试 rm ~/.python-version.

安装 ESP Rust 相关工具

根据 ESP-IDF-Template 中 Prerequisites 部分

Terminal window
cargo install cargo-generate
cargo install ldproxy
cargo install espup # ESP32-S3 属于 Xtensa,要用 espup 来装 Espressif Rust 工具链
cargo install espflash
cargo install cargo-espflash

根据 ESP-RS, 仅安装最小依赖

Terminal window
espup install --targets esp32s3 --std
. "$HOME/export-esp.sh"

推荐将环境加载持久化进 Shell, 将 ~/.zshrc 改成你的 Shell 用户配置文件

Terminal window
echo '. "$HOME/export-esp.sh"' >> ~/.zshrc

安装 VSCode 插件

在安装 VSCode 插件之前, 笔者更推荐安装以下的 Rust 的额外 lint 工具官方格式化工具

Terminal window
rustup component add clippy rustfmt

运行以下命令或手动安装以下两个 VSCode 插件

Terminal window
code --install-extension rust-lang.rust-analyzer
code --install-extension Slint.slint

推荐添加以下两个 VSCode 配置, 它做了两件事

  • 将检查命令从 cargo check 改为 cargo clippy
  • 在保存时自动格式化代码
{
"rust-analyzer.check.command": "clippy",
"[rust]": {
"editor.formatOnSave": true
}
}

搭建最小 Bootstrap

创建 ESP-IDF 项目

用官方模板生成项目, 在项目文件夹中运行如下命令, 根据 ESP-IDF-TEMPLATE

Terminal window
cargo generate esp-rs/esp-idf-template cargo

我选择的选项如下

➜ CLionProjects cargo generate esp-rs/esp-idf-template cargo
⚠️ Favorite `esp-rs/esp-idf-template` not found in config, using it as a git repository: https://github.com/esp-rs/esp-idf-template.git
🤷 Project Name: esp32-s3-slint-rs
🔧 Destination: /Users/xiaoyouchr/CLionProjects/esp32-s3-slint-rs ...
🔧 project-name: esp32-s3-slint-rs ...
🔧 Generating template ...
✔ 🤷 Which MCU to target? · esp32s3
✔ 🤷 Configure advanced template options? · true
✔ 🤷 ESP-IDF version (master = UNSTABLE) · v5.5.3 # 不建议选择 master 分支, 不稳定
✔ 🤷 Use latest GIT versions of the esp-idf-* crates instead of released crates.io versions? · false # 不建议从 Git 仓库拉取最新版本, 不稳定
✔ 🤷 Installation location of managed ESP-IDF · workspace
✔ 🤷 Configure project to use Dev Containers (VS Code and GitHub Codespaces)? · false
✔ 🤷 Configure project to support Wokwi simulation with Wokwi VS Code extension? · false # Wokwi is World's most advanced ESP32 simulator
✔ 🤷 Add CI files for GitHub Action? · true # GitHub 自动构建工作流

安装 Slint 依赖

根据 https://docs.slint.dev/latest/docs/rust/slint/docs/mcu/

Terminal window
cargo add slint@1.16 --no-default-features --features "compat-1-2 unsafe-single-threaded libm renderer-software"
cargo add --build slint-build@1.16

最小 Slint UI

根据 https://docs.slint.dev/latest/docs/rust/slint/docs/mcu/

ui/app.slint

export component App inherits Window {
width: 320px;
height: 240px;
Rectangle {
background: #1f2937;
Text {
x: 16px;
y: 16px;
text: "ESP32-S3 + Slint + Rust";
color: white;
font-size: 18px;
}
Text {
x: 16px;
y: 48px;
text: "compile-only skeleton";
color: #cbd5e1;
font-size: 14px;
}
}
}

然后编辑 build.rs, 将 ui/app.slint 生成成 Rust 代码, 供 slint::include_modules!(); 引入.

build.rs

fn main() {
embuild::espidf::sysenv::output();
let config = slint_build::CompilerConfiguration::new()
.with_style("fluent".into())
.embed_resources(slint_build::EmbedResourcesKind::EmbedForSoftwareRenderer);
slint_build::compile_with_config("ui/app.slint", config).unwrap();
}

随后运行 cargo build, 编译一下 Slint 文件, 防止在编辑 ui/main.rs 时报错.

最小主函数

根据 https://docs.slint.dev/latest/docs/rust/slint/docs/mcu/#the-platform-trait

ui/main.rs

slint::include_modules!();
use std::boxed::Box;
use std::rc::Rc;
use std::time::{Duration, Instant};
use slint::platform::software_renderer::MinimalSoftwareWindow;
use slint::platform::{Platform, PlatformError};
struct EspPlatform {
window: Rc<MinimalSoftwareWindow>,
start: Instant,
}
impl Platform for EspPlatform {
fn create_window_adapter(
&self,
) -> Result<Rc<dyn slint::platform::WindowAdapter>, PlatformError> {
// Since on MCUs, there can be only one window, just return a clone of self.window.
// We'll also use the same window in the event loop.
Ok(self.window.clone())
}
fn duration_since_start(&self) -> Duration {
self.start.elapsed()
}
}
fn main() {
// It is necessary to call this function once. Otherwise, some patches to the runtime
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
esp_idf_svc::sys::link_patches();
// Bind the log crate to the ESP Logging facilities
esp_idf_svc::log::EspLogger::initialize_default();
log::info!("Booting...");
let window = MinimalSoftwareWindow::new(Default::default());
window.set_size(slint::PhysicalSize::new(320, 240));
slint::platform::set_platform(Box::new(EspPlatform {
window: window.clone(),
start: Instant::now(),
}))
.expect("failed to set Slint platform");
let _ui = App::new().expect("failed to create Slint UI");
log::info!("Slint initialized");
loop {
slint::platform::update_timers_and_animations();
window.draw_if_needed(|_renderer| {
// TODO: render to LCD
});
std::thread::sleep(Duration::from_millis(16));
}
}

第一次烧录

插入 ESP32-S3-BOX 后运行 cargo run, 查看控制台日志, 发现

I (480) esp32_s3_slint_rs: Booting...
I (490) esp32_s3_slint_rs: Slint initialized

烧录成功~

正式点亮屏幕

//

驱动 Xl9555

驱动屏幕

加入触屏功能

增强 Xl9555 驱动

驱动触摸

在 Slint 中处理触摸信号

优化性能

超频 I80 总线

边渲染边上屏

异步处理触摸信号

驱动 Wi-Fi

增强 Xl9555 以驱动 I²C 总线

扫描 Wi-Fi

连接 Wi-Fi

其他说明

提高波特率以加快烧录速度

提高栈大小以及如何避免栈溢出

Windows 下长路径问题

基于 ESP-IDF 的 Rust + Slint + ESP32-S3 快速上手
/posts/rust_slint_esp32s3/rust_slint_esp32s3/
作者
晓游
发布于
2026-04-21
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时