Linux

【Zynq7】2.U-bootの構築

1.記事一覧

記事は複数回に分けて投稿します。Zynq7020SoCで動作する、YoctoベースのPetaLinuxを使わない素のLinuxを構築します。

ZynqMP(arm64版)はこちら

エッジArm Linux構築編(armv7l)

エッジArm Linux実践編(armv7l)

2.環境

開発PCUbuntu20.04, intel core i5 750 RAM 16G
DockerDocker Engine v23.0.0, Ubuntu20.04 base image
ターゲットボードDigilent Zybo z7-20 Rev.B.2(XC7Z020-1CLG400C, DDR3 1GB)
u-bootXilinxがGithubで提供するソースを使用。tag=xilinx-v2022.2
u-boot 2022.01
https://github.com/Xilinx/u-boot-xlnx/tree/xilinx-v2022.2
bootgenbootパーティションに配置するboot.binを生成するツール
Xilinxが提供するソースからインストールする(tag=xilinx_v2022.2)
https://github.com/Xilinx/bootgen/tree/xilinx_v2022.2

u-bootのビルド環境にはDockerコンテナ環境を使用します。理由は私の開発PCではすでに別の開発環境が入っており、クリーンでないからです。再現性を高めるためなので、必ずしも使う必要はなく、直接開発PC上に環境構築しても問題ありません。

ただし、Vitisを開発PCのUbuntuにインストールしたときに入る、bootgenコマンドを別途用意する必要があります。今回はコンテナ上でソースコードからビルドしてインストールします。

3.ビルド環境の構築

3-1. Ubuntu20.04 Image作成及び、コンテナ起動

#image作成例 Dockerfileはページ最後に記載

Bash
$ ls
Dockerfile
# docker build例
$ docker image build ./ -t ub2004/sample

コンテナ起動例:開発ホストPCのworkフォルダを共有フォルダに設定して、コンテナ上から操作できるようにします。

Bash
$ docker run -v "/home/ホストのユーザ名/work/:/home/share" --name "buildzynqlinux" -it "ub2004/sample" /bin/bash

3-2. ビルドパッケージのインストール

Bash
$ sudo apt install build-essential libssl-dev bison flex git gcc-arm-linux-gnueabihf

3-3. bootgenコマンドのビルドとインストール

Bash
$ mkdir bootgen_wk
$ cd bootgen_wk
$ git clone https://github.com/Xilinx/bootgen.git -b xilinx_v2022.2 --depth 1
$ cd bootgen
$ make
$ sudo cp ./bootgen /usr/local/bin
$ cd ../..

3-4. u-bootクロスビルド環境変数(zynq7なのでarmv7l)

Bash
$ export CROSS_COMPILE=arm-linux-gnueabihf-
$ export ARCH=arm  #<-- make時に指定しても良い

4.u-bootのビルド確認

4-1. Xilinx社のGithubよりu-bootのソースコードをclone

Bash
$ mkdir uboot_wk
$ cd uboot_wk
$ git clone https://github.com/Xilinx/u-boot-xlnx.git -b xilinx-v2022.2 --depth 1
$ cd u-boot-xlnx

4-2. zynq7標準defconfigによるビルド確認

環境構築がうまく行けばビルド通ります。

Bash
$ make xilinx_zynq_virt_defconfig
$ make

5.defconfigカスタム設定

5-1. 目的

最終目標はオリジナルカスタムボード向けのu-boot構築です。今回はzybo z7ボードをオリジナルカスタムボートに見立てて、defconfigを新規作成します。実はzybo z7ボードのdefconfig及びこの後説明するu-bootデバイスツリーはzybo z7ボードに対応した設定が既に存在します。選ぶだけだと何もすることが無いので、新規に起こして少しだけ改変します。

5-2. defconfigファイル新規作成

zynq7標準defconfigを複製して改変します。先ほどcloneしたu-bootソースのルートをカレントフォルダとします。
任意の名前でdefconfigファイルをコピーします。

Bash
$ cd ./configs
$ cp xilinx_zynq_virt_defconfig myboard_defconfig

5-3. defconfig設定箇所

作成したオリジナルdefconfigをエディタで編集します。主に変更するCONFIG値は3つです。

  • CONFIG_DEFAULT_DEVICE_TREE
  • CONFIG_OF_LIST
  • CONFIG_ZYNQ_GEM

1つ目はこの後作成するu-boot用デバイスツリーファイルの選択です。
2つ目はu-boot用デバイスツリーファイルのリストです。1つ目はこの中から選択します。
3つ目はGigabitEthernetポートの有無です。なひたふ氏によると未搭載のボードで’y’のままだと処理が停止することがあるとのことです。

5-4. defconfig設定内容

変更後のdefconfigです。デバイスツリーファイル名はこれから新規作成するので任意です。

  • CONFIG_DEFAULT_DEVICE_TREE="zynq-myboard"
  • CONFIG_OF_LIST="zynq-myboard"
  • CONFIG_ZYNQ_GEM=y

6.u-bootデバイスツリーカスタム設定

u-bootデバイスツリーソースファイルはarch/arm/dtsフォルダの中にあります。大量のファイルがありますが、”zynq-zybo-z7.dts”が今回使用するzyboz7ボードのデバイスツリーファイルになります。既に用意されているため、簡単な設定のみ変更していきます。

まずはzynq-zybo-z7.dtsを複製して新しいデバイスツリーファイルを作成します。ファイル名は「5-4.defconfig設定内容」で決めたファイル名です。

Bash
$ cd ./u-boot-xlnx/arch/arm/dts
$ cp ./zynq-zybo-z7.dts ./zynq-myboard.dts

6-1. model、compatibleの変更

