实时传输(Real-Time Transfer, RTT)
在开发嵌入式系统时,你需要一种方式来观察程序内部的运行情况。在普通计算机上,你可以使用 println! 将消息打印到终端。但在微控制器上,并没有连接屏幕或终端。实时传输(Real-Time Transfer, RTT)通过允许你将调试信息和日志从微控制器发送到电脑,解决了这一问题。
什么是 RTT?
RTT 是一种通信方法,可让你的微控制器通过已用于烧录程序的调试器(debug probe)向电脑发送消息。
当你将 Raspberry Pi 调试器连接到 Pico 时,就建立了一个具备以下两种功能的连接:
- 向芯片烧录新程序
- 读写芯片内存
RTT 利用了这种内存访问能力。它在微控制器上创建特殊的内存缓冲区,调试器则读取这些缓冲区,并将消息显示在你的电脑上。这一切都在后台进行,不会影响程序的正常运行。
使用 Defmt 进行日志记录
Defmt(“deferred formatting”,即“延迟格式化”的缩写)是一个专为资源受限设备(如微控制器)设计的日志框架。在你的 Rust 嵌入式项目中,你将使用 defmt 来打印消息并调试程序。
Defmt 通过延迟格式化和字符串压缩实现高性能。所谓延迟格式化,是指格式化操作并非在记录日志的设备上完成,而是在另一台设备(如你的电脑)上进行。
你的 Pico 发送的是小型代码,而非完整的文本消息。你的电脑接收这些代码并将其还原为可读的文本。这种方式使固件体积更小,并避免了在微控制器上执行缓慢的字符串格式化操作。
你可以在项目中添加 defmt 依赖:
defmt = "1.0.1"
然后像这样使用它:
#![allow(unused)] fn main() { use defmt::{info, warn, error}; ... info!("Starting program"); warn!("You shall not pass!"); error!("Something went wrong!"); }
Defmt RTT
Defmt 本身并不知道如何将消息从 Pico 发送到电脑,它需要一个传输层。这就是 defmt-rtt 的作用所在。
defmt-rtt crate 将 defmt 与 RTT 连接起来,使你的日志消息能通过调试器传输到电脑。
你可以在项目中添加 defmt-rtt 依赖:
defmt-rtt = "1.0"
注意:要查看 RTT 和 defmt 日志,你需要使用
probe-rs工具(例如cargo embed命令)运行程序。这些工具会自动开启 RTT 会话,并在终端中显示日志。
然后在代码中引入它:
#![allow(unused)] fn main() { use defmt_rtt as _; }
这行代码建立了 defmt 与 RTT 之间的连接。你无需直接调用其中的任何函数,但必须导入该 crate 才能使其生效。
使用 Panic-Probe 显示 Panic 信息
当程序崩溃(panic)时,你希望看到具体出错的原因。panic-probe crate 可以让 panic 信息通过 defmt 和 RTT 显示出来。
你可以在项目中添加 panic-probe 依赖:
# print-defmt 特性:告诉 panic-probe 使用 defmt 输出信息。
panic-probe = { version = "1.0", features = ["print-defmt"] }
然后在代码中引入它:
#![allow(unused)] fn main() { use panic_probe as _; }
你可以手动触发一次 panic 来测试 panic 信息的显示效果。尝试在代码中加入以下内容:
#![allow(unused)] fn main() { panic!("something went wrong"); }