实验开发板: Luckfox Lyra
首先安装 arm-unknown-linux-gnueabihf 编译器
$ rustup target add arm-unknown-linux-gnueabihf
$ rustup target list
aarch64-apple-darwin
aarch64-apple-ios
aarch64-apple-ios-macabi
aarch64-apple-ios-sim
aarch64-linux-android
aarch64-pc-windows-gnullvm
aarch64-pc-windows-msvc
aarch64-unknown-fuchsia
aarch64-unknown-linux-gnu
aarch64-unknown-linux-musl
aarch64-unknown-linux-ohos
aarch64-unknown-none
aarch64-unknown-none-softfloat
aarch64-unknown-uefi
arm-linux-androideabi
arm-unknown-linux-gnueabi
arm-unknown-linux-gnueabihf (installed)
arm-unknown-linux-musleabi
arm-unknown-linux-musleabihf
arm64ec-pc-windows-msvc
armebv7r-none-eabi
armebv7r-none-eabihf
armv5te-unknown-linux-gnueabi
armv5te-unknown-linux-musleabi
armv7-linux-androideabi
armv7-unknown-linux-gnueabi
armv7-unknown-linux-gnueabihf
armv7-unknown-linux-musleabi
armv7-unknown-linux-musleabihf
armv7-unknown-linux-ohos
armv7a-none-eabi
armv7r-none-eabi
armv7r-none-eabihf
i586-unknown-linux-gnu
i586-unknown-linux-musl
i686-linux-android
i686-pc-windows-gnu
i686-pc-windows-gnullvm
i686-pc-windows-msvc
i686-unknown-freebsd
i686-unknown-linux-gnu
i686-unknown-linux-musl
i686-unknown-uefi
loongarch64-unknown-linux-gnu
loongarch64-unknown-linux-musl
loongarch64-unknown-none
loongarch64-unknown-none-softfloat
nvptx64-nvidia-cuda
powerpc-unknown-linux-gnu
powerpc64-unknown-linux-gnu
powerpc64le-unknown-linux-gnu
powerpc64le-unknown-linux-musl
riscv32i-unknown-none-elf
riscv32im-unknown-none-elf
riscv32imac-unknown-none-elf
riscv32imafc-unknown-none-elf
riscv32imc-unknown-none-elf
riscv64gc-unknown-linux-gnu
riscv64gc-unknown-linux-musl
riscv64gc-unknown-none-elf
riscv64imac-unknown-none-elf
s390x-unknown-linux-gnu
sparc64-unknown-linux-gnu
sparcv9-sun-solaris
thumbv6m-none-eabi
thumbv7em-none-eabi
thumbv7em-none-eabihf
thumbv7m-none-eabi
thumbv7neon-linux-androideabi
thumbv7neon-unknown-linux-gnueabihf
thumbv8m.base-none-eabi
thumbv8m.main-none-eabi
thumbv8m.main-none-eabihf
wasm32-unknown-emscripten
wasm32-unknown-unknown
wasm32-wasip1
wasm32-wasip1-threads
wasm32-wasip2
wasm32v1-none
x86_64-apple-darwin
x86_64-apple-ios
x86_64-apple-ios-macabi
x86_64-fortanix-unknown-sgx
x86_64-linux-android
x86_64-pc-solaris
x86_64-pc-windows-gnu
x86_64-pc-windows-gnullvm
x86_64-pc-windows-msvc
x86_64-unknown-freebsd
x86_64-unknown-fuchsia
x86_64-unknown-illumos
x86_64-unknown-linux-gnu (installed)
x86_64-unknown-linux-gnux32
x86_64-unknown-linux-musl
x86_64-unknown-linux-ohos
x86_64-unknown-netbsd
x86_64-unknown-none
x86_64-unknown-redox
x86_64-unknown-uefi
使用 Cargo 创建一个项目, 然后在项目的根目录创建一个文件夹并创建一个文件(.cargo/config
), 这个文件是用来配置Cargo使用其他编译器, 详细看这篇文章 https://course.rs/cargo/reference/configuration.html
[build]
jobs = 8
target = "arm-unknown-linux-gnueabihf"
[target.arm-unknown-linux-gnueabihf]
linker = "/home/think/work/Lyra-sdk/prebuilts/gcc/linux-x86/arm/gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-gcc"
其中只配置target编译会报连接失败的错误, 所以要加linker的路径, 如何配置了环境变量就需要就对路径, 我只是偷懒使用了sdk中的工具
之后使用cargo就可以编译成功了, 把编译出来的程序传到开发板上就可以运行了, 注意: rust工程交叉编译后的程序在编译器对应的文件夹里, 所以默认路径在: target/arm-unknown-linux-gnueabihf/debug/hello-rust
是不是非常简单, 接着编写一个控制GPIO程序, 这里要注意一下: 如果使用File来操作文件会报没有权限的问题, 原因可能是Rust的File打开文件权限是可读可写的, 但是GPIO操作的文件只能写, 所以报了没有权限的错误, 所以要使用OpenOptions能控制文件权限的接口操作文件: GPIO | LUCKFOX WIKI
use std::{fs::{OpenOptions}, io::{Read, Write}, thread::sleep, time::Duration};
const GPIO_PATH: &str = "/sys/class/gpio";
fn delete_gpio(pin_num: &str) {
if let Ok(mut f) = OpenOptions::new().write(true).open(format!("{}/unexport", GPIO_PATH)) {
write!(f, "{}", pin_num)
.expect("Failed to write to unexport file");
println!("Pin {} unexported", pin_num);
} else {
println!("Failed to open unexport file");
}
}
fn main() -> std::io::Result<()> {
println!("Hello, world!");
let args: Vec<String> = std::env::args().collect();
let pin_num = args
.get(1)
.expect("Please provide a pin number as an argument");
match OpenOptions::new().write(true).open(format!("{}/export", GPIO_PATH)) {
Ok(mut f) => {
write!(f, "{}", pin_num)
.expect("Failed to write to export file");
}
Err(e) => {
println!("Failed to open export file, error: {}", e);
}
}
let pin_num_cp = pin_num.clone();
std::panic::set_hook(Box::new(move |panic_info| {
delete_gpio(pin_num_cp.as_str());
println!("Panic occurred: {}", panic_info);
}));
let pin_num_cp = pin_num.clone();
ctrlc::set_handler(move || {
delete_gpio(pin_num_cp.as_str());
println!("Exiting...");
std::process::exit(0);
})
.expect("Error setting Ctrl-C handler");
if let Ok(mut f) = OpenOptions::new().write(true).open(format!("{}/gpio{}/direction", GPIO_PATH, pin_num)) {
write!(f, "out")
.expect("Failed to write to direction file");
} else {
println!("Failed to set direction for pin {}", pin_num);
return Ok(());
}
let mut value = "1";
loop {
if let Ok(mut f) = OpenOptions::new().write(true).open(format!("{}/gpio{}/value", GPIO_PATH, pin_num)) {
write!(f, "{}", value)
.expect("Failed to write to value file");
}
if let Ok(mut f) = OpenOptions::new().read(true).open(format!("{}/gpio{}/value", GPIO_PATH, pin_num)) {
let mut str = String::new();
f.read_to_string(&mut str)
.expect("Failed to write to value file");
println!("Pin {} value: {}", pin_num, str.trim());
}
value = if value == "1" { "0" } else { "1" };
sleep(Duration::from_secs(1));
}
}
这里使用了一个库用来挂ctrlc信号的:
[dependencies]
ctrlc = "3.1.7"
运行结果:
root@luckfox:~# ./hello-rust 10
Hello, world!
Pin 10 value: 1
Pin 10 value: 0
Pin 10 value: 1
Pin 10 value: 0
Pin 10 value: 1
Pin 10 value: 0
Pin 10 value: 1
Pin 10 value: 0
Pin 10 value: 1
^CExiting...
评论区
写评论还没有评论