1500円ZYNQ基板でNANDブートの実現

#はじめに
1500円 ZYNQ 基板(EBAZ4205)で、自作 PetaLinux ブートイメージを NAND フラッシュメモリに書き込んで、起動する方法を解説します。

EBAZ4205 には、マイニング装置の Linux ブートイメージが書き込まれています。
最初の動作テストには使えますが、実用には向きません。
自分で作成した PetaLinux ブートイメージで NAND から起動できると、やりたいことはなんでもできるようになります。

前回作成した microSD 用の PetaLinux ブートイメージは、NAND フラッシュからのブートにも使えます。
実際に NAND メモリに書き込みを行い、起動してみます。

ブートイメージ作成方法は、QSPI と同じですので、QSPI ブートにも応用できます。


#NAND にブートイメージを書く理由
ブートストレージが microSD だと、経年劣化で接触不良を起こす恐れがあります。
(端子の汚れや酸化、端子バネの弾力性の喪失など)

長期使用される組込機器では、基板に直接はんだづけするメモリの方が、信頼性が高いです。
ZYNQ では、直実装型のメモリとして eMMC、SPI フラッシュ、NAND フラッシュが使用できます。

EBAZ4205 には 1 G-bit (128 MB) の NAND フラッシュが搭載されています。
ブートイメージを NAND フラッシュに書き込めれば、長期的な信頼性を確保できます。

また、PetaLinux では、デフォルトで rootfs が RAM 上に展開されます。
microSD や NAND へアクセスするのは、起動時の読み出しの時だけで、書き込みは行いません。
電源はいつでもブチ切り可能です。

使っているうちに、フラッシュメモリの書込み可能回数を超えて破損するようなこともありません。

なお、ブートデバイスとして QSPI フラッシュを搭載している ZYNQ 基板の方が、一般的ではないかと思います。
EBAZ4205 では搭載されていませんが、ZYBO や Xilinx 評価基板には QSPI フラッシュが搭載されています。
(QSPI の方が、基板面積と MIO ピン使用数を節約できる代わりに、部品単価が高い)

#使用環境

1. Windows10 Pro (20H2)
2. [前々回の記事](https://qiita.com/kan573/items/3da286f598b696f38cc3)でインストールした VirtiualBox + Ubuntu 18.04.5 + PetaLinux 2020.1 環境
3. Vitis 2020.1 (同上)
4. EBAZ4205 (25MHz 水晶 有り/無しどちらでも可、microSD ソケットつき)

#参考資料
UG1165 - Zynq-7000 SoC: エンベデッド デザイン チュートリアル (v2020.2)
https://xilinx.github.io/Embedded-Design-Tutorials/master/docs/Introduction/Zynq7000-EDT/7-linux-booting-debug.html
UG1144 - PetaLinux ツール資料リファレンス ガイド (日本語版) (v2019.2)
UG1144 - PetaLinux Tools Documentation: Reference Guide (v2020.1)


#作業の流れ
microSD でのブートでは 3 つのファイルを作成して、ファイルコピーで microSD に書き込んでいました。
NAND 用は、メモリにベタ書き込みする単一のバイナリファイルを作成します。

ファイルは、PetaLinux ツールがビルドしたフォルダから取ってきます。
これを Vitis 2020.1 の Create Boot Image ツールで合体させて、バイナリファイルを作成します。

作成したバイナリの NAND への書込みは、Vitis から Program Flash ツールでやるのが第一の方法です。
しかし、115.2K のシリアルで 70 MB を転送する事になるので、恐ろしく時間がかかります。
(書き込みだけで30分ほど。ベリファイまでやるともっと長い)

microSD に書いておいて、PetaLinux のコマンドで直接書き込めば、一瞬で終わります。
手っ取り早くできる、この方法でやることにします。

#NAND 起動用 ブートイメージの作成

microSD から起動可能な PetaLinux を構築済みのところから、作業をスタートします。
まだの方は、以前の記事 [1500円ZYNQ基板でPetaLinuxを動作させる(後編:PetaLinux ビルドと EBAZ4205 での動作)](https://qiita.com/kan573/items/98f364eec46cb3842d79) の作業を実施して、構築してください。

最初に投稿した時の設定では、FSBL から NAND が認識されなかったため、NAND のタイミング設定を変えています。

以前に PetaLinux ビルドされた方も、ハードウェア情報を更新して、再度ビルドしてください。
再ビルドなら、そんなに時間はかかりません。


NAND タイミングを修正してエクスポートしたハードウェア情報 ebaz4205_wrapper.xsa

https://drive.google.com/file/d/1e0OfOAcd2wyCLCnepdqKCaoaNiCeQ87G/view?usp=sharing

##1. FSBL の作成
PetaLinux Tools 2018.3 以降から、ビルド時に zynq_fsbl.elf のコンパイルと更新が行われず、Pre-Built な zynq_fsbl.elf がそのまま使われてしまいます。
ビルドすると zynq_fsbl.elf のタイムスタンプは更新されますが、md5sum は何をやっても変わりません。

UG1144 (2018.2) までは、
Generating Boot Components - First Stage Bootloader
のところに、下記の記載がありました。

>This operation will generate the First Stage Bootloader (FSBL) source into components/bootloader/ inside your PetaLinux project root directory, if it does not already exist. 
>
> The directory for Zynq-7000 is as below
> components/plnx_workspace/fsbl/fsbl/zynq_fsbl

UG1144 (2018.3) 以降では削除されていることから、__FSBL は Vitis で作成して、PetaLinux に持ち込む__ 方針に変わっています。(PetaLinux ツールでは新規の FSBL が作れない)

ebaz4205_wrapper.xsa の情報を取り込んだ FSBL を新規作成して組み込まないと、EBAZ4205 の NAND が認識されないため、ブートしてもうんともすんとも言いません。

下記手順で、新しく FSBL を作成します。

・Vitis 2020.1 を起動する
・Create Application Project から、Create a new platfrom from hardware (XSA)を選択し、ebaz4205_wrapper.xsa を指定
・Application Project name は NAND_FSBL とする
・Templates で Zynq FSBL を選んで Finish

![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/cae5a971-7979-e8c7-f8da-28bebeff3c41.png)


新規で Platform Project と Application Project が作成されました。
特に変更するところはありませんので、このままビルドします。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/24234667-bbd9-c3eb-e2bd-0f3fb170bc6e.png)


ビルド後、NAND_FSBL.ELF が生成されますので、場所を確認しておきます。

アプリケーションプロジェクトの Binaries の下に NAND_FSBL.elf があり、右クリックでプロパティを表示すると Location がわかります。
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/9c8ef033-7263-2217-198c-d208c4e5d3c9.png)


