本文介绍在RTL8211千兆网络模块基础上实现Petalinux 下的网络访问功能
vivado 版本是2018.3版 ,其他版本请自行尝试
(备注 此章节内容适用于 Smart ZYNQ SP和SL 版的板子,如果是Smart ZYNQ 标准版请看对应板子目录)
网络的vivado 工程和 Smart ZYNQ(SP&SL 版) 工程十七 千兆网络模块初测(基于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)选择芯片型号 XC7Z020CLG484-1
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,本实验所用到型号:MT41K256M16RE-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)添加UART功能(用于Petalinux 的命令行输出)
由原理图可知, 主板的UART功能接在 ZYNQ PL端的 L17脚和M17脚了,即 ZYNQ的TX是 连接L17,ZYNQ的RX是连接M17 (备注 V1.0板子上的丝印 TX 和 RX标反了,以原理图为准)
使能UART 0 并在IO选项里选择EMIO方式
13)添加使能SD功能,用于linux 系统的TF卡启动用
14) 所有的都完成后点选 Run Block Automation,完成后续自动布线
15)引出UART 信号,因为我们增加了EMIO 的UART,所以这里需要将UART的引脚引出 ,右键选择ZYNQ模块的UART_0,然后选择Make External
16)创建硬件描述,source→Design Source ,右键我们创建的BLOCK工程,点击create HDL wrapper如下图所示(这一步的作用相当于将图纸转换成对应的硬件描述语言的功能)
17)编写好代码后 对代码进行编译
18)添加约束文件 对管脚 和 电平进行约束, 尤其要注意 最下面的时序约束部分 一定要添加,不然大概率无法ping通
set_property PACKAGE_PIN G21 [get_ports MDIO_PHY_0_mdc] set_property PACKAGE_PIN H22 [get_ports MDIO_PHY_0_mdio_io] set_property PACKAGE_PIN A22 [get_ports {RGMII_0_rd[0]}] set_property PACKAGE_PIN A18 [get_ports {RGMII_0_rd[1]}] set_property PACKAGE_PIN A19 [get_ports {RGMII_0_rd[2]}] set_property PACKAGE_PIN B20 [get_ports {RGMII_0_rd[3]}] set_property PACKAGE_PIN A21 [get_ports RGMII_0_rx_ctl] set_property PACKAGE_PIN B19 [get_ports RGMII_0_rxc] set_property PACKAGE_PIN E21 [get_ports {RGMII_0_td[0]}] set_property PACKAGE_PIN F21 [get_ports {RGMII_0_td[1]}] set_property PACKAGE_PIN F22 [get_ports {RGMII_0_td[2]}] set_property PACKAGE_PIN G20 [get_ports {RGMII_0_td[3]}] set_property PACKAGE_PIN G22 [get_ports RGMII_0_tx_ctl] set_property PACKAGE_PIN D21 [get_ports RGMII_0_txc] set_property PACKAGE_PIN M17 [get_ports UART_0_0_rxd] set_property PACKAGE_PIN L17 [get_ports UART_0_0_txd] set_property IOSTANDARD LVCMOS33 [get_ports MDIO_PHY_0_mdc] set_property IOSTANDARD LVCMOS33 [get_ports MDIO_PHY_0_mdio_io] set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_rd[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_rd[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_rd[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_rd[3]}] set_property IOSTANDARD LVCMOS33 [get_ports RGMII_0_rx_ctl] set_property IOSTANDARD LVCMOS33 [get_ports RGMII_0_rxc] set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_td[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_td[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_td[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_td[3]}] set_property IOSTANDARD LVCMOS33 [get_ports RGMII_0_tx_ctl] set_property IOSTANDARD LVCMOS33 [get_ports RGMII_0_txc] set_property IOSTANDARD LVCMOS33 [get_ports UART_0_0_rxd] set_property IOSTANDARD LVCMOS33 [get_ports UART_0_0_txd] 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]}] set_property SLEW FAST [get_ports RGMII_0_tx_ctl] set_property SLEW FAST [get_ports RGMII_0_txc] 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]
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是512MB 的,所以这里不需要像Tiny ZYNQ板那样调整net boot offset加载位置
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,所以系统产生的警告,这个是正常的直接忽略就好,对系统通讯并不影响)
尝试ping路由器网关 192.168.1.1,可以通过命令行看到ping成功了
如果路由器连接外网的话,还可以尝试ping 外网看看
以下是 VIVADO 的工程 (里面的image文件夹 里面是 Ubuntu 下编译的镜像文件,将image 文件夹里的镜像复制到fat32的TF卡也能看效果)
请问一下,我不配置设备树的话petalinux-build会出错,具体如下:
很显然是phy1的问题,但我该如何配置phy1呢?我的petalinux是2020.2,使用您的hdf还是我自己生成的xsa都出现了该问题,最后我将phy1改为usb的phy成功编译了,但不知道是否可行
ERROR: device-tree-xilinx-v2020.2+gitAUTOINC+f725aaecff-r0 do_compile: Error executing a python function in exec_python_func() autogenerated:
The stack trace of python calls that resulted in this exception/failure was:
File: ‘exec_python_func() autogenerated’, lineno: 2, function:
0001:
*** 0002:devicetree_do_compile(d)
0003:
·······
*** 0512: output=stdout, stderr=stderr)
0513: return CompletedProcess(process.args, retcode, stdout, stderr)
0514:
0515:
0516:def list2cmdline(seq):
Exception: subprocess.CalledProcessError: Command ‘[‘dtc’, ‘-@’, ‘-p’, ‘0x1000’, ‘-i’, ‘/home/kingdom/petalinux/Petalinux_Net_TEST/project-spec/configs/../../components/plnx_workspace/device-tree/device-tree’, ‘-i’, ‘/home/kingdom/petalinux/Petalinux_Net_TEST/build/tmp/work/zynq_generic-xilinx-linux-gnueabi/device-tree/xilinx-v2020.2+gitAUTOINC+f725aaecff-r0’, ‘-i’, ‘/home/kingdom/petalinux/Petalinux_Net_TEST/build/tmp/work-shared/zynq-generic/kernel-source/scripts/dtc/include-prefixes’, ‘-i’, ‘/home/kingdom/petalinux/Petalinux_Net_TEST/build/tmp/work-shared/zynq-generic/kernel-source/arch/arm/boot/dts’, ‘-o’, ‘system-top.dtb’, ‘-I’, ‘dts’, ‘-O’, ‘dtb’, ‘system-top.dts.pp’]’ returned non-zero exit status 2.
Subprocess output:
/home/kingdom/petalinux/Petalinux_Net_TEST/project-spec/configs/../../components/plnx_workspace/device-tree/device-tree/zynq-7000.dtsi:288.27-297.5: ERROR (phandle_references): /amba/ethernet@e000b000: Reference to non-existent node or label “phy1”
also defined at /home/kingdom/petalinux/Petalinux_Net_TEST/project-spec/configs/../../components/plnx_workspace/device-tree/device-tree/pcw.dtsi:15.7-29.3
also defined at /home/kingdom/petalinux/Petalinux_Net_TEST/project-spec/configs/../../components/plnx_workspace/device-tree/device-tree/system-conf.dtsi:14.7-16.3
/home/kingdom/petalinux/Petalinux_Net_TEST/project-spec/configs/../../components/plnx_workspace/device-tree/device-tree/pcw.dtsi:23.38-27.5: ERROR (phandle_references): /amba/ethernet@e000b000/mdio/gmii_to_rgmii_0@8: Reference to non-existent node or label “phy1”
ERROR: Input tree has errors, aborting (use -f to force output)
ERROR: Logfile of failure stored in: /home/kingdom/petalinux/Petalinux_Net_TEST/build/tmp/work/zynq_generic-xilinx-linux-gnueabi/device-tree/xilinx-v2020.2+gitAUTOINC+f725aaecff-r0/temp/log.do_compile.5875
ERROR: Task (/home/kingdom/petalinux/Petalinux_Net_TEST/components/yocto/layers/meta-xilinx/meta-xilinx-bsp/recipes-bsp/device-tree/device-tree.bb:do_compile) failed with exit code ‘1’
我没完全看明白,可以描述以下 不被编译是因为定义了PHY1 ,还是说 没有定义设备树引起的?
另外你说的 定义回USB PHY 是什么意思呢, 我有点绕晕了 ,所以暂时不能给你答复
谢谢,没事了,因为我是个小白,只写过verlog,玩这些只是爱好,可能很业余,描述也可能不清楚。之前不懂硬件设备树什么的,后来研究了下设备树和petalinux,现在稍微了解了。
我想将所有东西整一起,然后用ext4的rootfs,我将usb、网络,lcd,led什么的都添加后生成了xsa,然后用petalinux进行了编译,然后就报Reference to non-existent node or label “phy1”这个错了,查看pcw.dtsi发现&gem里自动生成的是phy1,但里面又没有自动生成PHY1的定义。
然后我以为usb的phy和网络的phy是一个东西,因为了解到有个phy芯片啥的,还看到有说是什么外部phy的,然后我就用给usb定义的phy去替换网络自动生成的phy1,结果编译通过了,但好像连不上网,最后自己在system-user.dtsi里加上了&gem的全部定义(内含phy)后,所有功能才正常
替换就是把pcw.dtsi中自动生成的&gem里使用但没定义的phy1换成system-user.dtsi里自定义的给usb用的usb_phy
没被编译是因为自动生成没有生成phy1,但是自动生成了&gem,而&gem里用来phy1,而phy1既不是自己定义的,也没有自动生成
Hello king,
I have got the same issue as you did…..
(ERROR (phandle_references): /amba/ethernet@e000b000/mdio/gmii_to_rgmii_0@8: Reference to non -existent node or label “phy1”)
I tried several methods to get rid of this error,but those didn’t work.
Can you please help me on what changes should i make to system-user.dtsi?
可以详细描述一下吗? 根据大家的反馈 2020以上的版本 petalinux 里的 网络设备树部分似乎都不是自动生成的 ,可以手动添加网络部分的设备树内容
我也遇到这个问题了,就是phy1在pcw.dtsi不会自动生成,其他和2018.3一样,然后build到这里会报phy1未定义的错误
可以告知版本号吗?
我试过2020.2 2022.2 2023.2 2024.1都不可以,之前搜到过一个帖子,gmii2rgmii在2018.3之后的引脚全部有问题