LoginSignup
3
2

More than 5 years have passed since last update.

FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(ZYBOとDE0-Nano-SoCのデュアルブートに対応)

Last updated at Posted at 2016-08-15

注意(2017年9月20日追記)

この記事は Linux Kernel 4.4 時点に投稿したものであり、古い内容が含まれています。Linux Kernel 4.10 以降、FPGA 関連は大きく進歩しました。詳しくは「Linux Kernel 4.10 でのFPGAのサポート事情」を参照してください。

はじめに

以下の記事で Device Tree Overlay と FPGA Manager に対応した FPGA+SoC+Linux の動作環境を紹介しました。

さらに、以下の記事でこのシステムを ZYBO と DE0-Nano-SoC に対応した実例を紹介しました。

上で紹介した実例では ZYBO と DE0-Nano-SoC で別々の SD-Card を用意していましたが、この記事では、1枚の SD-Card で ZYBO と DE0-Nano-SoC の2種類のボードで起動する方法を紹介します。

もともと、このデュアルブート方法は、次の資料に触発されたもので、おおいに参考にさせてもらいました。この場を借りてお礼を申し上げます。

  • 石原ひでみ. 『第五章 ついに起動!デュアル・ブート SD カードの作り方』「FPGA マガジン No.12」57頁

追記

  • 2017/1/14 に Linux Kernel のバージョンを v4.8.17 に更新しました。
  • 2017/1/31 に udmabuf のバージョンを v0.6.0 に更新しました。

概要

  • Hardware
    • ZYBO : Xilinx Zynq-7000 ARM/FPGA SoC Trainer Board by Digilent
    • DE0-Nano-SoC : Altera SoC FPGA Development Kit by terasic
  • U-Boot v2016.03 (customized)
    • Build for ZYBO and DE0-Nano-SoC
    • Customized boot by uEnv.txt
    • Customized boot by boot.scr
  • Linux Kernel Version v4.4.7 or v4.8.17
    • Available in both Xilinx-Zynq-7000 and Altera-SoC in a single image
    • Enable Device Tree Overlay
    • Enable FPGA Manager
  • Debian8(jessie) Root File System
    • Installed build-essential
    • Installed device-tree-compiler
    • Installed ruby ruby-msgpack ruby-serialport
    • Installed u-boot-tools
  • FPGA Device Drivers
    • dtbocfg (Device Tree Blob Overlay Configuration File System)
    • fpgacfg (FPGA Configuration Interface for Linux FPGA Manager Framework)
    • fclkcfg (FPGA Clock Configuration Device Driver)
    • udmabuf (User space mappable DMA Buffer)
    • zptty (Pseudo TeleTYpewriter for FPGA Device)
    • fpga-bridge (FPGA to/from HPS Bridge Driver for Altera SoCFPGA Devices)

インストール

ダウンロード

github から次のようにダウンロードしてください。
現時点の最新バージョンは v0.2.0 です。チェックアウトしてください。
なお、いくつかのイメージファイルはかなり大きいので、Git LFS(Large File Storage)を使っています。
お使いの環境に git-lfs がインストールされている必要があります。

shell$ git clone git://github.com/ikwzm/FPGA-SoC-Linux
shell$ cd FPGA-SoC-Linux
shell$ git checkout v0.3.3
shell$ git lfs pull

Build boot files

ZYBO 用のディレクトリと DE0-Nano-SoC 用のディレクトリから必要なファイルをデュアル・ブート用のディレクトリ(target/zynq-zybo-de0-nano-soc)にコピーします。
target/zynq-zybo-de0-nano-soc/Makefile を用意していますので活用してください。

shell$ cd target/zynq-zybo-de0-nano-soc/
shell$ make
mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n "linux boot script" -d boot/boot.script boot/boot.scr
Image Name:   linux boot script
Created:      Fri Jan 13 17:05:07 2017
Image Type:   ARM Linux Script (uncompressed)
Data Size:    1324 Bytes = 1.29 kB = 0.00 MB
Load Address: 00000000
Entry Point:  00000000
Contents:
   Image 0: 1316 Bytes = 1.29 kB = 0.00 MB
