ひでみのアイデア帳

くだらないことなんだけど、忘れないために・・・

Zynqをu-bootだけでブートする

ここ最近、メインラインのu-bootとLinux Kernelのソースコードを眺めている。

u-bootを眺めていたら、ずいぶん進化していたのでZYBO向けに取り込んでみた。

今回、使用したu-bootは2015.07でu-bootのversionコマンドでは次のように表示される。

U-Boot 2015.07-rc3-00054-g891b487-dirty (Jul 09 2015 - 13:28:00 +0900)

arm-poky-linux-gnueabi-gcc (GCC) 4.9.2

GNU ld (GNU Binutils) 2.25.0

SPL

最新のu-boot環境ではSPLという、ブートローダが追加されている。

SPLとはSecond Program Loaderの略でありVivado SDKでいう、FSBL(First Stage Boot Loader)に取って代わるブートローダである。

SPLのおかげでVivado SDKでFSBLを生成する手間が一つ省けるようになった。

さらに、SPLはfalconブートという、u-bootを抜いて一気にLinux Kernelなどを起動するモードも存在する。

高速起動などが必要な場合は、falconブートを使用すると良いだろう。

ただ、FPGA(PL)のデバッグなどでu-bootはその力を発揮するので当面はu-bootを使用したままにしておく。

DTS

Linux Kernelではお馴染みのDevice Freeだが、u-bootでも採用されるようになった。

従って、今後、Device Treeはu-boot用とLinux Kernel用があることを認識しておかなければいけない。

u-boot用のDevice Treeはあくまで起動で必要なペリフェラルの設定だけを含めるように心がける。

余計なものを設定しているとそれだけ、容量と起動が遅くなるだけだ。

Linux Kernel用のDevice Treeは使用する全てのペリフェラルの設定を記載する。

FIT

FITとはFlat Image Treeの略で、Linux Kernel、InitRam、Device Treeなどをパック化したイメージである。

最近のu-bootはデフォルトでこのFITを使用して、Linux Kernelを起動するようになっているが、Linux Kernelのデバイスドライバなどの開発時はドライバを組み込んではFITを生成しなおすという手間が発生するので、従来通り、作業しやすいようにuImage、DeviceTreeなどを別々でロードしてLinux Kernelを起動する方法を採用する。

FITはLinux KernelをFixした時に使用するだけに留めるのが良いだろう。

クロス環境

何はともあれ、まず最初にクロス環境の準備である。

% source /opt/poky/1.8+snapshot/environment-setup-cortexa9-vfp-neon-poky-linux-gnueabi

クロスコンパイル環境はYocto 1.8というか、いつものように最新版でTool Chainを作成している。

通常、クロスコンパイル環境で行う次の儀式も環境変数のセットアップに含まれているので上記のコマンド一発でクロス開発環境になる。

export ARCH=arm

export CROSS_COMPILE=arm-poky-linux-gnueabi-

u-bootのダウンロード

次のようにdenxのgitリポジトリからu-bootをcloneする。

% git clone git://git.denx.de/u-boot.git

% cd u-boot

ps7_init.[ch]生成方法

SPLには、Vivado SDKで生成できるPS7の初期化コードが必要である。

これはFSBLをビルドするときと同じであり、VivadoからExport Hardwareを行うと、ZYBO.sdk/ZYBO_hw_platform_XにHDFファイルが生成される。

このHDFファイルを使用して、PS7の初期化コードのps7_init_gpl.[ch]を生成することになる。

ps7_init_gpl.[ch]は従来のFSBLをビルドするように生成しても構わないが、hsiコマンドで生成することができる。

% cd /usr/bin

% sudo ln -s make gmake

% hsi

** hsi v2015.1 (64-bit)

  **** SW Build 1215546 on Mon Apr 27 19:19:00 MDT 2015

    ** Copyright 1986-2015 Xilinx, Inc. All Rights Reserved.

hsi% open_hw_design ZYBO_wrapper.hdf

ZYBO_wrapper

hsi% generate_app -hw ZYBO_wrapper -os standalone -proc ps7_cortexa9_0 -app zynq_fsbl -sw fsbl -dir zynq_fsbl

WARNING : No interface that uses file system is available

hsi::generate_target: Time (s): cpu = 00:00:05 ; elapsed = 00:00:05 . Memory (MB): peak = 447.406 ; gain = 0.914 ; free physical = 4366 ; free virtual = 13970

hsi::generate_app: Time (s): cpu = 00:00:05 ; elapsed = 00:00:05 . Memory (MB): peak = 447.406 ; gain = 0.914 ; free physical = 4369 ; free virtual = 13970

hsi% quit

これでFSBLでお馴染みのps7_init.[ch]が生成される。

この2つのファイルをu-bootのboard/xilinx/zynq/custom_hw_platformへ次のようにコピーする。

% cp HOGEHOGE/ps7_init.c board/xilinx/zynq/custom_hw_platform/ps7_init_gpl.c

% cp HOGEHOGE/ps7_init.h board/xilinx/zynq/custom_hw_platform

ただ、hsiコマンドだけのためにVivado SDKをインストールしておかなければいけないがhsiコマンドのおかげでLinuxを起動するまでVivado SDKを立ち上げることは無くなった。

つまり、VivadoからLaunch SDKもしなくて良くなったのだ。

今後、hsiコマンドもVivado本体に取り込まれることを期待しよう。

