有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 sky 于 2021-5-12 15:12 编辑
如下是来自RVBoards开源小组liangdi关于「哪吒开发板」的技术文章。
一、用 Rust 探索RISC-V 主板 全志D1芯片之GPIO
gpio 是单片机或者单板机和外部硬件沟通的桥梁,通过它可以控制外部硬件,可以建立通讯,可以获取传感器数据等
D1 开发板和树莓派一样,对外引出了 40pin 引脚, 这些引脚包含3.3v,5v供电, GND , 以及几个未使用(NC)引脚, 然后就是我们要讲到的 GPIO 引脚.
辅助利器
开发 gpio 应用离不开几个利器
1. 原理图
已经开放原理图下载, 下载地址: https://www.rvboards.org/forum/c ... es/1620265818082-d1
哪吒开发板原理图20210224.pdf
根据原理图,我们可以看到 40pin 引脚与之对应的芯片端口
这里要说明 D1 板子用 PCF8574 扩展了 8 个 IO 分别是 PP0-PP7 ,其他引出的 IO 来至 D1 这颗芯片, 并且由于 IO 端口不足, 40 Pin 里面物理 32pin 和 38pin 为未启用(NC), 树莓派中是两个 GPIO 端口
2. DEBUGFS
第二个利器就是 debugfs Wiki: Debugfs
debugfs 传承了 Linux 一切皆文件的理念,把内核更多信息通过文件系统展现给开发者,这里当然就包括了我们要的 gpio 信息
debugfs 默认挂载在 /sys/kernel/debug , 如果没有挂载,可以执行 mount -t debugfs none /sys/kernel/debug 挂载
在 /sys/kernel/debug 目录下有个 gpio 文件
- gpiochip0: GPIOs 0-223, parent: platform/2000000.pinctrl, 2000000.pinctrl:
- gpio-115 ( |usb1-vbus ) out lo
- gpio-116 ( |otg_det ) in lo
- gpio-117 ( |otg_id ) in hi
- gpio-144 ( |phy-rst ) out hi
- gpio-166 ( |cd ) in hi IRQ
- gpio-202 ( |wlan_hostwake ) in hi
- gpio-204 ( |wlan_regon ) out lo
- gpio-208 ( |bt_wake ) out lo
- gpio-209 ( |bt_hostwake ) in hi
- gpio-210 ( |bt_rst ) out lo
- gpiochip1: GPIOs 2020-2027, parent: i2c/2-0038, pcf8574, can sleep:
复制代码 里面内容显示了,板子上有两部分 gpio 组成,第一部分(gpiochip0)有 0-223 ,共224 个 gpio 端口,来自 D1 芯片, 第二部分(gpiochip1) 2020-2027 , 共8个 gpio 端口来自 PCF8574, 并且 8574 是通过 i2c 连接的 , 同时又显示了gpiochip0 中已经做了配置的 GPIO 接口
D1 芯片中的 gpio 信息可以在 /sys/kernel/debug/pinctrl/2000000.pinctrl/pins 找到编号和芯片引脚名称(PA1,PB2等)的对应关系
- registered pins: 88
- pin 32 (PB0)
- pin 33 (PB1)
- pin 34 (PB2)
- pin 35 (PB3)
- pin 36 (PB4)
- pin 37 (PB5)
- pin 38 (PB6)
- pin 39 (PB7)
- pin 40 (PB8)
- pin 41 (PB9)
- pin 42 (PB10)
- pin 43 (PB11)
- pin 44 (PB12)
- pin 64 (PC0)
- pin 65 (PC1)
- pin 66 (PC2)
- pin 67 (PC3)
- ...
复制代码
3. SYSFS
sysfs 和 debugfs 一样,通过文件系统,用户不仅可以查看信息,还可以操作硬件.
在 /sys/class/gpio 目录下有四个文件,分别是 export,gpiochip0 ,gpiochip2020,unexport
其中 gpiochip0,gpiochip2020 链接的是芯片两个gpio主控
export 和 unexport 用来控制 gpio 的开启与关闭
- # 启用 2020 号 gpio 端口, 根据上面的信息,可以知道 2020 对应扩展 IO PP0 , 也就是 40pin 引脚中的 GPIO8
- echo 2020 > export
- # 执行完 echo 2020 > export 后, 会在 /sys/class/gpio 中创建一个目录 /sys/class/gpio/gpio202 , 在这个目录里面就可以设置 gpio 的in 和 out 以及读取或者输出高低电平
- cd /sys/class/gpio/gpio2020
- # 设置为输出
- echo out > direction
- # 设置高电平
- echo 1 > value
- # 设置低电平
- echo 0 > value
- # 执行代码后, 如果接了 LED 灯, 灯就会亮了又灭了
复制代码
二、Rust 在 gpio 方面的支持情况
rust 有以下一些 crate
1. LINUX-EMBEDDED-HAL
Implementation of the embedded-hal traits for Linux devices
2. GPIO-CDEV
基于 GPIO character device ABI 的库
3. SYSFS-GPIO
基于 sysfs 操作 gpio 的库, 原理如上面手动操作 sysfs 是一样的
4. GPIO-UTILS
操作 gpio 的小工具程序, 基于 sysfs_gpio
Rust Demo (使用cdev-gpio)
list gpios
- extern crate gpio_cdev;
- use gpio_cdev::*;
- fn main() {
- let chip_iterator = match chips() {
- Ok(chips) => chips,
- Err(e) => {
- println!("Failed to get chip iterator: {:?}", e);
- return;
- }
- };
- for chip in chip_iterator {
- let chip = match chip {
- Ok(chip) => chip,
- Err(err) => panic!("Failed to open the chip: {:?}", err)
- };
- println!(
- "GPIO chip: {}, "{}", "{}", {} GPIO Lines",
- chip.path().to_string_lossy(),
- chip.name(),
- chip.label(),
- chip.num_lines()
- );
- for line in chip.lines() {
- match line.info() {
- Ok(info) => {
- let mut flags = vec![];
- if info.is_kernel() {
- flags.push("kernel");
- }
- if info.direction() == LineDirection::Out {
- flags.push("output");
- }
- if info.is_active_low() {
- flags.push("active-low");
- }
- if info.is_open_drain() {
- flags.push("open-drain");
- }
- if info.is_open_source() {
- flags.push("open-source");
- }
- let usage = if !flags.is_empty() {
- format!("[{}]", flags.join(" "))
- } else {
- "".to_owned()
- };
- println!(
- "\tline {lineno:>3}: {name} {consumer} {usage}",
- lineno = info.line().offset(),
- name = info.name().unwrap_or("unused"),
- consumer = info.consumer().unwrap_or("unused"),
- usage = usage,
- );
- }
- Err(e) => println!("\tError getting line info: {:?}", e),
- }
- }
- println!();
- }
- }
复制代码
cdev-gpio 的接口中, 通过 chips() 获取 gpio控制器列表, D1 中的/dev/gpiochip0 和 /dev/gpiochip1
每个 chip 中有 lines 列表,就是控制器下的 gpio 列表 line 就是 gpio 对象, 可以 进行 set_value , get_value ,以及设定输入输出等操作
总体来说, Linux 对 gpio 封装已经很简单, rust 在这方面支持也比较完善. 后续文章还有 i2c, spi , uart 等方面的操作,欢迎关注,欢迎拍砖。
完
|