cp ../zynq-zybo/boot/zImage-4.8.17-armv7-fpga boot/zImage-4.8.17-armv7-fpga
cp ../zynq-zybo/boot/boot.bin boot/boot.bin
cp ../zynq-zybo/boot/design_1_wrapper.bit boot/design_1_wrapper.bit
cp ../zynq-zybo/boot/devicetree-4.8.17-zynq-zybo.dtb boot/devicetree-4.8.17-zynq-zybo.dtb
cp ../zynq-zybo/boot/devicetree-4.8.17-zynq-zybo.dts boot/devicetree-4.8.17-zynq-zybo.dts
cp ../zynq-zybo/boot/u-boot.img boot/u-boot.img
cp ../de0-nano-soc//boot/devicetree-4.8.17-socfpga.dtb boot/devicetree-4.8.17-socfpga.dtb
cp ../de0-nano-soc//boot/devicetree-4.8.17-socfpga.dts boot/devicetree-4.8.17-socfpga.dts
cp ../de0-nano-soc//boot/DE0_NANO_SOC.rbf boot/DE0_NANO_SOC.rbf
cp ../de0-nano-soc//u-boot/u-boot-spl.sfp u-boot/u-boot-spl.sfp
cp ../de0-nano-soc//u-boot/u-boot.img u-boot/u-boot.img

ファイルの説明

デュアル・ブート用のディレクトリ(tareget/zynq-zybo-de0-nano-soc)には以下のようなファイルがあります。

  • tareget/zynq-zybo-de0-nano-soc/
    • boot/
      • boot.bin : Stage 1 Boot Loader (for ZYBO U-boot-spl)
      • u-boot.img : Stage 2 Boot Loader (for ZYBO U-boot image)
      • uEnv.txt : U-Boot environment variables for set kernel version
      • boot.script : U-Boot boot script (source)
      • boot.scr : U-Boot boot script (binary)
      • design_1_wrapper.bit : FPGA configuration file (for ZYBO)
      • DE0_NANO_SOC.rbf : FPGA configuration file (for DE0-Nano-SoC)
      • zImage-4.8.17-armv7-fpga : Linux Kernel Image
      • devicetree-4.8.17-zynq-zybo.dtb : Linux Device Tree Blob (for ZYBO)
      • devicetree-4.8.17-zynq-zybo.dts : Linux Device Tree Source (for ZYBO)
      • devicetree-4.8.17-socfpga.dtb : Linux Device Tree Blob (for DE0-Nano-SoC)
      • devicetree-4.8.17-socfpga.dts : Linux Device Tree Source (for DE0-Nano-SoC)
    • u-boot/
      • u-boot-spl.sfp : Stage 1 Boot Loader (for DE0-Nano-SoC U-boot-spl)
      • u-boot.img : Stage 2 Boot Loader (for DE0-Nano-SoC U-boot image)
  • debian8-rootfs-vanilla.tgz : Debian8 Root File System (use Git LFS)
  • linux-image-4.8.17-armv7-fpga_4.8.17-armv7-fpga-1_armhf.deb : Linux Image Package (use Git LFS)
  • linux-headers-4.8.17-armv7-fpga_4.8.17-armv7-fpga-1_armhf.deb : Linux Headers Package (use Git LFS)
  • fpga-soc-linux-drivers-4.8.17-armv7-fpga_0.0.3-1_armhf.deb : Device Drivers Package (use Git LFS)

SD-Card のフォーマット

SD-Card のパーティション1を FAT File System でファイルシステムを作ります。
SD-Card のパーティション2を ext3 File System でファイルシステムを作ります。
SD-Card のパーティション3を 特殊パーティション(パーティションタイプ=0xa2)にします。ファイルシステムは作りません。
フォーマット方法の詳細は『第五章 ついに起動!デュアル・ブート SD カードの作り方』「FPGA マガジン No.12」を参照してください。

SD-Card への書き込み

SD-Card のパーティション3(下の例では/dev/sdc3)に target/zynq-zybo-de0-nano-soc/u-boot/ 下のファイルイメージを dd を使って書き込みます。
SD-Card のパーティション1(下の例では/dev/sdc1)に target/zynq-zybo-de0-nano-soc/boot/ 下のファイルをコピーします。
SD-Card のパーティション2(下の例では/dev/sdc2)に debian8-rootfs-vanilla.tgz の中身を展開します。
また、展開したルートファイルシステムの home/fpga に fpga-soc-linux-drivers パッケージをあらかじめコピーしておくと良いでしょう。後から network 経由でコピーしてもかまいません。

shell# mount /dev/sdc1 /mnt/usb1
shell# mount /dev/sdc2 /mnt/usb2
shell# cp target/zynq-zybo-de0-nano-soc/boot/*                          /mnt/usb1
shell# dd if=target/zynq-zybo-de0-nano-soc/u-boot/u-boot-spl.sfp of=/dev/sdc3 bs=64k seek=0
shell# dd if=target/zynq-zybo-de0-nano-soc/u-boot/u-boot.img     of=/dev/sdc3 bs=64k seek=4
shell# tar xfz debian8-rootfs-vanilla.tgz -C                            /mnt/usb2
shell# cp linux-image-4.8.17-armv7-fpga_4.8.17-armv7-fpga-1_armhf.deb   /mnt/usb2/home/fpga
shell# cp linux-headers-4.8.17-armv7-fpga_4.8.17-armv7-fpga-1_armhf.deb /mnt/usb2/home/fpga
shell# cp fpga-soc-linux-drivers-4.8.17-armv7-fpga_0.0.3-1_armhf.deb    /mnt/usb2/home/fpga
shell# umount mnt/usb1
shell# umount mnt/usb2

