Ultra96 PYNQ入门之一——PS端控制MIO与EMIO


不合理的地方欢迎批评指正!!!

源代码链接:Ultra96-PYNQ_A-simple-summary

1 PYNQ GPIO模块

注:这部分是进行简单分析相应的重要函数,如嫌啰嗦,可以直接转到2小节。

本小节与Ultra96-V2板卡的PL部分无关,直接使用PS控制GPIO作为示例
进行下面之前,需要导入GPIO模块

from pynq import GPIO

1.1 get_gpio_base

获取gpio号的基地址,PYNQ的源代码是使用Linux’s GPIO Sysfs API来获取对应的基地址的。

gpio_base = GPIO.get_gpio_base()
print("Ultra96-V2 gpio_base is {}".format(gpio_base))

下面是对应的Linux Sysfs部分

xilinx@pynq:~$ cd /sys/class/gpio/
xilinx@pynq:/sys/class/gpio$ tree
.
├── export
├── gpiochip338 -> ../../devices/platform/amba/ff0a0000.gpio/gpio/gpiochip338
└── unexport

1.2 get_gpio_base_path

获取gpio设备在Linux Sysfs的路径

gpio_base_path = GPIO.get_gpio_base_path()
print("Ultra96-V2 gpio_base_path is {}".format(gpio_base_path))

1.3 get_gpio_npins

获取这个gpio控制器,最多可控制多少个引脚

gpio_npins = GPIO.get_gpio_npins()
print("Ultra96-V2 gpio_npins is {}".format(gpio_npins))

Ultra96-V2 gpio_npins is 174

从数据手册可以获取这个数值的含义,相信你只要上过小学,就可以知道这个174是MIO+EMIO的数量
在这里插入图片描述

1.4 get_gpio_pin

这个可以获取Linux Sysfs GPIO的引脚号,可用于后续的初始化。

def get_gpio_pin(gpio_user_index, target_label=None):
	if target_label is not None:
	    GPIO_OFFSET = 0
	else:
	    GPIO_OFFSET = GPIO._GPIO_MIN_USER_PIN
	
	return (GPIO.get_gpio_base(target_label) + GPIO_OFFSET +
	        gpio_user_index)

通过源码可知如使用MIO部分的GPIO,则不建议使用此API。

1.5 init

初始化部分必须慎重对待。区分开MIO与EMIO,EMIO在MIO之外加上相应的偏移。

def __init__(self, gpio_index, direction):
    """Return a new GPIO object.

    Parameters
    ----------
    gpio_index : int
        The index of the GPIO using Linux's GPIO Sysfs API.
    direction : 'str'
        Input/output direction of the GPIO.

    """

1.5.1 PS MIO

gpio_index = GPIO.get_gpio_base() + MIO编号

1.5.2 PS EMIO

gpio_index = GPIO.get_gpio_base() + GPIO.get_gpio_pin(gpio_user_index = EMIO编号)

1.6 其他

这部分API不用多说,很简单明了。

  1. read(self)
  2. write(self, value)
  3. release(self)

2 PS MIO的使用

2.1 尝试控制LED?

经过上面的讲解,假设你看中了Ultra96-V2的一个PS MIO连接的LED,想要试验一下,控制这个LED,找点成就感,在此我遗憾的告诉你,你将碰一鼻子灰…。

在这里插入图片描述
如果执行如下操作

led1 = GPIO(gpio_base + 19, 'out')

则会出现设备资源繁忙,无法访问的错误,如下所示

OSError                                   Traceback (most recent call last)
OSError: [Errno 16] Device or resource busy

During handling of the above exception, another exception occurred:

OSError                                   Traceback (most recent call last)
<ipython-input-5-22b01faa7ec5> in <module>()
----> 1 led1 = GPIO(gpio_base + 19, 'out')

/usr/local/lib/python3.6/dist-packages/pynq/gpio.py in __init__(self, gpio_index, direction)
    192 
    193         if not self._impl or not self._impl.is_exported():
--> 194             self._impl = _GPIO(gpio_index, direction)
    195             _gpio_map[gpio_index] = self._impl
    196 

/usr/local/lib/python3.6/dist-packages/pynq/gpio.py in __init__(self, gpio_index, direction)
     77         if not os.path.exists(self.path):
     78             with open('/sys/class/gpio/export', 'w') as f:
---> 79                 f.write(str(self.index))
     80 
     81         with open(self.path + 'direction', 'w') as f:

OSError: [Errno 16] Device or resource busy

根本原因是,Ultra96-V2的PYNQ镜像,已经在设备树中将该GPIO资源分配给LED了,如果再通过GPIO模块对该资源进行访问,则肯定会出现设备资源繁忙错误报告。

Ultra96-V2的设备树中的LED如下所示

xilinx@pynq:/sys/class/gpio$ cd /sys/class/leds/
xilinx@pynq:/sys/class/leds$ tree
.
├── ds2 -> ../../devices/platform/leds/leds/ds2
├── ds3 -> ../../devices/platform/leds/leds/ds3
├── ds4 -> ../../devices/platform/leds/leds/ds4
├── ds5 -> ../../devices/platform/leds/leds/ds5
├── mmc0:: -> ../../devices/platform/amba/ff160000.mmc/leds/mmc0::
├── mmc1:: -> ../../devices/platform/amba/ff170000.mmc/leds/mmc1::
└── vbus_det -> ../../devices/platform/leds/leds/vbus_det

7 directories, 0 files

进入相应目录,可以使用root写入brightness来控制相应LED的亮灭。具体如何通过Python来控制这些,会在文章最后进行简单提及的。