作成された NAND_FSBL.elf を、Ubuntu との共有フォルダ(\desktop\share)にコピーしておきます。


##2. boot.scr の変更
PetaLinux Tools (2020.1) が生成する boot.scr は、NAND からの起動に対応していませんので、NAND 起動の処理を追加します。
変更後の boot.scr は、microSD 用にもそのまま使えます。

VirtualBox から PetaLinux 環境の Ubuntu を起動して、端末を開く(E) でターミナルを開きます。

変更点は、下記 2 点です。
・L12 の imageub_addr= のアドレスを 0x1000_0000 から 0x0100_0000 へ変更する (EBAZ4205 の搭載メモリ量の都合)
・末尾に nand 起動処理を追加する

>$ vi ~/ebaz4205_test1/project-spec/meta-user/recipes-bsp/u-boot/u-boot-zynq-scr/boot.cmd.default


```boot.cmd.default
(前略)

imageub_addr=0x01000000

(中略)

	if test "${boot_target}" = "nand" || test "${boot_target}" = "nand0"; then
		nand info
		if test "image.ub" = "image.ub"; then
			nand read ${imageub_addr} 0x01000000 0x04000000;
			bootm ${imageub_addr};
			exit;
		fi
	fi
done

```


##3. 必要なファイルのコピー
先に作成した NAND_FSBL.elf に加えて、必要なファイル 3 つを、Windows との共有フォルダ( /media/sf_share )にコピーします。
boot.scr は、コンパイルして生成します。

>\$ cp ~/ebaz4205_test1/images/linux/system.bit /media/sf_share
>\$ cp ~/ebaz4205_test1/images/linux/u-boot.elf /media/sf_share
>\$ cp ~/ebaz4205_test1/images/linux/image.ub /media/sf_share

>\$ mkimage -c none -A arm -T script -d ~/ebaz4205_test1/project-spec/meta-user/recipes-bsp/u-boot/u-boot-zynq-scr/boot.cmd.default /media/sf_share/boot.scr


##4. NAND 書込みイメージの作成

Vitis IDE を起動します。

プロジェクトは開かずに、ツールバーから Xilinx - Create Boot Image を起動します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/6b51b68b-4d33-dcb4-f16e-222f3726556f.png)