デバイスドライバパッケージのインストール

省略します。「FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(ブートイメージの提供)」 を参照してください。

デュアル・ブートのしくみ

1枚の SD-Card で ZYNQ と DE0-Nano-SoC の両方をブートするしくみに関しては『第五章 ついに起動!デュアル・ブート SD カードの作り方』を参照してください。

ここでは、U-Boot がスクリプトによって ZYBO と DE0-Nano-SoC でブート手順を切り替える手法の説明をします。

U-Boot の改良

https://github.com/ikwzm/FPGA-SoC-Linuxで用意した U-Boot には、ソースコードに少し細工がしてあります。

ZYBO 用の U-Boot のソースコードには次のようなパッチをあてています。

diff --git configs/zynq_zybo_defconfig configs/zynq_zybo_defconfig
index 7c23fec..8fc954e 100644
--- configs/zynq_zybo_defconfig
+++ configs/zynq_zybo_defconfig
@@ -22,3 +22,5 @@ CONFIG_DEBUG_UART_ZYNQ=y
 CONFIG_DEBUG_UART_BASE=0xe0001000
 CONFIG_DEBUG_UART_CLOCK=50000000
 CONFIG_ZYNQ_QSPI=y
+# CONFIG_OF_SEPARATE is not set
+CONFIG_OF_EMBED=y
diff --git include/configs/zynq-common.h include/configs/zynq-common.h
index 982905d..fd50c69 100644
--- include/configs/zynq-common.h
+++ include/configs/zynq-common.h
@@ -227,10 +227,35 @@
    "usbboot=if usb start; then " \
            "echo Copying FIT from USB to RAM... && " \
            "load usb 0 ${load_addr} ${fit_image} && " \
-           "bootm ${load_addr}; fi\0" \
-       DFU_ALT_INFO
-
-#define CONFIG_BOOTCOMMAND     "run $modeboot"
+           "bootm ${load_addr}\0" \
+       "fi\0" \
+   "bootenv=uEnv.txt\0" \
+        "config=" CONFIG_DEFAULT_DEVICE_TREE "\0" \
+   "loadbootenv=load mmc 0 ${load_addr} ${bootenv}\0" \
+   "importbootenv=echo Importing environment from mmc ...;" \
+       "env import -t $load_addr $filesize\0" \
+        "loadbootscript=load mmc 0 ${load_addr} boot.scr\0" \
+        "bootscript=echo Running bootscript from mmc ...;" \
+                "source ${load_addr}\0" \
+   DFU_ALT_INFO
+
+#define CONFIG_BOOTCOMMAND \
+   "if mmc rescan; then " \
+       "echo SD/MMC found on device...;" \
+       "if run loadbootenv; then " \
+           "echo Loaded environment from ${bootenv};" \
+           "run importbootenv;" \
+       "fi;" \
+       "if test -n $uenvcmd; then " \
+           "echo Running uenvcmd ...;" \
+           "run uenvcmd;" \
+       "fi;" \
+       "if run loadbootscript; then " \
+           "run bootscript; " \
+       "fi; " \
+   "fi;" \
+        "run $modeboot"
+#define CONFIG_CMD_BOOTZ
 #define CONFIG_BOOTDELAY       3 /* -1 to Disable autoboot */
 #define CONFIG_SYS_LOAD_ADDR       0 /* default? */

DE0-Nano-SoC 用の U-Boot のソースコードには次のようなパッチをあてています。

diff --git include/configs/socfpga_de0_nano_soc.h include/configs/socfpga_de0_nano_soc.h
index cbc7396..1b68bdb 100644
--- include/configs/socfpga_de0_nano_soc.h
+++ include/configs/socfpga_de0_nano_soc.h
@@ -37,7 +37,22 @@
 #define CONFIG_BOOTDELAY   3
 #define CONFIG_BOOTFILE        "fitImage"
 #define CONFIG_BOOTARGS        "console=ttyS0," __stringify(CONFIG_BAUDRATE)
