本文将在petalinux下完成 GPIO的输入输出功能。其中输出功能将用LED灯来演示,输入功能用板子上的按键来演示
vivado 版本是2018.3版 ,其他版本请自行尝试
(备注 此章节内容适用于 Smart ZYNQ SP和SL 版的板子,如果是Smart ZYNQ 标准版请看对应板子目录)
Vivado 部分的工程创建(Vivado 创建过程和之前的工程有部分雷同,可以选择性对的跳看)
1)打开Vivado 新建一个项目, 新建一个VIVADO 工程,打开软件 选中Create Project, 如下图所示
2)点击NEXT ,在出现的第二个对话框“Project name”中输入工程名;在“Project location”中选择保存路径;勾选“Create project subdirectory”(默认),最后点击“Next” 备注,所有的路径均不能出现中文名称
3)点击 RTL PROJECT 选项,点击NEXT
4) 第四步Add Sources 选项直接留空,NEXT
5)第五步Add Constraints 选项直接留空,NEXT
6)选择芯片型号 XC7Z020CLG484-1
7)确认所选信息 点击“Finish”,完成vivado的工程创建
之后 工程就新建好了, vivado 进入到开发界面
Block Design 部分创建
此处需要创建一个ZYNQ CORE ,并在ZYNQ CORE中设置DDR 以及UART等参数
UART此处用 EMIO方式连接(Tiny FPGA 以及 EBAZ4205转接板都用EMIO的方式连接)
1)创建一个BLOCK设计
2)搜索并添加ZYNQ7 Processing System,添加ZYNQ7 PROCESSING SYSTEM模块
3)软件自动生成了一个 zynq的block 如下图所示,接下来要做一些相应的设置,双击下图中的ZYNQ核
4)在zynq中设置DDR功能:
依次在弹窗里找到DDR Configuration→DDR Controller Configuration→DDR3,在Memory Part下拉菜单中根据自己板子上的DDR来选择相应的DDR3,本实验所用到型号:MT41K256M16RE-125,数据位宽选择16bit 最后点击“OK”,如下图所示。
5) linux 需要通过串口来进行命令行的输入输出,所以这里额外在ZYNQ核心中增加串口功能(选择EMIO方式)
由原理图可知, 主板的UART功能接在 ZYNQ PL端的 L17脚和M17脚了,即 ZYNQ的TX是 连接L17,ZYNQ的RX是连接M17 (备注 V1.0板子上的丝印 TX 和 RX标反了,以原理图为准)
使能UART 0 并在IO选项里选择EMIO方式
6). 在block design 的设置界面 使能SD的功能
增加4路GPIO (EMIO方式),其中两路用来点亮LED灯,两路用来读入按键的值
7)随后点OK 保存修改, 点击“Run Block Automation”如下图所示。在弹出的选项中保持默认,点击“OK”,即可完成对ZYNQ7 Processing System的配置
8)用鼠标连接FCLK_CLK和 M_AXI_GP0_ACLK,得到下图
9)右键GPIO_0选择Make External
10) 引出UART 信号,右键选择ZYNQ模块的UART_0,然后选择Make External
11)source→Design Source ,右键我们创建的BLOCK工程,点击create HDL wrapper,打包BLOCK文件并生成.v代码
12) 点击绿色箭头RUN 对代码进行编译
13) 完成后点击RTL 中的SCHEMATIC , 并选择右边出现的 IO Ports 来增加UART 0 EMIO部分的管脚定义(这一步也可以在约束文件中定义, 可看之前的例子)
将4个EMIO的GPIO 分别接P20 P21 K21 J20分别对应两个LED灯和两个按键,UART 的TX设置L17 和 RX设置 M17 之后保存(保存的时候会让你给约束文件命名,自行定义就好)
14) 生成bit文件 :按下Generate Bitstream 完成综合以及生成bit文件,等待弹出综合完成的窗口
15)File→Export→Export hardware…在弹出的对话框中勾选“include bitstream”,点击“OK”确认,如下图所示。
12)File→Lauch SDK,在弹出的对话框中,保存默认,点击“OK”,如下图所示。
系统将自动打开SDK开发环境
其中SDK工程下的 下图hdf文件就是我们需要的系统硬件描述文件,这个需要交给petalinux 进行交叉编译用。
PetaLinux 工程创建
1)打开虚拟机下的 Ubuntu系统,打开命令行
输入 source /opt/pkg/petalinux/2018.3/settings.sh 对Petalinux 的环境进行加载
source /opt/pkg/petalinux/2018.3/settings.sh
2)在Ubuntu下创建工程目录(这里用图形界面的方式,当然也可以用mkdir的方式)
在home文件夹下 创建一个Petalinux文件夹(前两个章节已经创建了),可以图形界面打开Home 文件夹然后直接右键新建一个Petalinux
3) 创建Petalinux 工程
在工程文件夹的空白处 右键,然后点选Open in Terminal 打开终端命令行(这种方式打开命令行会自动定位到当前文件夹),当然也可以普通方式打开终端 ,再用CD的方式定位到此文件夹
(备注 如果用此方法,必须重新在这个新打开的命令行中对petalinux 开发环境进行预加载,否则后面会失败,每次打开新的命令行都需要执行这个命令)
source /opt/pkg/petalinux/2018.3/settings.sh
在命令行输入,来创建一个Petalinux_GPIO_TEST的工程
petalinux-create --type project --template zynq --name Petalinux_GPIO_TEST
按下回车后 名为Petalinux_GPIO_TEST的工程会被创建,并且刚才的文件夹下多了一个对应的工程文件夹
为了方便以后的工程管理,我们将刚才生成的system.hdf 也拖到Petalinux_GPIO_TEST文件夹中
4) 复制hdf文件到刚才创建的工程文件夹中
在图形界面下双击打开这个Petalinux 文件夹
打开刚才SDK的软件界面, 右键hdf文件,选择copy 复制
然后在图形界面打开 Ubuntu 的Petalinux 文件夹下的Petalinux_GPIO_TEST文件夹内, 右键空白处 点选Paste (粘贴)
5)设置路径并启动Petalinux 配置页
在刚才的界面下先CD进入 工程文件夹(Petalinux_GPIO_TEST) 备注(CD 的时候 可以输入文件夹的第一个字母然后按tab键,这样相同名称的文件夹就会跳出来)
cd Petalinux_GPIO_TEST
进入文件夹后,按下下列代码, 指定导入hdf的路径(因为是当前命令行的路径所以这里 带一个”.”就可以了,不然=号后跟具体路径) 并按下回车
petalinux-config --get-hw-description=.
之后系统将启动配置页
6) 对Petalinux 进行配置 (大量内容和之前章节四重复,可选择看)
a) 修改启动项
用键盘上的上下左右键移动光标,选择Subsystem AUTO Hardware Settings 按下回车(按两下ESC可以退回上一层)
选择Advanced bootable images storage Settings ,按下回车
选择 boot image settings选项 回车
选择 image storage media 回车
选择 primary sd并按回车(如果你在vivado 里设置了nand flash 等,这里就有多个选项可选了)
之后连按两次ESC 可以返回上一级, 一直返回,直到回到最初的初始界面
b )同理 对kernel image settings 也进行设置 ,ubsystem AUTO Hardware Settings 按下回车
选择Advanced bootable images storage Settings ,按下回车
之后用多次双击ESC的方式回到初始菜单
c) root 文件系统 类型选择
选择Image Packaging Configuration
选择 Root filesystem type
选择 INITRAMFS(这里不要因为是TF启动就选择SD CARD,否则需要构建根文件系统,这个有时间后面章节再写)
之后按多次ESC回到根菜单
d)因为板子上的DDR是512MB 的,所以这里不需要像Tiny ZYNQ板那样调整net boot offset加载位置
e)保存设置 选择save 并点选ok 对设置进行保存
f )退出 设置界面
主菜单选择EXIT 退出
之后 系统进行配置 ,此时等待配置结束
g) 等待配置结束后 输入以下命令 对内核进行配置(这一步不操作 没影响)
petalinux-config -c kernel
之后又是漫长的等待
之后弹出了 KERNEL 的配置界面,这里我们不需要任何修改默认即可,直接保存
退出
h) 编译整个工程
petalinux-build
之后又是漫长的等待
直接到出现提示 successfully built project 代表编译完成了
I) 打包boot.bin
编译完成后,项目工程文件夹下会有image文件夹,执行petalinux -package 命令 将zynq_fsbl.elf, system_wrapper.bit,u-boot.elf,image.ub 四个文件打包生成
BOOT.bin 文件
petalinux-package --boot --fsbl ./images/linux/zynq_fsbl.elf --u-boot --fpga --kernel --force
如下图所示,代表打包完成(有警告,直接忽略)
TF启动测试
在Ubuntu 系统内 打开 工程文件夹内 编译生成的image文件夹
再打开linux 文件夹
复制这2个文件 BOOT.bin、image.ub
然后回到windows 下,粘贴到格式为FAT32的 TF卡的根目录
之后正常退出TF卡, 并将卡插入到 我们的主板上
上电测试
将跳线位置换回到SD上
备注 实际测试过程中会发现 虚拟机 和windows 争抢串口的资源的情况,导致windows 下 无法访问串口,所以这里测试的时候(把串口默认设置连接到windows ) 或者临时挂起虚拟机
设置成SD启动后重新上电后,打开串口助手,波特率设置成115200 ,之后我们就能看到linux 发出来的命令行了(这里也可以用 SDK 自带的Terminal 功能,如下图打开,串口号根据实际的选择,备注:部分JTAG下载器带串口功能,选择串口根据实际用的哪路串口去选择
系统此时停留在等待输入账号密码的状态, 此时输入用户名 root 输入密码 root (不同的串口助手有些需要带回车)
之后就正式登录 petalinux 了
之后就可以进行linux 的操作了
GPIO功能验证一 点亮LED
我们这里直接用最最原始的方式来驱动GPIO(sysfs方式) 首先我们尝试点亮LED灯
对GPIO的操作主要分三步:
①导入IO到用户空间:/sys/class/gpio/export echo 960 > export ②配置IO:/sys/class/gpio/direction echo out > direction # 输出 echo in > direction # 输入 ③控制IO:/sys/class/gpio/value echo 1 > value #输出高电平 echo 0 > value #输出低电平
按照这个思路我们来实际操作一下
a)进入 /sys/class/gpio/ 目录
cd /sys/class/gpio/
b) 查看 文件夹下的内容
ls
c)由下图可以知道系统已经识别出一个GPIO设备 gpiochip906了
gpiochip906的起始编号是 906 ,因为我们的板子上LED灯被配置到EMIO的0 和EMIO 1上了,而emio0 和emio1分别对应54和55(编号0-53属于MIO),相当于对应linux 系统的 gpio960(906+54)和gpio961(906+55)
备注 有时候gpiochip并不是906 也可能是shu905 904, 这样对应的gpio 数就要加上对应的数
d) 输入下列指令输将EMIO0 节点(即LED灯)导入用户空间
echo 960 > /sys/class/gpio/export
e) 接下来我们尝试点亮LED灯,我们需要的操作是将输入输出改成为输出模式, 并且将LED灯对应的EMIO0 (GPIO960)设置为高电平
下列指令将GPIO960设置为输出
echo out > gpio960/direction
输入下列指令将GPIO960设置为高电平
echo 1 > gpio960/value
此时LED灯被正常点亮了, 想要关闭LED灯,可以把 gpio960/value 设置为0
echo 0 > gpio960/value
此时LED灯被熄灭
GPIO功能验证二 按键读取
接下来我们来尝试读取按键的值
gpiochip906的起始编号是 906 ,因为我们的板子上KEY被配置到EMIO的2 和EMIO 3上了,而emio0 和emio1分别对应56和57(编号0-53属于MIO),相当于对应linux 系统的 gpio962(906+56)和gpio963(906+57),根据之前设置 KEY1对应的是gpio963
备注 有时候gpiochip并不是906 也可能是shu905 904, 这样对应的gpio 数就要加上对应的数,查看gpiochip 的方法是 进入/sys/class/gpio/目录后,用ls命令查看设备
a)进入 /sys/class/gpio/ 目录
cd /sys/class/gpio/
b) 输入下列指令输将EMIO2 节点(即KEY1)导入用户空间
echo 963 > /sys/class/gpio/export
c) 我们也可以通过下列命令查看当前的输入输出状态
cat gpio963/direction
可以看到这里 GPIO962默认就是输入状态了
d) 如果输入输出状态是out ,那我们这里需要用下列命令将模式修改成in
echo in > gpio963/direction
e )之后我们通过下列指令来查看当前的按键值(输入指令前,我们需要提前按下或者松开按键)
cat gpio963/value
如下图所示,当KEY1 (即EMIO3 GPIO963) 按下时,返回的value值是0, 当KEY1 松开时返回值是1
以上是petalinux 的GPIO 输入输出测试的完整流程。 后续有时间 将尝试设备树和驱动等方式来调用GPIO
以下是 VIVADO 的工程 (里面的image文件夹 里面是 Ubuntu 下编译的镜像文件,将image 文件夹里的镜像复制到fat32的TF卡也能看效果),因为ubuntu下工程比较庞大,无法上传,所以大家按照上面描述的内容自行创建
备注 一般linux 的命令行远程调试习惯上用 putty这样的专业工具替代串口助手(这样诸如CTRL+C这样的指令就可以用键盘的形式直接发送了,putty官网可以免费下载到)
打开后配置界面如下 模式选择serial ,并设置好串口号(查看设备管理器得到) 和波特率115200就行
另外 关于 sysfs:sysfs(虚拟文件系统),sysfs的作用是将注册进系统中的设备、总线和驱动组织成一个个分级的文件,并直观地将驱动和设备的层次结构以文件的形式展示在用户空间,通过操作这些文件,系统向用户空间导出内核数据结构以及他们的属性,这样一来用户空间可以通过修改sysfs的文件属性来修改设备的属性值,进而改变设备的工作状态
以下是 VIVADO 的工程 (里面的image文件夹 里面是 Ubuntu 下编译的镜像文件,将image 文件夹里的镜像复制到fat32的TF卡也能看效果)