天天看點

1. PYNQ在ZCU102上的移植【PYNQ】

在goggle上搜zcu102 pynq可以找到一些移植方法的資訊

0. Prebuilt

下載:

完整Image固件

1. 生成鏡像

git clone

$ git clone https://github.com/Xilinx/PYNQ.git
$ cd PYNQ
$ git checkout v2.3
$ git checkout -b vacajk_dev
           

檢查依賴環境,qemu,crosstool-ng

$ cd sdbuild/scripts
$ ./setup_host.sh
$ source /opt/pkg/petalinux/settings.sh
$ source /opt/Xilinx/Vivado/2018.2/settings64.sh
$ cd ../../
           

拷貝ZCU104的配置作為ZCU102來使用,删除不用的ZCU104petalinux配置

$ cp -rf ./boards/ZCU104 ./boards/ZCU102
$ rm -rf ./boards/ZCU102/petalinux_bsp/
$ mv ./boards/ZCU104/ZCU104.spec ./boards/ZCU102/ZCU102.spec
$ gedit ./boards/ZCU102/ZCU102.spec
           

修改ZCU102.spec的内容

ARCH_ZCU102 := aarch64
BSP_ZCU102 := xilinx-zcu102-v2018.2-final.bsp
STAGE4_PACKAGES_ZCU102 := ethernet
           

從官網上下載下傳xilinx-zcu102-v2018.2-final.bsp,複制到./boards/ZCU102目錄下從github下載下傳的腳本能夠完整的生成img檔案,并會自動将所有的環境搭建完畢,但是速度很慢,看了PYNQ的官網發現能夠直接下載下傳編譯好的rootfs

這樣僅僅編譯BOOT.bin和隻包含kernel的image.ub就可以了。

網上下載下傳的rootfs

如果準備使用下載下傳的rootfs,在這裡下載下傳rootfs的鏡像

1. PYNQ在ZCU102上的移植【PYNQ】

http://www.pynq.io/board.html

https://www.xilinx.com/member/forms/download/xef.html?filename=pynq_rootfs_aarch64_v2.3.zip

解壓後把bionic.aarch64.2.3.img複制到./sdbuild/prebuilt下

如下指令:

$ make boot_files BOARDS=ZCU102
$ make images BOARDS=ZCU102 PREBUILT=./prebuilt/bionic.aarch64.2.3.img
           

自行生成的rootfs

如果準備自行編譯rootfs,如下指令。比較花時間且網速影響較大

$ make BOARDS=ZCU102
           

2. 燒寫鏡像

生成的img檔案在./sdbuild/output/ZCU102-2.3.img

使用Win32_Disk_Imager将img燒寫到SD卡中

1. PYNQ在ZCU102上的移植【PYNQ】

在linux上可以檢視SD卡分區及内容,可以看到包含一個FAT32分區用于存放BOOT.bin和image.ub

第二個分區是檔案系統,ubunttu 18.04嘗試啟動,使用序列槽可以看到能夠正常登陸

1. PYNQ在ZCU102上的移植【PYNQ】

通過網頁直接連接配接通路ZCU102,輸入密碼xilinx可以打開jupyter-notebook,預設目錄中有各種例子,可以進行嘗試。

1. PYNQ在ZCU102上的移植【PYNQ】

3. 自定義FPGA固件

因為使用的是bsp中的FPGA固件,裡面的邏輯外設可能不符合要求,下面重新編輯FPGA固件,測試闆上的LED和DIP SWITCH

編輯Vivado工程

使用vivado 2018.2打開xilinx-zcu102-v2018.2-final.bsp中的vivado工程

1. PYNQ在ZCU102上的移植【PYNQ】

增加兩個AXI_GPIO子產品,分别用于測試led和switch,添加幾個其他ip用于整體系統組成

1. PYNQ在ZCU102上的移植【PYNQ】

在xdc中添加IO管腳限制。