xilinx@pynq:/sys/class/leds/ds3$ cat brightness
0
xilinx@pynq:/sys/class/leds/ds3$ su
Password:
root@pynq:/sys/class/leds/ds3# tree
.
├── brightness
├── device -> ../../../leds
├── max_brightness
├── power
│   ├── autosuspend_delay_ms
│   ├── control
│   ├── runtime_active_time
│   ├── runtime_status
│   └── runtime_suspended_time
├── subsystem -> ../../../../../class/leds
├── trigger
└── uevent

3 directories, 9 files
root@pynq:/sys/class/leds/ds3# echo 1 > brightness
root@pynq:/sys/class/leds/ds3# cat brightness
1
root@pynq:/sys/class/leds/ds3#

2.2 控制GPIO

既然LED设备资源无法访问,访问那些没有在设备树分配相应功能的GPIO资源了。
在这里插入图片描述
这里仅使用MIO36_PS_GPIO1_0输出示例使用方法。
如果尝试输入实验,一定要注意电平标准(MIO 1.8V!!!),不要一不小心,把2K多的板子给烧了…。
如果尝试输入实验,一定要注意电平标准(MIO 1.8V!!!),不要一不小心,把2K多的板子给烧了…。
如果尝试输入实验,一定要注意电平标准(MIO 1.8V!!!),不要一不小心,把2K多的板子给烧了…。

一般的口袋仪器的数字部分电平是LVCMOS 3.3V的,这时候可以考虑使用口袋仪器的信号发生器来构造1.8V的脉冲信号,来进行测试。输入部分没事,1.8V勉强可以触发3.3V,至少烧不坏。

完整测试代码

from pynq import GPIO
import time

gpio_base = GPIO.get_gpio_base()
print("Ultra96-V2 gpio_base is {}".format(gpio_base))
gpio0 = GPIO(gpio_base + 36, 'out')

for i in range(100):
    gpio0.write(1)
    time.sleep(0.1)
    gpio0.write(0)
    time.sleep(0.1)

逻辑分析仪的测量结果如下,符合软件设置的间隔。
在这里插入图片描述
输入实验,与输出实验类似,唯一要注意的是不要使用不兼容的电压标准。

2.3 一个小彩蛋

上面使用gpio0 = GPIO(gpio_base + 36, 'out')对一个MIO部分的GPIO资源进行实例化,这时候可以在Linux Sysfs部分惊奇的发现

root@pynq:/sys/class/leds/ds3# cd /sys/class/gpio/
root@pynq:/sys/class/gpio# tree
.
├── export
├── gpio374 -> ../../devices/platform/amba/ff0a0000.gpio/gpiochip0/gpio/gpio374
├── gpiochip338 -> ../../devices/platform/amba/ff0a0000.gpio/gpio/gpiochip338
└── unexport

2 directories, 2 files

进入相应的目录,可以与LED类似,直接写入相应的值进行控制。 PYNQ的GPIO模块原理就是使用Linux’s GPIO Sysfs API来进行控制GPIO的,使用Python进行进一步封装,减少开发难度。

3 PS EMIO的使用

3.1 硬件设计

这部分需要加载相应的bit流文件,进行使用。

这里我拿这6个小家伙作为EMIO示例,约束为可以输入可以输出,具体如何使用,需要软件进一步配置
在这里插入图片描述

很简单的一个设计,可以在Vivado中的TCL控制台通过如下命令,进行快速重建

source 1.ps_emio.tcl

在这里插入图片描述
如果打开实现后的器件视图,可以发现PS的EMIO正确的连接到相应的引脚上了
在这里插入图片描述

3.2 控制GPIO

使用类似的代码,即可进行验证

from pynq import GPIO
from pynq import Overlay
import time

emio_gpio_design = Overlay("./data/1.PS_EMIO.bit")
hd_emio_gpio0_n = GPIO.get_gpio_pin(gpio_user_index= 0)
print("Ultra96-V2 hd_emio_gpio0 numbers is {}".format(hd_emio_gpio0))
hd_emio_gpio0 = GPIO(hd_emio_gpio0_n, 'out')

for i in range(100):
    hd_emio_gpio0.write(1)
    time.sleep(0.1)
    hd_emio_gpio0.write(0)
    time.sleep(0.1)

逻辑分析仪的测量结果如下,符合软件设置的间隔。
在这里插入图片描述
EMIO与MIO类似,可以在sysfs中查询得到,同样可以进行控制

root@pynq:/sys/class/gpio# tree
.
├── export
├── gpio416 -> ../../devices/platform/amba/ff0a0000.gpio/gpiochip0/gpio/gpio416
├── gpiochip338 -> ../../devices/platform/amba/ff0a0000.gpio/gpio/gpiochip338
└── unexport

4 控制设备树中的LED

A pure Python 2/3 library for peripheral I/O (GPIO, LED, PWM, SPI, I2C, MMIO, Serial) in Linux.
这里仅放相应的Github链接,并不进行演示,具体可在链接中查询。

注:控制设备树中的常用外设,与FPGA部分无关,这时候Ultra96-V2与树莓派之类的板卡类似。



原创不易,严禁剽窃!

在这里插入图片描述

欢迎大家关注我创建的微信公众号——小白仓库
原创经验资料分享:包含但不仅限于FPGA、ARM、RISC-V、Linux、LabVIEW等软硬件开发,另外分享生活中的趣事以及感悟。目的是建立一个平台记录学习过的知识,并分享出来自认为有用的与感兴趣的道友相互交流进步。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值