上段の項目は、下記を設定します。

>Architecture: Zynq
>Create new BIF file
>Output BIF file path: (output.bif = ファイル登録情報の出力先)
>UDF data: (空欄)
>Split: チェック無し
>Output format: BIN
>Output path: (ブートイメージ BOOT_NAND.bin の出力先)

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/d6d3b4b5-f8fb-19cd-1f6a-4f6f1a8d89be.png)


下段は、必要なファイルを登録します。

UG1165 では、ファイルは下記のように配置されています。
これは、QSPI メモリの大きさが 16 MB、image.ub (FITイメージ)の大きさが 11 MB の時の配置例です。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/df259893-9518-f9ad-fa3c-e841c42fcbae.png)


boot.scr は offset 0x00FC0000 になっていて、fsbl からの呼び出し位置が 0xFC0000 で決め打ちされています。
前記事で microSD 用に作成した image.ub は 55 MB あるので、例のまま 0x520000 に置くと、後ろの boot.scr と被ってしまいます。

そこで、image.ub を boot.scr よりも後の、0x1000000～ に配置します。


登録する順番は、下記の通りにします。
各登録情報は、()指定のところだけ変更し、それ以外はデフォルトのままでよいです。

1. NAND_FSBL.elf (Partition type: bootloader)
2. system.bit
3. u-boot.elf
4. boot.scr (Offset: 0xfc0000)
5. image.ub (Offset: 0x1000000)

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/5c9af3d6-4a5c-4975-a602-55b319e735f7.png)



準備ができたら、Create Image ボタンを押します。
(やり直したい時は、Import from existing BIF file で output.bif を読み込むと、出力時の登録情報が呼び出せます)

これで、NAND/QSPI 書き込み用のブートイメージ BOOT_NAND.bin が作成できました。
EBAZ4205 起動用の microSD カードに、BOOT_NAND.bin をコピーしておきます。


とりあえず NAND に書いて試してみる用に、作成したファイルを下記に置いておきます。

https://drive.google.com/file/d/1_OYSLhidtBTWX3jeCpH2vODiX1Rf0r_9/view?usp=sharing

#NAND フラッシュへの書込み

※最初に書いてあったマイニング用のブートイメージは消えてしまいます。
　必要ならバックアップを取っておいてください。
　u-boot で丸ごと DDR に読み出して、microSD に書くことができます。

EBAZ4205 を microSD で起動したら、NAND のフラッシュ(消去)と、書き込みを実施します。

>\$ flash_eraseall /dev/mtd0
>\$ nandwrite -p /dev/mtd0 /media/sd-mmcblk0p1/BOOT_NAND.bin

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/517b9fd0-f873-d4f6-da8b-8649f11a1219.png)

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/bed6c436-a65d-4b64-a462-d4da58803f7d.png)

#NAND フラッシュから起動

microSD/NAND 切り替えスイッチを NAND 側にして、リセットボタンを押します。
(または、電源の再投入)

うまく NAND から起動できたら、完成です。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/6c1ff4b4-deb0-44a5-0208-b02676047232.png)

#FSBL のデバッグモード有効化
起動してもうんともすんとも言わず、PL のコンフィグ完了を知らせる LED1 も光らない場合は、FSBL がエラーを出して停止しています。

デフォルトだと画面に何も表示されないまま固まるので、ただハングしているようにしか見えません。
デバッグモードを有効にして FSBL をコンパイルすると、エラーが表示されるので、どこで止まっているかが分かります。

Vitis の Application Project のソースのうち、fsbl_debug.h の適当なところに、

>\#define FSBL_DEBUG_INFO

を追加すると、デバッグモードを有効にしてコンパイルできます。
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/afe440a1-caf1-4b8b-ea01-3d03930077af.png)


これで作成した NAND_FSBL.elf を組み込むと、FSBL のログが表示されるので、エラーの原因がわかります。

下記は、デバッグモードの FSBL から起動した例です。
U-boot のログの前に、FSBL のログが表示されています。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/88c51dd5-72b3-b1c1-2ae0-ec477b6a9f76.png)


#まとめ
EBAZ4205 で NAND ブートを実現することができました。

今回の例では、128 MB ある NAND フラッシュのうち、70MB 程度を利用しています。
/dev/mtd0, /dev/mtd1 でパーティションを設定して、空いている後半をストレージとして利用することもできますので、試してみてください。