-#define CONFIG_BOOTCOMMAND "run mmcload; run mmcboot"
+#define CONFIG_BOOTCOMMAND     \
+   "if mmc rescan; then " \
+       "echo SD/MMC found on device...;" \
+       "if run loadbootenv; then " \
+           "echo Loaded environment from ${bootenv};" \
+           "run importbootenv;" \
+       "fi;" \
+       "if test -n $uenvcmd; then " \
+           "echo Running uenvcmd ...;" \
+           "run uenvcmd;" \
+       "fi;" \
+       "if run loadbootscript; then " \
+           "run bootscript; " \
+       "fi; " \
+   "fi;" \
+        "run mmcload; run mmcboot"
 #define CONFIG_LOADADDR        0x01000000
 #define CONFIG_SYS_LOAD_ADDR   CONFIG_LOADADDR

@@ -65,6 +80,15 @@
    "mmcload=mmc rescan;" \
        "load mmc 0:1 ${loadaddr} ${bootimage};" \
        "load mmc 0:1 ${fdt_addr} ${fdtimage}\0" \
+        "fpgadata=0x02000000\0" \
+   "bootenv=uEnv.txt\0" \
+   "config=" CONFIG_DEFAULT_DEVICE_TREE "\0" \
+   "loadbootenv=load mmc 0 ${loadaddr} ${bootenv}\0" \
+   "importbootenv=echo Importing environment from mmc ...;" \
+       "env import -t $loadaddr $filesize\0" \
+        "loadbootscript=load mmc 0 ${loadaddr} boot.scr\0" \
+        "bootscript=echo Running bootscript from mmc ...;" \
+                "source ${loadaddr}\0" \

 /* The rest of the configuration is shared */
 #include <configs/socfpga_common.h>

いずれのパッチも次のような修正をしています。

  1. config 変数に U-Boot ビルド時のボード名を設定する
  2. ブート時に uEnv.txt を読んで環境変数を設定する
  3. ブート時に uEnv.txt に uenvcmd 変数が設定されていた場合はこれを実行する
  4. ブート時に uenvcmd が無くて boot.scr があれば、boot.scr を実行する

uEnv.txt

uEnv.txt では Linux Kernel のバージョン番号を設定しています。

uEnv.txt
kernel_version=4.8.17

boot.scr

boot.scr は次のようなスクリプト(boot.script)を U-Boot 用にコンパイルしたものです。

boot.script
if test $config = "zynq-zybo"; then
    echo "Configuration for " $config
    boot_image=zImage-$kernel_version-armv7-fpga
    fdt_image=devicetree-$kernel_version-zynq-zybo.dtb
    fpga_image=design_1_wrapper.bit
    if  fatload mmc 0 0x03000000 $fpga_image; then
        fpga loadb  0 0x03000000 $filesize
        mw.l 0xF8000008 0xDF0D
        mw.l 0xF8000170 0x00100A00
        mw.l 0xF8000004 0x767B
    fi
    fatload mmc 0 0x03000000 $boot_image
    fatload mmc 0 0x02A00000 $fdt_image
    setenv bootargs console=ttyPS0,115200 root=/dev/mmcblk0p2 rw rootwait uio_pdrv_genirq.of_id=generic-uio
    if test $kernel_version = "4.8.17"; then
        setenv bootargs $bootargs sdhci.debug_quirks=64
    fi
    bootz 0x03000000 - 0x02A00000
fi
if test $config = "socfpga_cyclone5_de0_nano_soc"; then
    echo "Configuration for " $config
    boot_image=zImage-$kernel_version-armv7-fpga
    fdt_image=devicetree-$kernel_version-socfpga.dtb
    fpga_image=DE0_NANO_SOC.rbf
    if  fatload mmc 0 $fpgadata $fpga_image; then
        fpga load 0   $fpgadata $filesize
        bridge enable
    fi
    fatload mmc 0 $loadaddr $boot_image
    fatload mmc 0 $fdt_addr $fdt_image
    setenv bootargs console=ttyS0,115200 root=/dev/mmcblk0p2 rw rootwait uio_pdrv_genirq.of_id=generic-uio
    bootz $loadaddr - $fdt_addr
fi

U-Boot のビルド時に config 変数にボードの種類が設定されていて、この config 変数の値によってブートの手順を切り替えています。

uEnv.txt で kernel_verion 変数に Linux カーネルのバージョンを設定して、そのバージョンに対応したカーネルのイメージとデバイスツリーをロードするようにしています。

なお、Linux Kernel v4.8.17 には sdhci ドライバに問題があって、そのままでは ZYNQ では動きません。その回避策として bootargs に sdhci.debug_quirks=64 を追加しています。詳細は「Zynq + Linux Kernel 4.5(以降) で "mmc0: Timeout waiting for hardware interrupt" が起きる場合の対処方法」 を参照してください。

参考

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2