set_property PACKAGE_PIN AG14 [get_ports {led_8bits_tri_o[0]}]
set_property PACKAGE_PIN AF13 [get_ports {led_8bits_tri_o[1]}]
set_property PACKAGE_PIN AE13 [get_ports {led_8bits_tri_o[2]}]
set_property PACKAGE_PIN AJ14 [get_ports {led_8bits_tri_o[3]}]
set_property PACKAGE_PIN AJ15 [get_ports {led_8bits_tri_o[4]}]
set_property PACKAGE_PIN AH13 [get_ports {led_8bits_tri_o[5]}]
set_property PACKAGE_PIN AH14 [get_ports {led_8bits_tri_o[6]}]
set_property PACKAGE_PIN AL12 [get_ports {led_8bits_tri_o[7]}]  
set_property IOSTANDARD LVCMOS33 [get_ports {led_8bits_tri_o[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_8bits_tri_o[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_8bits_tri_o[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_8bits_tri_o[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_8bits_tri_o[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_8bits_tri_o[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_8bits_tri_o[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_8bits_tri_o[7]}]    
set_property PACKAGE_PIN AN14 [get_ports {dip_switch_8bits_tri_i[0]}]
set_property PACKAGE_PIN AP14 [get_ports {dip_switch_8bits_tri_i[1]}]
set_property PACKAGE_PIN AM14 [get_ports {dip_switch_8bits_tri_i[2]}]
set_property PACKAGE_PIN AN13 [get_ports {dip_switch_8bits_tri_i[3]}]
set_property PACKAGE_PIN AN12 [get_ports {dip_switch_8bits_tri_i[4]}]
set_property PACKAGE_PIN AP12 [get_ports {dip_switch_8bits_tri_i[5]}]
set_property PACKAGE_PIN AL13 [get_ports {dip_switch_8bits_tri_i[6]}]
set_property PACKAGE_PIN AK13 [get_ports {dip_switch_8bits_tri_i[7]}] 
set_property IOSTANDARD LVCMOS33 [get_ports {dip_switch_8bits_tri_i[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dip_switch_8bits_tri_i[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dip_switch_8bits_tri_i[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dip_switch_8bits_tri_i[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dip_switch_8bits_tri_i[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dip_switch_8bits_tri_i[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dip_switch_8bits_tri_i[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dip_switch_8bits_tri_i[7]}]
           

Create HDL Wrapper,注意zcu102_wrapper.v的内容是否正常,我是删除了原有的,然後重新生成的。編譯并生成bitstream

完成後使用Export Block Design将bd的tcl生成檔案輸出。

拷貝并重命名剛生成的bit和tcl檔案,并重命名為:

zcu102_led.bit和zcu102_led.tcl

使用PYTHON測試LED和DIP

使用tftp将剛才的兩個檔案複制到闆上的目錄中:/home/xilinx/zcu102_test/

$ cd ~/zcu102_test/
$ sudo python3
Python 3.6.5 (default, Apr  1 2018, 05:46:30) 
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from pynq import Overlay
>>> ol = Overlay('zcu102_led.bit')
>>> leds = ol.gpio_leds.channel1
>>> leds[0:8].on()
>>> leds[0:8].off()
>>> sws = ol.gpio_sws.channel1
>>> sws.read()
170
>>> sws.read()
85
           

如上即可使用python測試led和dip switch

使用jupyter-notebook來進行測試:

import time
from pynq import Overlay
           
leds = ol.gpio_leds.channel1
sws = ol.gpio_sws.channel1
           
for i in range(256):
    leds.write(mask=255, val=i)
    time.sleep(0.05)
print("led test finish!")
           
led test finish!
           
sws status: 0x00000028
           

4. 問題

問題1:發現在python中使用自動補全時程式崩潰

在python中使用ol = Overlay(‘zcu102_led.bit’)後,輸入ol進行自動補全時會使python程式崩潰。

>>> ol.[ 1491.769317] Bad mode in Error handler detected on CPU0, code 0xbf000002 -- SError
[ 1491.776716] Internal error: Oops - bad mode: 0 [#3] SMP
[ 1491.781922] Modules linked in:
[ 1491.784963] CPU: 0 PID: 4501 Comm: python3 Tainted: G      D         4.14.0-xilinx-v2018.2 #1
[ 1491.793466] Hardware name: ZynqMP ZCU102 Rev1.0 (DT)
[ 1491.798416] task: ffffffc877b4c000 task.stack: ffffff80092f8000
[ 1491.804319] PC is at 0x7f9d84b458
[ 1491.807616] LR is at 0x55cc3c
[ 1491.810568] pc : [<0000007f9d84b458>] lr : [<000000000055cc3c>] pstate: 80000000
[ 1491.817946] sp : 0000007fc15c5060
[ 1491.821245] x29: 0000007fc15c5060 x28: 0000007f9945ae00 
[ 1491.826540] x27: 0000007f99297e40 x26: 0000000000845578 
[ 1491.831836] x25: 0000000000000000 x24: 0000000000860000 
[ 1491.837131] x23: 0000007f9c5c0f60 x22: 0000007f9c645230 
[ 1491.842426] x21: 000000003b4ccf90 x20: 0000007f9c645282 
[ 1491.847721] x19: 0000007f9945ac48 x18: 0000007f9e0d3a70 
[ 1491.853017] x17: 00000000005751e0 x16: 0000007f9d8ab650 
[ 1491.858312] x15: 00000000000001ff x14: 0000000000000008 
[ 1491.863608] x13: 0000007f9a2bc348 x12: 0000000000000000 
[ 1491.868903] x11: 0000000000000000 x10: 000000003bb93498 
[ 1491.874198] x9 : 000000003bb93490 x8 : 0000000000000001 
[ 1491.879493] x7 : 00000000007b5750 x6 : 0000007f9db43008 
[ 1491.884789] x5 : 0000007fc15c4a48 x4 : 0000007f9d8b5d58 
[ 1491.890084] x3 : 0000007f994cb738 x2 : 5d43e4b8b60b9d00 
[ 1491.895380] x1 : 0000007f9d84b458 x0 : 0000007f994cb738 
[ 1491.900676] Process python3 (pid: 4501, stack limit = 0xffffff80092f8000)
[ 1491.907448] ---[ end trace fef7a706ca15de64 ]---
Segmentation fault
           

檢查發現問題出在了Vivado中Zynq UltraScale+ MPSoC子產品的配置有問題,但一直未定位到。。

子產品配置檔案:zcu102_ps_conf.tcl

可使用該配置在子產品中進行Apply Configuration,就能解決崩潰問題

1. PYNQ在ZCU102上的移植【PYNQ】
>>> ol.
ol.BS_FPGA_MAN            ol.gpio_dict              ol.load_ip_data(
ol.BS_FPGA_MAN_FLAGS      ol.gpio_leds              ol.parse_bit_header(
ol.axi_intc_0             ol.gpio_sws               ol.parser
ol.bin_path               ol.hierarchy_dict         ol.partial
ol.bitfile_name           ol.interrupt_controllers  ol.reset(
ol.clock_dict             ol.interrupt_pins         ol.timestamp
ol.convert_bit_to_bin(    ol.ip_dict                
ol.download(              ol.is_loaded(  
           

問題2:發現網絡不能正常連接配接

啟動以後進入系統,發現沒有eth0網口,感覺是下載下傳的rootfs img沒有加載執行STAGE4_PACKAGES_$(board)定義的ethernet包

檢視/sdbuild/packages/ethernet内的檔案内容,發現需要将eth0檔案放在/etc/network/interfaces.d下

有三種方式:

1. 在格式化sd卡前,直接在linux内編輯鏡像,并複制eth0到指定位置
2. 在序列槽控制台使用vim編輯文本,并複制到指定位置
3. 使用sudo ifconfig eth0 up && sudo ifconfig eth0 192.168.2.99 先使能網絡然後用tftp将eth0檔案複制到指定位置
           

eth0檔案内容如下:

auto eth0
iface eth0 inet dhcp    auto eth0:1
iface eth0:1 inet static
address 192.168.2.99
netmask 255.255.255.0
           

編輯完成後,重新開機闆子,即可看到網卡資訊

[email protected]:~$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.2.110  netmask 255.255.255.0  broadcast 192.168.2.255
        inet6 fe80::f4e8:61ff:fe39:2f29  prefixlen 64  scopeid 0x20<link>
        ether f6:e8:61:39:2f:29  txqueuelen 1000  (Ethernet)
        RX packets 1207  bytes 1082085 (1.0 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1180  bytes 106838 (106.8 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device interrupt 31      
eth0:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.2.99  netmask 255.255.255.0  broadcast 192.168.2.255
        ether f6:e8:61:39:2f:29  txqueuelen 1000  (Ethernet)
        device interrupt 31      
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 191  bytes 22047 (22.0 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 191  bytes 22047 (22.0 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
           

eth0為dhcp得到的ip位址。

eth0:1為靜态ip位址