常见问题解答
这里是一些未排序的常见问题及解答。
如果你在聊天中得到了问题的答案,欢迎随时在 此页面 添加内容!
如何在没有 debugging probe 的情况下部署到 RP2040
安装 elf2uf2-rs,用于将生成的 elf 二进制文件转换为 uf2 文件。
配置 runner 使用该工具,在 .cargo/config.toml 中添加如下内容:
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "elf2uf2-rs --deploy --serial --verbose"
命令行参数 --deploy 会自动检测你的设备并上传二进制文件,--serial 会启动串口连接。更多信息请查阅文档。
缺少 main 宏
如果你看到如下错误:
#[embassy_executor::main]
| ^^^^ could not find `main` in `embassy_executor`
你很可能缺少了 embassy-executor crate 的某些特性。
对于 Cortex-M 目标,请确保在 Cargo.toml 的 embassy-executor crate 中启用了以下所有特性:
-
arch-cortex-m -
executor-thread
对于 ESP32,请考虑使用对应 HAL crate 提供的 executors 和 #[main] 宏。
为什么我的二进制文件这么大?
管理二进制体积的第一步是设置 profiles。
[profile.release]
lto = true
opt-level = "s"
incremental = false
codegen-units = 1
# 注意:设置 debug = true 没问题,调试信息不会被烧录到设备!
debug = true
这些参数的详细说明见上面链接的 Rust Book 页面。
我的二进制依然很大,充满了 std::fmt 相关内容!
这说明你的代码足够复杂,panic! 的格式化需求没有被优化掉,即使你用了 panic-halt 或 panic-reset。
你可以在 .cargo/config.toml 中添加如下内容来解决:
[unstable]
build-std = ["core"]
build-std-features = ["panic_immediate_abort"]
这会将所有 panic 替换为 UDF(未定义)指令。
具体行为取决于芯片型号。
请查阅芯片手册,对于 thumbv6m,这会导致 hardfault。可以这样配置:
#[exception]
unsafe fn HardFault(_frame: &ExceptionFrame) -> ! {
SCB::sys_reset() // 你也可以做其他操作
}
更多信息请查阅 cortex-m 的 异常处理。
embassy-time 报链接错误
如果你看到如下链接错误:
= note: rust-lld: error: undefined symbol: _embassy_time_now
>>> referenced by driver.rs:127 (src/driver.rs:127)
>>> embassy_time-846f66f1620ad42c.embassy_time.4f6a638abb75dd4c-cgu.0.rcgu.o:(embassy_time::driver::now::hefb1f99d6e069842) in archive Devel/Embedded/pogodyna/target/thumbv7em-none-eabihf/debug/deps/libembassy_time-846f66f1620ad42c.rlib
rust-lld: error: undefined symbol: _embassy_time_allocate_alarm
>>> referenced by driver.rs:134 (src/driver.rs:134)
>>> embassy_time-846f66f1620ad42c.embassy_time.4f6a638abb75dd4c-cgu.0.rcgu.o:(embassy_time::driver::allocate_alarm::hf5145b6bd46706b2) in archive Devel/Embedded/pogodyna/target/thumbv7em-none-eabihf/debug/deps/libembassy_time-846f66f1620ad42c.rlib
rust-lld: error: undefined symbol: _embassy_time_set_alarm_callback
>>> referenced by driver.rs:139 (src/driver.rs:139)
>>> embassy_time-846f66f1620ad42c.embassy_time.4f6a638abb75dd4c-cgu.0.rcgu.o:(embassy_time::driver::set_alarm_callback::h24f92388d96eafd2) in archive Devel/Embedded/pogodyna/target/thumbv7em-none-eabihf/debug/deps/libembassy_time-846f66f1620ad42c.rlib
rust-lld: error: undefined symbol: _embassy_time_set_alarm
>>> referenced by driver.rs:144 (src/driver.rs:144)
>>> embassy_time-846f66f1620ad42c.embassy_time.4f6a638abb75dd4c-cgu.0.rcgu.o:(embassy_time::driver::set_alarm::h530a5b1f444a6d5b) in archive Devel/Embedded/pogodyna/target/thumbv7em-none-eabihf/debug/deps/libembassy_time-846f66f1620ad42c.rlib
你可能需要为 HAL 启用时间驱动(不是在 embassy-time 里!)。比如 embassy-stm32,你需要启用 time-driver-any:
[dependencies.embassy-stm32]
version = "0.1.0"
features = [
# ...
"time-driver-any", # 添加这一行!
# ...
]
如果你在项目早期阶段还没用到 HAL 的任何内容,请确保 HAL 被显式使用,防止链接器将其当作无用代码移除,在源码中加上:
use embassy_stm32 as _;
错误:Only one package in the dependency graph may specify the same links value.
你的依赖树中有多个版本的同一个 crate。这意味着有些 embassy crate 来自 crates.io,有些来自 git,导致依赖不一致。
解决方法:确保所有 embassy crate 都来自同一个源!
你可以用 [patch.crates.io] 和(如有需要)[patch.'https://github.com/embassy-rs/embassy.git'] 来统一依赖。
示例:
[patch.crates-io]
embassy-time-queue-driver = { git = "https://github.com/embassy-rs/embassy.git", rev = "e5fdd35" }
embassy-time-driver = { git = "https://github.com/embassy-rs/embassy.git", rev = "e5fdd35" }
# embassy-time = { git = "https://github.com/embassy-rs/embassy.git", rev = "e5fdd35" }
注意 git 版本号要和你用的其他 embassy 依赖一致!
如何优化我的 embassy-stm32 程序的速度?
-
确保 RCC 设置为最高速
-
确保启用了 flash cache
-
用
--release构建 -
在
Cargo.toml的 release 配置中设置:-
opt-level = "s" -
lto = "fat"
-
-
在
.cargo/config.toml的[unstable]部分设置:-
build-std = ["core"] -
build-std-features = ["panic_immediate_abort"]
-
-
启用特性
embassy-time/generic-queue,禁用embassy-executor/integrated-timers -
使用
InterruptExecutor时:-
禁用
executor-thread -
让
main启动所有任务,然后启用 SCB.SLEEPONEXIT 并loop { cortex_m::asm::wfi() } -
注意:如果需要 2 个优先级,建议用 2 个中断执行器,而不是 1 个线程执行器 + 1 个中断执行器。
-
如何在 stable 上配置任务 arena?
未启用 embassy-executor 的 nightly 特性时,执行器使用 bump allocator,可能需要配置。
如果任务 arena 太大,编译时会报错:
rust-lld: error: section '.bss' will not fit in region 'RAM': overflowed by _ bytes
rust-lld: error: section '.uninit' will not fit in region 'RAM': overflowed by _ bytes
如果任务 arena 太小,运行时会报错:
ERROR panicked at 'embassy-executor: task arena is full. You must increase the arena size, see the documentation for details: https://docs.embassy.dev/embassy-executor/'
注意:如果所有任务都在启动时被 spawn,这个 panic 会立刻发生。
更多细节见 任务 Arena 文档。
可以和 Embassy 一起用手写 ISR 吗?
可以!如果你需要尽可能快地响应事件,而常规的“ISR、唤醒、从 ISR 返回、上下文切换到被唤醒任务”流程延迟太大,可以像 其他嵌入式 Rust 项目 一样,直接定义 #[interrupt] fn INTERRUPT_NAME() {} 处理函数。
如何测量资源使用(CPU、RAM 等)?
最大栈使用
可用 cargo-call-stack 静态分析最坏情况栈用量。该工具有一些已知限制,详情见 README。