跳过正文

安装 ESP32 Rust 开发工具链 esp-rs

·1970 字
Rust Esp32 Rust Esp32
rust-esp32 - 这篇文章属于一个选集。
§ 3: 本文

参考:https://esp-rs.github.io/book/introduction.https

安装前置依赖: 不需要先安装 esp-idf,后续构建 std 应用时会自动下载和安装 esp-idf。

# 提供 cargo generate 子命令
cargo install cargo-generate

# A tool that forwards linker arguments to the actual linker that is also given as an argument to
# ldproxy
cargo install ldproxy

# A tool that simplifies installing and maintaining the components required to develop Rust
# applications for the Xtensa and RISC-V architectures.
cargo install espup

brew install libuv  # espflash 依赖它

cargo install espflash
cargo install cargo-espflash # 可选,后续可以直接使用命令 cargo espflash

espup 同时安装和维护 Xtensa and RISC-V architectures 两种 CPU 架构工具链,包括 esp fork 的 rust, GCC 和 LLVM 等。

Rust 官方编译器提供了对 RISC-V target 的 Tier2 支持,可以直接向官方 toolchain 添加对应 target:

rustup toolchain install nightly --component rust-src

# For no_std (bare-metal) applications
rustup target add riscv32imc-unknown-none-elf # For ESP32-C2 and ESP32-C3
rustup target add riscv32imac-unknown-none-elf # For ESP32-C6 and ESP32-H2

ESP32-S3 使用 xtensa 处理器,不再 Rust 官方 toolchain 支持范围内,ESP fork 了 Rust 编译器工具链来进行支持。

使用 espup 安装 esp channel:

# 清理旧版本
zj@a:~/esp$ espup uninstall
[info]: Uninstalling the Espressif Rust ecosystem
[info]: Uninstalling Xtensa LLVM
[info]: Uninstalling GCC
[info]: Uninstalling Xtensa Rust toolchain
[info]: Uninstallation successfully completed!
zj@a:~/esp$ rm -rf  ~/.rustup/toolchains/*

# espup 是 Rust 程序,不会执行 python 代码,所以支持 socks 代理。开启代理后可以缩短下载时间。
zj@a:~/esp$ enable_socks_proxy

# 安装 ESP32 的 Rust toolchain
zj@a:~/esp$ espup install -l debug
[debug]: Creating export file
[info]: Installation successfully completed!

        To get started, you need to set up some environment variables by running: '. /Users/alizj/export-esp.sh'
        This step must be done every time you open a new terminal.
            See other methods for setting the environment in https://esp-rs.github.io/book/installation/riscv-and-xtensa.html#3-set-up-the-environment-variables

# 修改自动生成的 ~/export-esp.sh 脚本
zj@a:~$ cat ~/export-esp.sh
# 删除 python venv 路径,防止后续 cargo build 安装 esp-idf 报错。
export DIR_TO_REMOVE=/Users/alizj/.venv/bin
PATH=$(echo "$PATH" | sed -e "s;:$DIR_TO_REMOVE;;" -e "s;$DIR_TO_REMOVE:;;" -e "s;$DIR_TO_REMOVE;;")
# 解决 Mac M1 cargo build 报错的问题:https://github.com/rust-lang/cc-rs/issues/1005
CRATE_CC_NO_DEFAULTS=1
# cargo build 过程中会安装 esp-idf python venv ,不支持 SOCKS 代理,故切换为 HTTP 代理。
enable_http_proxy

export LIBCLANG_PATH="/Users/alizj/.rustup/toolchains/esp/xtensa-esp32-elf-clang/esp-16.0.4-20231113/esp-clang/lib"
export PATH="/Users/alizj/.rustup/toolchains/esp/xtensa-esp-elf/esp-13.2.0_20230928/xtensa-esp-elf/bin:$PATH"

为了方便使用,将 ~/export-esp.sh 脚本 mv 到 ~/esp 目录,同时添加两个 alias:

zj@a:~/esp$ mv ~/export-esp.sh ~/esp/
zj@a:~/esp$ grep esp ~/.bashrc
alias export_idf='. $HOME/esp/esp-idf/export.sh'
alias export_esp='. $HOME/esp/export-esp.sh'

后续每次使用 esp-rs 前都需要 source ~/esp/export-esp.sh 脚本。

修正 esp toolchain 缺失 rust-analyzer 的问题:esp 是 espup 安装的自定义 toolchain,不包含 rust-analyzer,需要建一个软链接:

zj@a:~$ rustup component add rust-analyzer
info: downloading component 'rust-analyzer'
info: installing component 'rust-analyzer'

zj@a:~/docs$ ls -l ~/.rustup/toolchains/stable-aarch64-apple-darwin/bin/
total 96M
-rwxr-xr-x 1 alizj  27M  5  5 12:11 cargo*
-rwxr-xr-x 1 alizj 1.1M  5  5 12:11 cargo-clippy*
-rwxr-xr-x 1 alizj 1.5M  5  5 12:11 cargo-fmt*
-rwxr-xr-x 1 alizj  11M  5  5 12:11 clippy-driver*
-rwxr-xr-x 1 alizj  39M  5  5 12:30 rust-analyzer*
-rwxr-xr-x 1 alizj  980  5  5 12:11 rust-gdb*
-rwxr-xr-x 1 alizj 2.2K  5  5 12:11 rust-gdbgui*
-rwxr-xr-x 1 alizj 1.1K  5  5 12:11 rust-lldb*
-rwxr-xr-x 1 alizj 626K  5  5 12:11 rustc*
-rwxr-xr-x 1 alizj  11M  5  5 12:11 rustdoc*
-rwxr-xr-x 1 alizj 6.3M  5  5 12:11 rustfmt*

zj@a:~/docs$ ln -sf ~/.rustup/toolchains/stable-aarch64-apple-darwin/bin/rust-analyzer ~/.rustup/toolchains/esp/bin/rust-analyzer

也可以从 esp-rs/rust 源码编译安装 rust-analyer:

# 在 --tools 中指定 rust-analyzer 来编译安装 esp32 使用的 rust-analyzer
./configure --experimental-targets=Xtensa --release-channel=nightly --enable-extended
  --tools=clippy,cargo,rustfmt,rust-analyzer --enable-lld

espup 安装的内容位于 ~/.espup 目录下,主要包含如下内容:

  • Espressif Rust fork with support for Espressif targets
  • nightly toolchain with support for RISC-V targets
  • LLVM fork with support for Xtensa targets
  • GCC toolchain that links the final binary
# 安装了两个 toolchain,分别是 nightly-x86_64-apple-darwin 和 esp
#
# nightly-x86_64-apple-darwin 是 rust 官方工具链,支持 riscv32xx 和 x86_64-apple-darwin 等 4 个 targets
# riscv32xx 是 esp32-c3 系列 RISC-V CPU 类型。
zj@a:~/esp$ rustup show
Default host: aarch64-apple-darwin
rustup home:  /Users/alizj/.rustup

installed toolchains
--------------------

stable-aarch64-apple-darwin (default) # 标准工具链
nightly-aarch64-apple-darwin
esp # 自定义 esp 工具链

active toolchain
----------------

stable-aarch64-apple-darwin (default)
rustc 1.78.0 (9b00956e5 2024-04-29)

# espup 安装的 esp 工具链, esp 为 channel 名称
zj@a:~/esp$ ls -l ~/.rustup/toolchains/esp/
total 0
drwxr-xr-x 12 alizj 384  5  5 12:12 bin/ # esp fork 的 rust 交叉编译工具链
drwxr-xr-x  3 alizj  96  5  5 12:12 etc/
drwxr-xr-x  5 alizj 160  5  5 12:13 lib/
drwxr-xr-x  3 alizj  96  5  5 12:12 libexec/
drwxr-xr-x  5 alizj 160  5  5 12:12 share/
drwxr-xr-x  3 alizj  96  5  5 12:11 xtensa-esp-elf/ # esp fork 的支持 xtensa CPU 的 gcc 等工具链
drwxr-xr-x  3 alizj  96  5  5 12:11 xtensa-esp32-elf-clang/ # esp fork 的 clang LLVM 工具链

# esp fork 的 rust 交叉编译工具链
zj@a:~/esp$ ls -l ~/.rustup/toolchains/esp/bin/
total 63M
-rwxr-xr-x 1 alizj  30M  5  5 12:12 cargo*
-rwxr-xr-x 1 alizj 1.2M  5  5 12:12 cargo-clippy*
-rwxr-xr-x 1 alizj 1.6M  5  5 12:12 cargo-fmt*
-rwxr-xr-x 1 alizj  11M  5  5 12:12 clippy-driver*
-rwxr-xr-x 1 alizj  980  5  5 12:12 rust-gdb*
-rwxr-xr-x 1 alizj 2.2K  5  5 12:12 rust-gdbgui*
-rwxr-xr-x 1 alizj 1.1K  5  5 12:12 rust-lldb*
-rwxr-xr-x 1 alizj 584K  5  5 12:12 rustc*
-rwxr-xr-x 1 alizj  12M  5  5 12:12 rustdoc*
-rwxr-xr-x 1 alizj 7.1M  5  5 12:12 rustfmt*

zj@a:~/docs$ ls -l ~/.rustup/toolchains/esp/bin/
total 59M
-rwxr-xr-x 1 zhangjun  28M  2  8 14:51 cargo*
-rwxr-xr-x 1 zhangjun 1.1M  2  8 14:51 cargo-clippy*
-rwxr-xr-x 1 zhangjun 1.6M  2  8 14:51 cargo-fmt*
-rwxr-xr-x 1 zhangjun  11M  2  8 14:51 clippy-driver*
lrwxr-xr-x 1 zhangjun   80  2  8 16:58 rust-analyzer -> /Users/zhangjun/.rustup/toolchains/nightly-x86_64-apple-darwin/bin/rust-analyzer*  # 链接到官方工具链的 rust-analyzer
-rwxr-xr-x 1 zhangjun  980  2  8 14:50 rust-gdb*
-rwxr-xr-x 1 zhangjun 2.2K  2  8 14:50 rust-gdbgui*
-rwxr-xr-x 1 zhangjun 1.1K  2  8 14:50 rust-lldb*
-rwxr-xr-x 1 zhangjun 664K  2  8 14:50 rustc*
-rwxr-xr-x 1 zhangjun  11M  2  8 14:50 rustdoc*
-rwxr-xr-x 1 zhangjun 6.9M  2  8 14:51 rustfmt*

# esp rustc 支持 x86_64/arm64/riscv64/xtensa-esp32s3-espidf/xtensa-esp32s3-none-elf target
# 后续可以在项目的 rust-toolchain.toml 和 .cargo/config.toml 中指定使用 esp channel 和对应的 target。
zj@a:~/docs$  ~/.rustup/toolchains/esp/bin/rustc --print target-list |grep -E 'xtensa|riscv'
riscv32gc-unknown-linux-gnu
riscv32gc-unknown-linux-musl
riscv32i-unknown-none-elf
riscv32im-unknown-none-elf
riscv32imac-esp-espidf
riscv32imac-unknown-none-elf
riscv32imac-unknown-xous-elf
riscv32imc-esp-espidf
riscv32imc-unknown-none-elf
riscv64-linux-android
riscv64gc-unknown-freebsd
riscv64gc-unknown-fuchsia
riscv64gc-unknown-hermit
riscv64gc-unknown-linux-gnu
riscv64gc-unknown-linux-musl
riscv64gc-unknown-netbsd
riscv64gc-unknown-none-elf
riscv64gc-unknown-openbsd
riscv64imac-unknown-none-elf
xtensa-esp32-espidf
xtensa-esp32-none-elf
xtensa-esp32s2-espidf
xtensa-esp32s2-none-elf
xtensa-esp32s3-espidf  # esp idf target,即 std 应用
xtensa-esp32s3-none-elf # none-elf 为 non_std 应用
xtensa-esp8266-none-elf

zj@a:~/esp$ ls -l  ~/.espup/
total 0
lrwxr-xr-x 1 alizj 92  5  5 12:11 esp-clang -> /Users/alizj/.rustup/toolchains/esp/xtensa-esp32-elf-clang/esp-16.0.4-20231113/esp-clang/lib/

# ~/esp/export-esp.sh 脚本将 LIBCLANG_PATH 环境变量指向 esp fork 的 LLVM 目录,这样后续 rustc 在编
# 译时自动链接 esp 的版本。(rustc 依赖 LLVM)。
zj@a:~/esp$ ls -l  /Users/alizj/.rustup/toolchains/esp/xtensa-esp32-elf-clang/esp-16.0.4-20231113/esp-clang/lib/
total 117M
drwxr-xr-x 3 alizj  96  5  5 12:11 clang/
-rw-r--r-- 1 alizj 50M 11 14 23:46 libLLVM.dylib
-rw-r--r-- 1 alizj 44M 11 14 23:46 libclang-cpp.dylib
-rw-r--r-- 1 alizj 24M 11 14 23:46 libclang.dylib

zj@a:~/esp$ cd ~/.rustup/toolchains/esp/xtensa-esp-elf/esp-13.2.0_20230928/xtensa-esp-elf/bin/
zj@a:~/.rustup/toolchains/esp/xtensa-esp-elf/esp-13.2.0_20230928/xtensa-esp-elf/bin$ ls -l *esp32s3*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-addr2line*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-ar*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-as*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-c++*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-c++filt*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-cc*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-cpp*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-elfedit*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-g++*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-gcc*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-gcc-13.2.0*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-gcc-ar*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-gcc-nm*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-gcc-ranlib*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-gcov*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-gcov-dump*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-gcov-tool*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-gprof*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-ld*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-ld.bfd*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-lto-dump*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-nm*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-objcopy*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-objdump*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-ranlib*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-readelf*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-size*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-strings*
-rwxr-xr-x 1 alizj 361K  9 29  2023 xtensa-esp32s3-elf-strip*
zj@a:~/.rustup/toolchains/esp/xtensa-esp-elf/esp-13.2.0_20230928/xtensa-esp-elf/bin$

# export-esp.sh 将该 bin 目录添加 PATH 前面
zj@a:~$ cd esp/
zj@a:~/esp$  ls ~/.rustup/toolchains/esp/xtensa-esp-elf/esp-*/xtensa-esp-elf/xtensa-esp-elf/bin/
ar*  as*  ld*  ld.bfd*  nm*  objcopy*  objdump*  ranlib*  readelf*  strip*