環境変数

include/configs/zynq-common.h

/ Default environment /

define CONFIG_EXTRA_ENV_SETTINGS

"fit_image=fit.itb\0"       

"load_addr=0x2000000\0"     

"fit_size=0x800000\0"       

"flash_off=0x100000\0"      

"nor_flash_off=0xE2100000\0"    

"fdt_high=0x20000000\0"     

"initrd_high=0x20000000\0"  

"norboot=echo Copying FIT from NOR flash to RAM... && " 

    "cp.b ${nor_flash_off} ${load_addr} ${fit_size} && " 

    "bootm ${load_addr}\0" 

"sdboot=echo Copying FIT from SD to RAM... && " 

    "load mmc 0 ${load_addr} ${fit_image} && " 

    "bootm ${load_addr}\0" 

"jtagboot=echo TFTPing FIT to RAM... && " 

    "tftpboot ${load_addr} ${fit_image} && " 

    "bootm ${load_addr}\0" 

"usbboot=if usb start; then " 

        "echo Copying FIT from USB to RAM... && " 

        "load usb 0 ${load_addr} ${fit_image} && " 

        "bootm ${load_addr}\0" 

    "fi\0" 

    DFU_ALT_INFO

bootmodeはM0〜M4の設定によって決まる。

norboot、sdboot,jtagbootの3種類がある。

そこで、次のsdbootを変更する。

"sdboot=echo Copying FIT from SD to RAM... && " 

    "load mmc 0 ${load_addr} ${fit_image} && " 

    "bootm ${load_addr}\0" 

bootargs=console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0

kernel_image=uImage

devicetree_image=devicetree.dtb

kernel_load_address=0x2080000

devicetree_load_address=0x2000000

uenvcmd=echo Copying Linux from SD to RAM... && mmcinfo && fatload mmc 0 ${kernel_load_address} ${kernel_image} && fatload mmc 0 ${devicetree_load_address} ${devicetree_image} && bootm ${kernel_load_address} - ${devicetree_load_address}

u-bootのビルド

% make zynq_zybo_defconfig

% make

ビルドが完了すると、u-boot-dtb.img、spl/u-boot-spl.binが生成されている。

使用するバイナリファイルはこの2つでZynqのu-boot起動までの環境を作成する。

boot.binの生成

boot.binは従来はbootgenコマンドを使用して、FSBL、Bitストリーム、u-bootをパックにして生成していたが、今回はPythonスクリプトで生成する。

boot.binを生成するスクリプトを取得する

これだけはu-bootのメインラインに入っていないのでXilinxのu-boot-xlnxリポジトリから借用する。

% git clone git://github.com/Xilinx/u-boot-xlnx

% cp u-boot-xlnx/tools/zynq-boot-bin.py ~/bin

% zynq-boot-bin.py -o boot.bin -u spl/u-boot-spl.bin

SPL(u-boot-spl.bin)はこの方法でboot.binを生成しないと正常起動しないので注意しなければいけない。

生成されたboot.binとu-boot-dtb.imgをSDカードにコピーする。

% cp boot.bin SDCARD

% cp u-boot-dtb.img SDCARD

ついでにBitストリームもコピーしよう。

% cp ZYBO.bit SDCARD

起動

さぁ、準備が整ったので起動しよう。

U-Boot 2015.07-rc3-00054-g891b487-dirty (Jul 09 2015 - 13:28:00 +0900)

Model: Zynq ZED Board

I2C:   ready

DRAM:  ECC disabled 512 MiB

MMC:   zynq_sdhci: 0

Using default environment

In:    serial

Out:   serial

Err:   serial

Model: Zynq ZED Board

Net:   Gem.e000b000

Error: Gem.e000b000 address not set.

Hit any key to stop autoboot:  0

以前よりも凄く手順が簡単になった。

u-bootからBit Streamのロード方法

FPGAのロードはu-boot上から行うことができる。

次の2つのコマンドを使用するだけだ。

load mmc 0 0x1000000 ZYBO.bit

fpga loadb 0 0x1000000 4045659

zynq-uboot> load mmc 0 0x1000000 ZYBO.bit

reading ZYBO.bit

4045659 bytes read in 367 ms (10.5 MiB/s)

zynq-uboot> fpga loadb 0 0x1000000 4045659

  design filename = "ZYBO;UserID=0XFFFFFFFF"

  part number = "7z020clg484"

  date = "2014/07/24"

  time = "10:59:12"

  bytes in bitstream = 4045564

zynq_align_dma_buffer: Align buffer at 100005f to ffffe0(swap 1)

FPGAをロードするときの注意として、Bitストリームをアドレスの0x0000_0000へロードしてしまうと正常にBitストリームがロードできない。

SDカード

パーティション1はFAT、パーティーション2はext4でLinuxのrootfs

パーティーション1には次のものが入る。

boot.bin

uImage

u-boot-dtb.img

devicetree.dtb

ZYBO.bit

開発環境

開発順序は次のようになるなぁ。

1.Vivado Design SuiteでIP開発

2.Vivado Design SuiteでIP IntegratorでSoCモデリング

3.Vivado Design Suiteで論理合成/配置配線

1.Linuxディストリビューション構築

2.クロス開発環境構築

4.u-bootでSPL、u-bootビルド

4.Linux Kernelビルド/Linux Kernelドライバ開発

5.Qt5アプリケーション開発/アプリケーション開発