启动新项目
一旦你成功地 xref:#_getting_started[运行了一些示例项目],下一步就是创建一个独立的 Embassy 项目。
用于生成 Embassy 项目的工具
CLI
- link:https://github.com/adinack/cargo-embassy[cargo-embassy] (STM32 和 NRF)
cargo-generate
- link:https://github.com/lulf/embassy-template[embassy-template] (STM32, NRF, 和 RP)
- link:https://github.com/bentwire/embassy-rp2040-template[embassy-rp2040-template] (RP)
从零开始创建项目
作为示例,让我们从零开始为一个 STM32G474 创建一个新的 embassy 项目。相同的指令适用于任何受支持的芯片,只需进行一些小的更改。
运行:
cargo new stm32g474-example
cd stm32g474-example
创建一个空的 rust 项目:
stm32g474-example
├── Cargo.toml
└── src
└── main.rs
查看 link:https://github.com/embassy-rs/embassy/tree/main/examples[Embassy 示例],我们可以看到有一个 stm32g4
文件夹。找到 src/blinky.rs
并将其内容复制到我们的 src/main.rs
中。
.cargo/config.toml
目前,每次运行 cargo build
或 cargo run
时,我们都需要为 cargo 提供一个目标三元组。让我们通过从 examples/stm32g4
复制 .cargo/config.toml
到我们的项目来省去这项工作。
stm32g474-example
├── .cargo
│ └── config.toml
├── Cargo.toml
└── src
└── main.rs
除了目标三元组之外,.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` 中所列
runner = "probe-rs run --chip STM32G474RETx"
Cargo.toml
现在 cargo 知道要为哪个目标编译(并且 probe-rs 知道要在哪个芯片上运行),我们准备添加一些依赖项。
查看 examples/stm32g4/Cargo.toml
,我们可以看到示例需要许多 embassy crate。对于 blinky 示例,我们只需要其中三个:embassy-stm32
、embassy-executor
和 embassy-time
。
在编写本文时,embassy 已经发布到 crates.io。因此,可以轻松地通过 Cargo.toml 添加依赖项。
[dependencies]
embassy-stm32 = { version = "0.1.0", features = ["defmt", "time-driver-any", "stm32g474re", "memory-x", "unstable-pac", "exti"] }
embassy-executor = { version = "0.6.3", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt"] }
embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
之前,embassy 需要直接从 git 仓库安装。如果您想检出尚未发布的 embassy crate 的特定修订版,从 git 安装仍然很有用。 推荐的方法如下:
- 从示例
Cargo.toml
复制所需的embassy-*
行 - 对
features
进行任何必要的更改,例如需要embassy-stm32
的stm32g474re
功能 - 删除
embassy-*
条目中的path = ""
键 - 创建一个
[patch.crates-io]
部分,其中包含我们需要的每个 embassy crate 的条目。这些条目应包含相同的值:git 仓库的链接,以及对我们正在检出的提交的引用。假设您想要最新的提交,您可以通过运行git ls-remote https://github.com/embassy-rs/embassy.git HEAD
找到它
注意:使用此方法时,[dependencies]
中的 version
键必须与 [patch.crates.io]
下指定的 rev
中每个 crate 的 Cargo.toml
中定义的版本匹配。这意味着在更新时,您必须选择一个新的修订版,更改 [patch.crates.io]
中的所有内容以匹配它,然后更正 [dependencies]
下已更改的任何版本。
一个示例 Cargo.toml 文件可能如下所示:
[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"] }
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 工具链。将 embassy 仓库中的 rust-toolchain.toml
复制到我们的仓库中,并将目标列表修剪为仅与我们的项目相关的目标三元组 - 在本例中为 thumbv7em-none-eabi
:
stm32g474-example
├── .cargo
│ └── config.toml
├── Cargo.toml
├── rust-toolchain.toml
└── src
└── main.rs
# 在升级之前,请在此处检查所有 tier1 目标上是否都可用:
# 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