本帖最后由 sandman78 于 2018-4-12 11:41 编辑
Linux支持应用程序通过sysfs在用户空间进行GPIO的控制或读取状态,这里采用Rust语言的sysfs_gpio crate实现IO控制。
Rust中, crate是一个独立的可编译单元。具体说来,就是一个或一批文件。它编译后,会对应着生成一个可执行文件或一个库。sysfs_gpio提供了方便的访问GPIO的方法。
为了简化描述,这里采用sysfs_gpio仓库里面的例子说明
首先下载代码到本地
- $ git clone github.com/rust-embedded/rust-sysfs-gpio
- $ cd rust-sysfs-gpio
复制代码
编译完成后,可在target/armv7-unknown-linux-gnueabihf/debug/examples 目录下看到生成的可执行文件blinky,将该文件复制到开发板中,加入可执行权限。
交叉编译IO输出的例子程序
- $ cargo build --example blinky --target armv7-unknown-linux-gnueabihf
复制代码
输入./blinky,可看到提示Usage: ./blinky tion_ms> ,该程序需要三个参数,分别是操作的GPIO,运行时间和闪烁时间。
MYB-Y6ULX 提供了扩展口,这里选用扩展接口J14的8脚测试,经查找芯片手册可知该脚为gpio1.IO26,对应Linux中的GPIO26,在该脚接入发光二极管电路,运行程序
可看到对应管脚电平高低变化5次。
核心代码如下
- fn blink_my_led(led: u64, duration_ms: u64, period_ms: u64) -> sysfs_gpio::Result<()> {
- let my_led = Pin::new(led);
- my_led.with_exported(|| {
- my_led.set_direction(Direction::Low)?;
- let iterations = duration_ms / period_ms / 2;
- for _ in 0..iterations {
- my_led.set_value(0)?;
- sleep(Duration::from_millis(period_ms));
- my_led.set_value(1)?;
- sleep(Duration::from_millis(period_ms));
- }
- my_led.set_value(0)?;
- Ok(())
- })
- }
复制代码
下面解释一下执行过程,
- let my_led = Pin::new(led);
复制代码
构建一个Pin
- my_led.with_exported(|| {
- ....
复制代码
导出GPIO, 想当于执行 echo N > /sys/class/gpio/export, 这里使用了闭包的语法
- my_led.set_direction(Direction::Low)?
复制代码
设置端口为输出,并输出低电平
设置端口输出高电平
完整代码如下
- extern crate sysfs_gpio;
- use sysfs_gpio::{Direction, Pin};
- use std::time::Duration;
- use std::thread::sleep;
- use std::env;
- struct Arguments {
- pin: u64,
- duration_ms: u64,
- period_ms: u64,
- }
- // Export a GPIO for use. This will not fail if already exported
- fn blink_my_led(led: u64, duration_ms: u64, period_ms: u64) -> sysfs_gpio::Result<()> {
- let my_led = Pin::new(led);
- my_led.with_exported(|| {
- my_led.set_direction(Direction::Low)?;
- let iterations = duration_ms / period_ms / 2;
- for _ in 0..iterations {
- my_led.set_value(0)?;
- sleep(Duration::from_millis(period_ms));
- my_led.set_value(1)?;
- sleep(Duration::from_millis(period_ms));
- }
- my_led.set_value(0)?;
- Ok(())
- })
- }
- fn print_usage() {
- println!("Usage: ./blinky ");
- }
- fn get_args() -> Option {
- let args: Vec = env::args().collect();
- if args.len() != 4 {
- return None;
- }
- let pin = match args[1].parse::() {
- Ok(pin) => pin,
- Err(_) => return None,
- };
- let duration_ms = match args[2].parse::() {
- Ok(ms) => ms,
- Err(_) => return None,
- };
- let period_ms = match args[3].parse::() {
- Ok(ms) => ms,
- Err(_) => return None,
- };
- Some(Arguments {
- pin: pin,
- duration_ms: duration_ms,
- period_ms: period_ms,
- })
- }
- fn main() {
- match get_args() {
- None => print_usage(),
- Some(args) => {
- match blink_my_led(args.pin, args.duration_ms, args.period_ms) {
- Ok(()) => println!("Success!"),
- Err(err) => println!("We have a blinking problem: {}", err),
- }
- }
- }
- }
复制代码
|