ZYNQ linux开发 章节八 Petalinux 千兆以太网络功能的测试(Tiny ZYNQ版)

本文介绍在RTL8211千兆网络模块基础上实现Petalinux 下的网络访问功能

(针对网络扩展模块的看)

vivado 版本是2018.3版 ,其他版本请自行尝试

网络的vivado 工程和Tiny ZYNQ板 工程十七 千兆网络模块初测(基于PS EMIO)一致(额外需要在BLOCK DESIGN 中使能SD功能) 关于vivado部分选择性翻看。

ZYNQ 网络功能可以有4种方式实现

  • 一 PS端 MIO功能直接扩展以太网口
  • 二 PS端通过EMIO的方式将以太网口映射到PL端口上
  • 三 PL端口的硬件以太网功能 通过AXI的方式供PS端调用
  • 四 PL端用逻辑跑以太网功能(不需要PS端参与)

我们这里 因为网口接到了 PL端上,所以理论上 可以实现二 三 四, 第二种和第三种方式 其实效果差不多,只是方式三更占用逻辑资源,而方式四是 FPGA直接控制网络,所以为了方便测试我们先用方式三EMIO的方式来进行测试

PS本文仅适用于 Smart ZYNQ板, 如是Tiny ZYNQ的板子请看对应章节

关于设备树和 内核驱动部分 参考如下页面

https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842246/Xilinx+GMII2RGMII+converter

工程创建

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)选择芯片型号 我们板子上用的芯片是XC7Z010 ,并在列表栏中选择对应的封装型号,完整型号是XC7Z010CLG400-1 如下所示,选中后点NEXT

7)确认所选信息 点击“Finish”,完成vivado的工程创建

之后 工程就新建好了, vivado 进入到开发界面

Block Design 部分创建

此处需要创建一个ZYNQ CORE ,并在ZYNQ CORE中设置DDR 以及UART等参数

UART此处用 EMIO方式连接

1)创建一个BLOCK设计

2)搜索并添加ZYNQ7 Processing System,添加ZYNQ7 PROCESSING SYSTEM模块

软件自动生成了一个 zynq的block 如下图所示,接下来要做一些相应的设置,双击下图中的ZYNQ核

3) 依次在弹窗里找到DDR Configuration→DDR Controller Configuration→DDR3,在Memory Part下拉菜单中根据自己板子上的DDR来选择相应的DDR3,本实验所用到型号:MT41K128M16JT 125,数据位宽选择16bit 最后点击“OK”,如下图所示。

因为工程暂时用不到 AXI功能,所以可以先禁用AXI功能

4) 这里把ENET0通过EMIO引出来 ,并且选中MDIO功能

之后点选OK 来保存ZYNQ的配置

5)由于 ZYNQ的PS 调用EMIO方式 默认输出是GMII,而我们的网络转接卡上的芯片 RTL8211是 输出RGMII的,所以这里我们需要增加一个 GMII和RGMII转换的IP模块 (Gmii to Rgmii)

打开 GMII TO RGMII模块 设置更改成下面

6) 又因为GMII TO RGMII 是高电平复位 ,但是ZYNQ 是输出低电平复位的,所以这里需要增加一个反相器(搜索utility, 在检索出来的选项里 选择 utility vector logic)

在设置页里改成 not(反相器)将位宽改成1

7) 按下图方式连接好各个模块(复位 时钟 网络)

8)并通过右键 然后选择Make external 的方式引出RGMII 和MDIO_PHY功能引脚

9)由于我们的转接板上 网络部分的时钟25M单独有晶振控制了,所以这里不需要额外引出25M时钟

10)这里还要对Z7的模块进行一个修改,因为gmii to rgmii 模块的clkin 在手册上写要求是200mhz,所以我们这里需要对ZYNQ核的输出时钟频率进行修改

重新双击ZYNQ的核,将FCLK_CLK0的频率改成200

12)另外 因为 SDK中 网络功能的例程都需要UART功能来调试,所以这里额外在ZYNQ核心中增加串口功能(选择EMIO方式)