デバイスツリーファイルをエディタで開きます。ルート”/{}”内にある以下の項目を編集します。

  • model = "Digilent Zybo Z7 board";
  • compatible = "digilent,zynq-zybo-z7", "xlnx,zynq-7000";

“model”はu-boot起動メッセージに表示される文字列です。オリジナルの名前に変えてみます。”compatible”は第一引数がベンダ名、第2引数が「5-4.defconfig設定」 の”CONFIG_DEFAULT_DEVICE_TREE”の値です。ボードベンダとチップベンダの2つ記載されています。変更した例は以下になります。

  • model = "Zybo z7 Custom Board by sh-goto";
  • compatible = "xlnx,zynq-myboard";

6-2. aliasesについて

aliases{}はu-bootがどのようなペリフェラルを使用するか定義します。そのままでも大丈夫です。

簡単に見ていくと、シリアルコンソールのメッセージの見るために”serial0″、SDカードからブートするために”mmc0″は最低必要です。”serial0″が

  • serial0 = &uart1;

とあるのはUSB-JTAGの仮想COM ポートにUART1が接続されているからです。開発PCとボードをUSBケーブルで接続すればu-bootの起動メッセージを見ることができます。ただし、”chosen{}”の”stdout-path”に”serial0″が選択されていることが条件です。

6-3. memory@0について

memoryの”reg”は搭載されているSDRAMのサイズを定義します。搭載されているのはDDR3 1GBです。第1引数=開始アドレス、第2引数=サイズで、

  • reg = <0x0 0x40000000>;

になります。今後PL(FPGA)側で画像バッファやのような領域を使用したい場合はLinux管理のSDRAMサイズを減らします。例えば

  • reg = <0x0 0x20000000>; ←Linux512MB,後半512MBをPLのIPで使用

というようにします。

7-4. 変更後のデバイスツリーファイル

6-4. 変更後のデバイスツリーファイル

7.u-bootビルド

7-1. Makefile編集

Makefileを編集して新規作成したデバイスツリーファイルをビルド対象にします。

“u-boot-xlnx/arch/arm/dts/Makefile”をエディタで開きます。
“dtb-$(CONFIG_ARCH_ZYNQ) += \”の項目(L.293)を探し、末尾に付け足します。

変更前

Makefile
...
zynq-zybo.dtb \
zynq-zybo-z7.dtb
dtb-$(CONFIG_ARCH_ZYNQMP) += \
...

変更後

Makefile
...
zynq-zybo.dtb \
zynq-zybo-z7.dtb \
zynq-myboard.dtb    #<--追加
dtb-$(CONFIG_ARCH_ZYNQMP) += \
...

拡張子が.dtbになっていますがこれはデバイスツリーソースファイル(.dts)をコンパイルしたデバイスツリーblobファイル(.dtb)のことです。

7-2. ビルド

フォルダを”u-boot-xlnx”直下に移動してビルドします。

Bash
$ make distclean
$ make clean
$ make myboard_defconfig
$ make

“u-boot-xlnx/”直下にu-boot.elfファイルが生成されます。

8.bootgenによるboot.binの生成

前記事でFSBL、Bitstreamの2ファイル、そしてu-boot.elfの3ファイルが生成できたので、これをまとめてboot.binファイルに結合します。

u-boot-xlnxソースフォルダから出て、適当なフォルダを作って3ファイル集めます。今までの記事の場合、以下のファイルになります。

  • design_1_wrapper.bit
  • fsbl.elf
  • u-boot.elf

8-1. mkboot.bifの作成

結合内容を定義したmkboot.bifを3ファイルと同じ階層に作成します。エディタで以下を入力してください。

8-2. boot.binの作成

以下コマンドを実行します。

Bash
$ bootgen -w -image mkboot.bif -o i boot.bin

boot.binが生成されたら完了です。

9.(追記)Linuxが起動せず止まる場合

u-bootの起動途中で環境変数が読み込めずLinuxカーネル起動不可になる場合があります。
解決方法はいくつかありますが、bootコマンドをソースに直書きしてみます。
また、番外編1.u-bootが途中で止まる問題でも取り上げています。

u-bootのソースフォルダu-boot-xlnx/include/configs/zynq-common.hを開き、
“CONFIG_EXTRA_ENV_SETTINGS”マクロ定義に追加します。

C
#ifndef CONFIG_EXTRA_ENV_SETTINGS
#define CONFIG_EXTRA_ENV_SETTINGS \
"scriptaddr=0x20000\0" \
"script_size_f=0x40000\0" \
"fdt_addr_r=0x1f00000\0" \
"pxefile_addr_r=0x2000000\0" \
"kernel_addr_r=0x2000000\0" \
"scriptaddr=0x3000000\0" \
"ramdisk_addr_r=0x3100000\0" \
BOOTENV \             //↓bootcmdを上書きする
"bootcmd=fatload mmc 0 0x03000000 uImage && fatload mmc 0 0x02A00000 devicetree.dtb && bootm 0x03000000 - 0x02A00000\0" 
#endif

後はmakeをやり直します。

10.最後に

本記事はなひたふ氏の著書「ZYNQで実用的なシステムを構築するための本」を参考に実践した内容です。本記事では一部しか内容を取り上げていません。もっとディープな内容がほしい方は是非買ってみてください。

11.(参考)Dockerfile

本環境で使用しているUbuntu20.04のコンテナイメージです。一般ユーザ作成とsudo実行権限を許可しています。
また、ubootビルド、linuxビルド、デバイスツリービルドに必要なパッケージも予めインストールするようにしています。

ABOUT ME
sh-goto
組込エンジニア. 最近の遊びはLinuxの低レイヤいじりとXilinxのZynqとFPGAを使った電子工作
関連記事