1.記事一覧
記事は複数回に分けて投稿します。Zynq7020SoCで動作する、YoctoベースのPetaLinuxを使わない素のLinuxを構築します。
エッジArm Linux構築編(armv7l)
- 【Zynq7】Yoctoを使わずに素のLinuxをソースから構築する
- 【Zynq7】1.FSBL(1stStageBootLoader)の構築
- 【Zynq7】2.U-bootの構築 ←本ページ
- 【Zynq7】3.Linuxカーネルの構築
- 【Zynq7】4.Zyboz7ボードのデバイスツリー構築
- 【Zynq7】5.RootFSのマウント(Ubuntu18.04)
- 【Zynq7】6.カーネルモジュールの配置
- 【Zynq7】番外編1.u-bootが途中で止まる問題
- 【Zynq7】番外編2.MACアドレスをQSPIFlashから読み出して設定する
エッジArm Linux実践編(armv7l)
- 【Zynq7】実践1. LinuxにRTCを認識させる【I2Cデバイス】
- 【Zynq7】実践2. 温度センサをPython+Dockerで使う【I2Cデバイス】
- 【Zynq7】実践3. 組込みLinuxでコンテナ導入に苦労した話【Docker Engine編】
- 【Zynq7】実践4. LinuxでSPIを使う【液晶編1】
- 【Zynq7】実践5. ZynqPLのGPIOをLinuxで使う【液晶編2】
- 【Zynq7】実践6. PythonでSPI液晶を使う【液晶編3】
- 【Zynq7】閑話. SPI バス周波数が上がらない問題
2.環境
開発PC | Ubuntu20.04, intel core i5 750 RAM 16G |
Docker | Docker Engine v23.0.0, Ubuntu20.04 base image |
ターゲットボード | Digilent Zybo z7-20 Rev.B.2(XC7Z020-1CLG400C, DDR3 1GB) |
u-boot | XilinxがGithubで提供するソースを使用。tag=xilinx-v2022.2 u-boot 2022.01 https://github.com/Xilinx/u-boot-xlnx/tree/xilinx-v2022.2 |
bootgen | bootパーティションに配置する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はページ最後に記載
$ ls
Dockerfile
# docker build例
$ docker image build ./ -t ub2004/sample
コンテナ起動例:開発ホストPCのworkフォルダを共有フォルダに設定して、コンテナ上から操作できるようにします。
$ docker run -v "/home/ホストのユーザ名/work/:/home/share" --name "buildzynqlinux" -it "ub2004/sample" /bin/bash
3-2. ビルドパッケージのインストール
$ sudo apt install build-essential libssl-dev bison flex git gcc-arm-linux-gnueabihf
3-3. bootgenコマンドのビルドとインストール
$ 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)
$ export CROSS_COMPILE=arm-linux-gnueabihf-
$ export ARCH=arm #<-- make時に指定しても良い
4.u-bootのビルド確認
4-1. Xilinx社のGithubよりu-bootのソースコードをclone
$ 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によるビルド確認
環境構築がうまく行けばビルド通ります。
$ 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ファイルをコピーします。
$ 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設定内容」で決めたファイル名です。
$ 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)を探し、末尾に付け足します。
変更前
...
zynq-zybo.dtb \
zynq-zybo-z7.dtb
dtb-$(CONFIG_ARCH_ZYNQMP) += \
...
変更後
...
zynq-zybo.dtb \
zynq-zybo-z7.dtb \
zynq-myboard.dtb #<--追加
dtb-$(CONFIG_ARCH_ZYNQMP) += \
...
拡張子が.dtbになっていますがこれはデバイスツリーソースファイル(.dts)をコンパイルしたデバイスツリーblobファイル(.dtb)のことです。
7-2. ビルド
フォルダを”u-boot-xlnx”直下に移動してビルドします。
$ 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の作成
以下コマンドを実行します。
$ 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”マクロ定義に追加します。
#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ビルド、デバイスツリービルドに必要なパッケージも予めインストールするようにしています。