并且使能SD功能,用于linux 系统的TF卡启动用

同样通过右键 然后选择Make external 的方式引出UART功能引脚

13) 所有的都完成后点选 Run Block Automation,完成后续自动布线

14)创建硬件描述,source→Design Source ,右键我们创建的BLOCK工程,点击create HDL wrapper如下图所示(这一步的作用相当于将图纸转换成对应的硬件描述语言的功能)

15)编写好代码后 对代码进行编译

16)添加约束文件 对管脚 和 电平进行约束, 尤其要注意 最下面的时序约束部分 一定要添加,不然大概率无法ping通

备注1.0和1.1版本主板GPIO部分映射不同

如果是V1.0版的主板 时序约束如下

set_property PACKAGE_PIN J18 [get_ports {RGMII_0_td[1]}]
set_property PACKAGE_PIN G20 [get_ports RGMII_0_tx_ctl]
set_property PACKAGE_PIN G19 [get_ports {RGMII_0_td[3]}]
set_property PACKAGE_PIN K17 [get_ports {RGMII_0_td[0]}]
set_property PACKAGE_PIN G17 [get_ports {RGMII_0_rd[2]}]
set_property PACKAGE_PIN D19 [get_ports MDIO_PHY_0_mdio_io]
set_property PACKAGE_PIN B19 [get_ports MDIO_PHY_0_mdc]
set_property PACKAGE_PIN K16 [get_ports {RGMII_0_td[2]}]
set_property PACKAGE_PIN J16 [get_ports {RGMII_0_rd[3]}]
set_property PACKAGE_PIN H15 [get_ports {RGMII_0_rd[0]}]
set_property PACKAGE_PIN H18 [get_ports RGMII_0_txc]
set_property PACKAGE_PIN H16 [get_ports RGMII_0_rxc]
set_property PACKAGE_PIN E17 [get_ports RGMII_0_rx_ctl]
set_property PACKAGE_PIN F17 [get_ports {RGMII_0_rd[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_td[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports RGMII_0_tx_ctl]
set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_td[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_td[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_rd[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports MDIO_PHY_0_mdio_io]
set_property IOSTANDARD LVCMOS33 [get_ports MDIO_PHY_0_mdc]
set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_td[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_rd[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_rd[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports RGMII_0_txc]
set_property IOSTANDARD LVCMOS33 [get_ports RGMII_0_rxc]
set_property IOSTANDARD LVCMOS33 [get_ports RGMII_0_rx_ctl]
set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_rd[1]}]

set_property PACKAGE_PIN T12 [get_ports UART_0_0_rxd]
set_property IOSTANDARD LVCMOS33 [get_ports UART_0_0_txd]
set_property IOSTANDARD LVCMOS33 [get_ports UART_0_0_rxd]
set_property PACKAGE_PIN U13 [get_ports UART_0_0_txd]


create_clock -period 8.000 -name RGMII_0_rxc -waveform {0.000 4.000} [get_ports RGMII_0_rxc]
set_clock_groups -logically_exclusive -group [get_clocks -include_generated_clocks {gmii_clk_25m_out gmii_clk_2_5m_out}] -group [get_clocks -include_generated_clocks gmii_clk_125m_out]

set_property SLEW FAST [get_ports {RGMII_0_td[0]}]
set_property SLEW FAST [get_ports {RGMII_0_td[1]}]
set_property SLEW FAST [get_ports {RGMII_0_td[2]}]
set_property SLEW FAST [get_ports {RGMII_0_td[3]}]

如果是V1.1版的主板 时序约束如下

set_property PACKAGE_PIN J18 [get_ports {RGMII_0_td[1]}]
set_property PACKAGE_PIN G20 [get_ports RGMII_0_tx_ctl]
set_property PACKAGE_PIN G19 [get_ports {RGMII_0_td[3]}]
set_property PACKAGE_PIN K16 [get_ports {RGMII_0_td[0]}]
set_property PACKAGE_PIN G17 [get_ports {RGMII_0_rd[2]}]
set_property PACKAGE_PIN D19 [get_ports MDIO_PHY_0_mdio_io]
set_property PACKAGE_PIN B19 [get_ports MDIO_PHY_0_mdc]
set_property PACKAGE_PIN K18 [get_ports {RGMII_0_td[2]}]
set_property PACKAGE_PIN J16 [get_ports {RGMII_0_rd[3]}]
set_property PACKAGE_PIN H15 [get_ports {RGMII_0_rd[0]}]
set_property PACKAGE_PIN H18 [get_ports RGMII_0_txc]
set_property PACKAGE_PIN H16 [get_ports RGMII_0_rxc]
set_property PACKAGE_PIN E17 [get_ports RGMII_0_rx_ctl]
set_property PACKAGE_PIN F17 [get_ports {RGMII_0_rd[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_td[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports RGMII_0_tx_ctl]
set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_td[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_td[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_rd[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports MDIO_PHY_0_mdio_io]
set_property IOSTANDARD LVCMOS33 [get_ports MDIO_PHY_0_mdc]
set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_td[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_rd[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_rd[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports RGMII_0_txc]
set_property IOSTANDARD LVCMOS33 [get_ports RGMII_0_rxc]
set_property IOSTANDARD LVCMOS33 [get_ports RGMII_0_rx_ctl]
set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_rd[1]}]

set_property PACKAGE_PIN T12 [get_ports UART_0_0_rxd]
set_property IOSTANDARD LVCMOS33 [get_ports UART_0_0_txd]
set_property IOSTANDARD LVCMOS33 [get_ports UART_0_0_rxd]
set_property PACKAGE_PIN U13 [get_ports UART_0_0_txd]


create_clock -period 8.000 -name RGMII_0_rxc -waveform {0.000 4.000} [get_ports RGMII_0_rxc]
set_clock_groups -logically_exclusive -group [get_clocks -include_generated_clocks {gmii_clk_25m_out gmii_clk_2_5m_out}] -group [get_clocks -include_generated_clocks gmii_clk_125m_out]

set_property SLEW FAST [get_ports {RGMII_0_td[0]}]
set_property SLEW FAST [get_ports {RGMII_0_td[1]}]
set_property SLEW FAST [get_ports {RGMII_0_td[2]}]
set_property SLEW FAST [get_ports {RGMII_0_td[3]}]

17. 修改之后 点击 Generate Bitstream 进行综合以及生成Bit 文件

等待布线综合完成

11)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_Net_TEST的工程

petalinux-create --type project --template zynq --name Petalinux_Net_TEST

按下回车后 名为Petalinux_Net_TEST的工程会被创建,并且刚才的文件夹下多了一个对应的工程文件夹

为了方便以后的工程管理,我们将刚才生成的system.hdf 也拖到Petalinux_Net_TEST文件夹中

4) 复制hdf文件到刚才创建的工程文件夹中

在图形界面下双击打开这个Petalinux 文件夹

打开刚才SDK的软件界面, 右键hdf文件,选择copy 复制

然后在图形界面打开 Ubuntu 的Petalinux 文件夹下的Petalinux_Net_TEST文件夹内, 右键空白处 点选Paste (粘贴)

5)设置路径并启动Petalinux 配置页

在刚才的界面下先CD进入 工程文件夹(Petalinux_GPIO_TEST) 备注(CD 的时候 可以输入文件夹的第一个字母然后按tab键,这样相同名称的文件夹就会跳出来)

cd Petalinux_Net_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 也进行设置 ,Subsystem AUTO Hardware Settings 按下回车

选择Advanced bootable images storage Settings ,按下回车

之后用多次双击ESC的方式回到初始菜单

c) root 文件系统 类型选择

选择Image Packaging Configuration

选择 Root filesystem type

选择 INITRAMFS(这里不要因为是TF启动就选择SD CARD,否则需要构建根文件系统,这个有时间后面章节再写)

之后按多次ESC回到根菜单

d)设置加载位置,因为板子上的DDR是256MB 的,而默认的加载位置已经超过256M的边界了,所以这里需要调整加载位置

选择u-boot Configuration

选择 netboot offset 选项 按回车

修改为 0x08000000 按OK 确认 (0x08000000可以修改为其他值,它影响uboot中kernel的加载位置,以不会超区同时不会覆盖其他文件数据为准)

之后按多次ESC回到根菜单

e) 设置网络部分功能

选择Subsystem AUTO Hardware Settings 按下回车

选择Ethernet Settings

进入 Ethernet Settings后我们可以在这里设置 网络设备的MAC 地址,当然一般情况下MAC地址保留默认即可, 我们接下来 点选Primary Ethernet(ps7_ethernet_0) 按下回车

选择 ps7_ethernet_0即可(如果其他板子的工程用AXI创建的网络,这里会有不同的选择)

之后按多次ESC回到根菜单

f)保存设置 选择save 并点选ok 对设置进行保存

退出 设置界面

主菜单选择EXIT 退出

之后 系统进行配置 ,此时等待配置结束

配置Kernel 增加 GMII 2 RGMII驱动

g) 输入以下命令 对内核进行配置(因为我们使用了GMII TO RGMII模块,所以需要增加XILINX_GMII2RGMII驱动 ,这一步必须要调整)

petalinux-config -c kernel

按向下箭头选择 Device Driver,并按下回车

选择 Network device support,按下回车

选择 PHY Device support and infrastructure 并按下回车

拖到最最下方,在xilinx GMII2RGMII converter driver 的驱动选项点下键盘上的Y键 (选项前会多出一个“ * ”代表选中了)

之后用鼠标右键选择save 保存

弹出来的菜单 直接选ok,并在之后出现的选项里点exit

之后一多次按ESC键返回主菜单,然后按EXIT 退出kernel 设置

设备树的创建(不需要做,直接下一步)

网上大部分资料在这里 都提示需要创建设备树,但是其实按照之前的操作完成后,系统会自动帮我们在设备树里添加网络,而不需要手动添加(在没有编译前看不到设备树,这里我们先略过设备树的创建)

接下来 编译整个工程

petalinux-build

之后又是漫长的等待

直接到出现提示 successfully built project 代表编译完成了

关于网络部分的设备树

之后再去工程文件夹下可以看到系统自动为我们增加了网络的设备树部分:

在目录 /Petalinux_Net_TEST/components/plnx_workspace/device-tree/device-tree下的pcw.dtsi文件中

打开后可以看到 网络部分的设备树内容(这也就是前面我没有添加设备树的原因)

打包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 ) 或者临时挂起虚拟机

因为本工程需要用到ctrl+c来中断应用,所以这里用putty这样的专业工具替代串口助手(这样诸如CTRL+C这样的指令就可以用键盘的形式直接发送了,putty官网可以免费下载到)

打开后配置界面如下 模式选择serial ,并设置好串口号(查看设备管理器得到) 和波特率115200就行

设置成SD启动后重新上电,我们就能在putty上看到linux 发出来的命令行了

系统此时停留在等待输入账号密码的状态, 此时输入用户名 root 输入密码 root (不同的串口助手有些需要带回车)

之后就正式登录 petalinux 了

此时插入网线到我们的主板,并且另一头连接路由器

可以看到 系统提示 Link up (1000/Full) 代表网络已成功link 上1G 网络了(PS 此处系统提示unable to generate target frequency: 125000000 hz 是因为我们输入到PS的33.33m无法通过倍频实现非常精准的125Mhz的频率,超出了50ppm,所以系统产生的警告,这个是正常的直接忽略就好,对系统通讯并不影响

可以通过ifconfig命令来查看IP地址,MAC地址,网关等信息

尝试ping路由器网关 192.168.1.1,可以通过命令行看到ping成功了

如果路由器连接外网的话,还可以尝试ping 外网看看

以下是 VIVADO 的工程 (里面的image文件夹 里面是 Ubuntu 下编译的镜像文件,将image 文件夹里的镜像复制到fat32的TF卡也能看效果) 备注1.0和1.1版本主板GPIO部分映射不同

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注