# 这些工具是 crosstool-NG 的 esp 版本
zj@a:~/docs$  ~/.rustup/toolchains/esp/xtensa-esp-elf/esp-13.2.0_20230928/xtensa-esp-elf/xtensa-esp-elf/bin/ld --version
GNU ld (crosstool-NG esp-13.2.0_20230928) 2.41
Copyright (C) 2023 Free Software Foundation, Inc.

# 它们支持 elf32-xtensa target
zj@a:~/docs$  ~/.rustup/toolchains/esp/xtensa-esp-elf/esp-13.2.0_20230928/xtensa-esp-elf/xtensa-esp-elf/bin/ld --help |grep supp
                              Enable support of non-contiguous memory regions
/Users/zhangjun/.rustup/toolchains/esp/xtensa-esp-elf/esp-13.2.0_20230928/xtensa-esp-elf/xtensa-esp-elf/bin/ld: supported targets: elf32-xtensa-le elf32-xtensa-be elf32-little elf32-big srec symbolsrec verilog tekhex binary ihex plugin
/Users/zhangjun/.rustup/toolchains/esp/xtensa-esp-elf/esp-13.2.0_20230928/xtensa-esp-elf/xtensa-esp-elf/bin/ld: supported emulations: elf32xtensa

# esp rustc 支持 x86_64/arm64/riscv64/xtensa-esp32s3-espidf/xtensa-esp32s3-none-elf target
# 后续可以在项目的 rust-toolchain.toml 和 .cargo/config.toml 中指定使用 esp channel 和对应的 target。
zj@a:~/docs$  ~/.rustup/toolchains/esp/bin/rustc --print target-list |grep -E 'xtensa|riscv'
riscv32gc-unknown-linux-gnu
riscv32gc-unknown-linux-musl
riscv32i-unknown-none-elf
riscv32im-unknown-none-elf
riscv32imac-esp-espidf
riscv32imac-unknown-none-elf
riscv32imac-unknown-xous-elf
riscv32imc-esp-espidf
riscv32imc-unknown-none-elf
riscv64-linux-android
riscv64gc-unknown-freebsd
riscv64gc-unknown-fuchsia
riscv64gc-unknown-hermit
riscv64gc-unknown-linux-gnu
riscv64gc-unknown-linux-musl
riscv64gc-unknown-netbsd
riscv64gc-unknown-none-elf
riscv64gc-unknown-openbsd
riscv64imac-unknown-none-elf
xtensa-esp32-espidf
xtensa-esp32-none-elf
xtensa-esp32s2-espidf
xtensa-esp32s2-none-elf
xtensa-esp32s3-espidf  # espidf 后缀的 target 为使用 eps-idf 的 std 应用
xtensa-esp32s3-none-elf # none-elf 后缀的 target 为不使用 esp-idf 的 non_std 应用
xtensa-esp8266-none-elf

更新 esp-rs 工具链:

zj@a:~/esp$ enable_socks_proxy
zj@a:~/esp$ espup update
rust-esp32 - 这篇文章属于一个选集。
§ 3: 本文

相关文章

Rust 驱动 Audio - 播放和录音
·6323 字
Rust Esp32 Rust Esp32
Rust 驱动 Camera - 采集和播放
·7304 字
Rust Esp32 Rust Esp32
Rust 驱动 LCD - 显示中英文
·818 字
Rust Esp32 Rust Esp32
Rust 驱动 LCD - 显示图片
·4232 字
Rust Esp32 Rust Esp32