我正在尝试使用 Rust 实现一些在 Linux PC 上处理 UART 通信的东西。这是我第一次用 Rust 写任何东西,所以我可能完全放弃了。
因为我的协议的通信有点异步,所以我想使用
tokio
。我发现了 tokio_serial
板条箱,它似乎将串行端口包装到异步可用的 API 中。
我尝试了以下代码。它应该在 uart 端口上接收数据并将其打印到控制台并回显字节。这很好用。
但是,我的程序在收到第一个字节后消耗了 100% CPU 负载。只要尚未接收到数据,它就可以正常工作并且不会消耗 CPU。我添加了注释掉的 println!声明并看到,
port.readable().await;
实际上不会阻塞,而是在没有任何实际可读数据的情况下完成。
我在这里做错了什么?
use std::{env, io::Write, process, str};
use tokio_serial::{self, SerialPortBuilderExt};
#[tokio::main(flavor = "current_thread")]
async fn main() {
let baud_rate : u32 = 115200;
let serial_port = env::args().nth(1).unwrap_or_else(|| {String::from("/dev/ttyUSB0")});
println!("Open port {serial_port}");
let mut port = tokio_serial::new(serial_port, baud_rate).open_native_async().unwrap_or_else(
|e| {
println!("Error: {:?}", e);
process::exit(-1);
}
);
let mut buf : [u8; 255] = [0;255];
loop {
let readable_res = port.readable().await;
if let Ok(()) = readable_res {
match port.try_read(&mut buf) {
Ok(size) => {
println!("Got {} bytes: {}", size, str::from_utf8(&buf[0..size]).unwrap());
port.write(&buf[0..size]).unwrap_or_else(|e| {println!("{:?}", e); 0});
},
Err(e) => {
//println!("{:?}", e);
}
}
}
}
}