开始一个新的Embassy项目

当你成功地运行一些示例项目后,下一步就是创建一个独立的Embassy项目。

有一些生成Embassy项目的工具(正在开发中):

命令行(CLI)

cargo-generate

如果您想从零开始:

以STM32G474为例,让我们来创建一个全新的Embassy项目。该指南也适用于任何支持的芯片,只需做一些小小的改动。

运行:

cargo new stm32g474-example
cd stm32g474-example

来创建一个空的rust项目:

stm32g474-example
├── Cargo.toml
└── src
    └── main.rs

查看 Embassy examples , 我们可以看到有一个 stm32g4 文件夹。 将 src/blinky.rs 的内容复制到 src/main.rs

.cargo/config.toml

现在,我们每次运行 cargo build 或者 cargo run 都需要给cargo提供一个 target triple(-target <triple>) 。让我们一劳永逸,从 examples/stm32g4 复制 .cargo/config.toml 到我们的项目中。

stm32g474-example
├── .cargo
│   └── config.toml
├── Cargo.toml
└── src
    └── main.rs

除了target triple,.cargo/config.toml 还包含一个 runner 键,让我们可以通过probe-rs运行 cargo run 。为了让它正常工作,我们需要提供正确的芯片ID。可以通过 probe-rs chip list 获取它:

$ probe-rs chip list | grep -i stm32g474re
        STM32G474RETx

然后复制 STM32G474RETx.cargo/config.toml ,就像这样:

[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# 替换STM32G071C8Rx为你使用 `probe-rs chip list` 获取到的芯片ID
runner = "probe-rs run --chip STM32G474RETx"

Cargo.toml

现在cargo已经知道要为哪个目标编译(probe-rs也知道它会在哪个芯片上运行),让我们添加一些依赖项。

查看 examples/stm32g4/Cargo.toml ,我们可以看到示例所需要的一系列embassy crate。对于blinky项目,我们只需要其中的三个: embassy-stm32embassy-executorembassy-time

在撰写本文时,embassy的最新版本还没有在crates.io上发布,所以我们需要直接从git仓库安装。推荐的安装方法如下:

  • 从示例中复制所需的 embassy-* 行到 Cargo.toml

  • features 进行必要的更改,例如:需要 embassy-stm32 中的 stm32g474re feature

  • 移除 embassy-* 条目中的 path = ""

  • 创建一个 [patch.crates-io] 部分(section),列出我们需要的embassy crate。它们应该包含相同的值:一个指向git仓库的链接,以及我们正在检出的提交的引用。你可以通过运行 git ls-remote https://github.com/embassy-rs/embassy.git HEAD 来找到最新的提交

注意:使用这种方法时, [dependencies] 必须与 [patch.crates.io] 下的rev键对应的Cargo.toml的crate version相匹配。这意味着在更新时,你必须选择一个新的修订版本(revision),修改 [patch.crates.io] 中的所有相关内容,然后更正 [dependencies] 下已更改的内容。好复杂,希望一旦embassy在crates.io上发布,就不再需要这样做了!

这是撰写本文时按照上述方法写出的:

[dependencies]
embassy-stm32 = {version = "0.1.0", features =  ["defmt", "time-driver-any", "stm32g474re", "memory-x", "unstable-pac", "exti"]}
embassy-executor = { version = "0.3.3", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
embassy-time = { version = "0.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }

[patch.crates-io]
embassy-time = { git = "https://github.com/embassy-rs/embassy", rev = "7703f47c1ecac029f603033b7977d9a2becef48c" }
embassy-executor = { git = "https://github.com/embassy-rs/embassy", rev = "7703f47c1ecac029f603033b7977d9a2becef48c" }
embassy-stm32 = { git = "https://github.com/embassy-rs/embassy", rev = "7703f47c1ecac029f603033b7977d9a2becef48c" }

我们还需要一些其他的依赖项来构建项目,但幸运的是,它们的安装要简单得多。将它们从示例的 Cargo.toml 复制到新的 Cargo.toml 中的 [dependencies] 部分:

defmt = "0.3.5"
defmt-rtt = "0.4.0"
cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]}
cortex-m-rt = "0.7.3"
panic-probe = "0.3.1"

这些是运行 blinky.rs`所需的最少依赖项,但示例 `Cargo.toml`中指定的其他依赖项也值得一看————注意与embassy一起使用所需的功能 — 例如 `futures = { version = "0.3.17", default-features = false, features = ["async-await"] }

最后,将示例`Cargo.toml` 中的 [profile.release] 部分复制到我们的文件中。

[profile.release]
debug = 2

rust-toolchain.toml

在我们构建项目之前,我们还需要添加一个额外的文件来告诉cargo使用nightly工具链。将 rust-toolchain.toml 从embassy仓库复制到我们的项目,只需要保留target triple列表中我们需要的。 在这个例子中,是 thumbv7em-none-eabi

stm32g474-example
├── .cargo
│   └── config.toml
├── Cargo.toml
├── rust-toolchain.toml
└── src
    └── main.rs
# 在更新前请确认第一层(tier1)targets的一切都是可用的
# https://rust-lang.github.io/rustup-components-history
[toolchain]
channel = "nightly-2023-11-01"
components = [ "rust-src", "rustfmt", "llvm-tools", "miri" ]
targets = ["thumbv7em-none-eabi"]

build.rs

为了给我们的目标生成一个可工作的二进制文件,cargo需要一个自定义的构建脚本。将示例中的 build.rs 复制到我们的项目中:

stm32g474-example
├── build.rs
├── .cargo
│   └── config.toml
├── Cargo.toml
├── rust-toolchain.toml
└── src
    └── main.rs

构建和运行

现在,我们终于准备好构建和运行我们的项目了!通过调试器连接您的板子并运行:

cargo run --release

应该会有一个LED闪烁 (需要有一个LED连接到 src/main.rs 中定义的引脚,如果不是请修改) 。输出如下:

   Compiling stm32g474-example v0.1.0 (/home/you/stm32g474-example)
    Finished release [optimized + debuginfo] target(s) in 0.22s
     Running `probe-rs run --chip STM32G474RETx target/thumbv7em-none-eabi/release/stm32g474-example`
     Erasing sectors ✔ [00:00:00] [#########################################################] 18.00 KiB/18.00 KiB @ 54.09 KiB/s (eta 0s )
 Programming pages   ✔ [00:00:00] [#########################################################] 17.00 KiB/17.00 KiB @ 35.91 KiB/s (eta 0s )    Finished in 0.817s
0.000000 TRACE BDCR configured: 00008200
└─ embassy_stm32::rcc::bd::{impl#3}::init::{closure#4} @ /home/you/.cargo/git/checkouts/embassy-9312dcb0ed774b29/7703f47/embassy-stm32/src/fmt.rs:117
0.000000 DEBUG rcc: Clocks { sys: Hertz(16000000), pclk1: Hertz(16000000), pclk1_tim: Hertz(16000000), pclk2: Hertz(16000000), pclk2_tim: Hertz(16000000), hclk1: Hertz(16000000), hclk2: Hertz(16000000), pll1_p: None, adc: None, adc34: None, rtc: Some(Hertz(32000)) }
└─ embassy_stm32::rcc::set_freqs @ /home/you/.cargo/git/checkouts/embassy-9312dcb0ed774b29/7703f47/embassy-stm32/src/fmt.rs:130
0.000000 INFO  Hello World!
└─ embassy_stm32g474::____embassy_main_task::{async_fn#0} @ src/main.rs:14
0.000091 INFO  high
└─ embassy_stm32g474::____embassy_main_task::{async_fn#0} @ src/main.rs:19
0.300201 INFO  low
└─ embassy_stm32g474::____embassy_main_task::{async_fn#0} @ src/main.rs:23