もくじ
- はじめに
- 1. ブートローダーの変更およびビルド: .dts ファイルの変更
- 2. ブートローダーおよびコンフィグデータの書き込み: QSPI フラッシュへの格納
- 3. コンフィグ実行: U-Boot コマンドによる動作確認
- 4. 補足: U-Boot ソースコードへの記述追加(ブートローダーへの設定埋め込み)
- おわりに
はじめに
この記事では、Cyclone® V SoC / Arria® V SoC で QSPI ブートを行う際に、U-Boot から FPGA 側のコンフィグレーションを行うための環境構築方法を紹介します。
注記: この記事は SoC EDS v19.1 以降(SoC EDS に U-Boot が付属しない環境)向けです。
QSPI ブート向けのブートローダー生成に関する公式手順は、Building Bootloader for Cyclone V and Arria 10 | Documentation | RocketBoards.org の「Cyclone V SoC - Boot from QSPI」に記載されます。しかしながら、FPGA 側のコンフィグレーションは HPS (Hard Processor System) のブートとは独立して実行するフローを前提とした内容になっており、U-Boot から FPGA のコンフィグレーションを行うための方法について記載がありません。
そこで、この記事では QSPI ブート時に U-Boot から FPGA コンフィグレーションを行う方法についての補足情報を示します。
なお、この記事執筆時の動作確認環境としては、以下のものを使用しています。
【表 1】 動作確認環境
項番 | 項目 | 内容 |
1 | 開発ツール |
① Quartus® Prime v21.1 Standard Edition ② SoC EDS v20.1 Standard Edition ③ ブートローダーを生成するためには、Linux OS が起動するホストマシンの用意が必要です。通常は以下のいずれかの環境を使用します。*1 Linux OS としては、Building Bootloader for Cyclone V and Arria 10 の |
2 | リファレンス・デザイン | QPDS-22.1pro-21.1std.zip |
3 | U-Boot Branch | u-boot-socfpga_v2022.04 |
4 | Linux Branch | linux-socfpga-5.15.60-lts |
5 | ツールチェーン | gcc-arm-11.2-2022.02-x86_64-arm-none-linux-gnueabihf |
注記:
*1. ブートローダーのビルド以外に、Yocto Project を使用してターゲット Linux 環境のビルドも行う 予定がある場合は 1) か 3) で対応ください。Yocto Project は WSL 非対応です。
*2. WSL 環境の構築については以下のコンテンツをご参照ください。
WSL で Preloader / U-Boot をビルドしてみる 【その 1】 環境セットアップ編
1. ブートローダーの変更およびビルド: .dts ファイルの変更
この章では、.dts ファイルに FPGA コンフィグレーション・データを格納するパーテーションを追記する方法について説明します。
Cyclone® V SoC 開発キット向け U-Boot デバイスツリー・ソース(.dts)ファイルのデフォルトの状態では、ブートローダーと Linux のパーテーションのみが定義されています。ここに、FPGA コンフィグレーション・データ格納用のパーテーションを追加する必要があります。
1-1. U-Boot ソースツリーの取得およびハンドオフ情報の反映
.dts ファイルの変更を行う前に、「Cyclone V SoC - Boot from QSPI」の “B. U-Boot” の手順を、先頭から qts-filter.sh を実行する所まで(【図 1】の赤枠)の手順を予め実行しておきます。
【図 1】 Cyclone V SoC - Boot from QSPI の “B. U-Boot” の説明
1-2. デバイスツリーの編集(QSPI Flash 用の定義にパーテーションを追加)
FPGA コンフィグレーション・データ格納用のパーテーションを U-Boot ソースツリーの .dts ファイルに追記します。
【Cyclone® V SoC 開発キットの対象 .dts ファイル】
-
- u-boot-socfpga/arch/arm/dts/socfpga_cyclone5_socdk.dts
- u-boot-socfpga/arch/arm/dts/socfpga_cyclone5_socdk-u-boot.dtsi
【Arria® V SoC 開発キットの対象 .dts ファイル】
-
- u-boot-socfpga/arch/arm/dts/socfpga_arria5_socdk.dts
- u-boot-socfpga/arch/arm/dts/socfpga_arria5_socdk-u-boot.dtsi
【図 2】 .dts ファイルの変更
メモ: U-Boot ソースツリーに含まれる socfpga_arria5_socdk-u-boot.dtsi には QSPI フラッシュのパーテーション定義の記述がありません。Cyclone® V SoC 開発キット用のファイルに倣って、FPGA コンフィグレーション・データ格納用以外のパーテーションも全て記述してください。
メモ: Arria® V SoC 開発キットの場合は、qspi-rootfs パーテーションへの割り当てサイズをデフォルトの 120MB から 112MB に変更し、FPGA Image 格納用のパーテーションとして、qspi-fpga をスタートアドレス 0x7800000 から 8MByte サイズ分の定義を追加してお試しいただくのがよろしいかと思います。
参考: Cyclone® V SoC / Arria® V SoC 開発キットの QSPI メモリーサイズは以下の通りです。
- Cyclone® V SoC 開発キット ⇒ 64 MByte (512 Mbit)
Cyclone® V SoC FPGA Development Board Reference Manual
【図 3】 Cyclone® V SoC 開発キットの QSPI メモリーサイズ
- Arria® V SoC 開発キット ⇒ 128 MByte (1 Gbit)
Arria® V SoC FPGA Development Board Reference Manual
【図 4】 Arria® V SoC 開発キットの QSPI メモリーサイズ
1-3. U-Boot バイナリーのビルド
.dts ファイルの修正が終わったらファイルをセーブして、「Cyclone V SoC - Boot from QSPI」の “B. U-Boot” の続きの手順を実行して、U-Boot バイナリ―のビルドを行います。
【図 5】 U-Boot バイナリ―のビルド
参考: 使用されるデバイスツリー blob(.dtb)ファイルは、defconfig ファイル内で指定される CONFIG_DEFAULT_DEVICE_TREE と CONFIG_DEFAULT_FDT_FILE の定義によって選択されます。
【Cyclone® V SoC 開発キットの場合】
● u-boot-socfpga/configs/socfpga_cyclone5_defconfig の例
【図 6】 socfpga_cyclone5_defconfig の例
● u-boot-socfpga/configs/socfpga_cyclone5_qspi_defconfig の例
【図 7】 socfpga_cyclone5_qspi_defconfig の例
Arria® V SoC 開発キットの場合も、u-boot-socfpga/configs/socfpga_arria5_defconfig ファイルの中に同様の記述があります。
2. ブートローダーおよびコンフィグデータの書き込み: QSPI フラッシュへの格納
この章では、.dts ファイルに定義した QSPI フラッシュの FPGA コンフィグレーション・パーテーションに、FPGA コンフィグレーション・データを書き込みます。
参考: 「Cyclone V SoC - Boot from QSPI」ならびに、この記事のコマンド例では、Nios II Command Shell を使用していますが、SoC Embedded Command Shell でも対応可能です。必要に応じて以下のコマンドを置き換えて対応してください。
- ~/intelFPGA/21.1/nios2eds/nios2_command_shell.sh(Nios II Command Shell)
- ~/intelFPGA/20.1/embedded/embedded_command_shell.sh(SoC Embedded Command Shell)
2-1. FPGA コンフィグデータの生成
FPGA コンフィグレーション・データは、quartus_cpf コマンドライン・ユーティリティーを使用して、.sof(SRAM Object File)から .rbf(RAW Binary File)を生成します。
「Cyclone V SoC - Boot from QSPI」の "A. Setup" の手順(make sof)を実施すると、cv_soc_devkit_ghrd/output_files ディレクトリー下に soc_system.sof ファイルが生成されます。このファイルを soc_system.rbf に変換します。
【図 8】 ハードウェア・デザインのコンパイル
方法としては以下の2通りがあります:
a)make sof コマンド実行後、以下の make rbf コマンドを実行することによって、Makefile 内の指示
により soc_system.rbf ファイルを生成します。
cd cv_soc_devkit_ghrd
~/intelFPGA/21.1/nios2eds/nios2_command_shell.sh \
make rbf
b)以下の quartus_cpf コマンドラインにより、soc_system.sof を soc_system.rbf に変換します。
-c オプションはファイル変換(convert)することを示します。
-o bitstream_compression=on オプションは圧縮された .rbf ファイルを生成することを示します。
cd cv_soc_devkit_ghrd
~/intelFPGA/21.1/nios2eds/nios2_command_shell.sh \
quartus_cpf -c -o bitstream_compression=on output_files/soc_system.sof output_files/soc_system.rbf
参考: FAQ: Quartus II の GUI を使用せずに SOF ファイル を RBF ファイルへ変換する方法があれば教えてください。
2-2. QSPI フラッシュへの格納
2-2-1. 書き込み対象ファイルを作業ディレクトリーへコピー
「Cyclone V SoC - Boot from QSPI」 “C. QSPI Binaries” の Create qspi_bin folder and bring all the files: を参考に soc_system.rbf ファイルを $TOP_FOLDER/qspi_bin ディレクトリーにコピーします。
【図 9】 $TOP_FOLDER/qspi_bin ディレクトリーの作成およびファイルコピー
下記赤文字のコマンドを追加することで soc_system.rbf ファイルを qspi_bin ディレクトリーにコピーします。
cd $TOP_FOLDER/
sudo rm -rf qspi_bin && mkdir qspi_bin && cd qspi_bin
cp ../cv_soc_devkit_ghrd/software/bootloader/u-boot-socfpga/u-boot-with-spl.sfp .
cp ../cv_soc_devkit_ghrd/output_files/soc_system.rbf .
cp $LINUX_BIN/a9/zImage .
cp $LINUX_BIN/a9/socfpga_cyclone5_socdk.dtb .
目次へもどる
2-2-2. QSPI フラッシュへの書き込み
「Cyclone V SoC - Boot from QSPI」の “D. Boot” の Flash the QSPI binaries: の説明を参考に quartus_hps ツールで各種バイナリーファイルを QSPI フラッシュメモリーに書き込みます。
書き込みの際、FPGA コンフィグレーション・データである soc_system.rbf ファイルは、『1. ブートローダーの変更およびビルド: .dts ファイルの変更』の章で変更した、FPGA コンフィグレーション・データ格納用パーテーションのスタートアドレスを指定して書き込みます(この記事の説明では、Cyclone® V SoC 開発キットの場合を例として、0x3C00000 番地に書き込みを行っています)。
【図 10】 QSPI フラッシュへのバイナリーファイルの書き込み
下表の赤枠部分が示すように、Cyclone® V SoC 開発キットを例とした場合は、0x3C00000 番地に FPGA コンフィグレーション・データを書き込むことになります。
【図 11】 QSPI フラッシュへ書き込むデータのアドレスマップ
Cyclone® V SoC 開発キットの場合は、BSEL ジャンパーを 3.3V QSPI デバイスから起動するように次のように設定します。
-
-
- BSEL2=1 (left)
- BSEL1=1 (left)
- BSEL0=1 (left)
-
その後、下記の赤文字箇所のコマンドに注目して QSPI フラッシュメモリーの 0x3C00000 番地に FPGA コンフィグレーション・データである soc_system.rbf ファイルを書き込みます。
cd $TOP_FOLDER/qspi_bin
~/intelFPGA/21.1/nios2eds/nios2_command_shell.sh quartus_hps -c 1 -o pv -a 0x00000000 u-boot-with-spl.sfp
~/intelFPGA/21.1/nios2eds/nios2_command_shell.sh quartus_hps -c 1 -o pv -a 0x00220000 socfpga_cyclone5_socdk.dtb
~/intelFPGA/21.1/nios2eds/nios2_command_shell.sh quartus_hps -c 1 -o pv -a 0x00230000 zImage
~/intelFPGA/21.1/nios2eds/nios2_command_shell.sh quartus_hps -c 1 -o pv -a 0x00800000 core-image-minimal-cyclone5-rootfs.jffs2
~/intelFPGA/22.1/nios2eds/nios2_command_shell.sh quartus_hps -c 1 -o pv -a 0x03C00000 soc_system.rbf
注記: soc_system.rbf などサイズの大きいファイルの書き込みには時間がかかります。
参考: 以下のコマンドにより QSPI フラッシュを全消去することが可能です。
~/intelFPGA/21.1/nios2eds/nios2_command_shell.sh quartus_hps -c 1 -o E
3. コンフィグ実行: U-Boot コマンドによる動作確認
この章では、Cyclone® V SoC 開発キットで、QSPI ブートにおける U-Boot コマンドを使用した FPGA コンフィグレーションの動作を確認してみます。
参考: FPGA をコンフィグレーションする際に使用する U-Boot のコマンドとしては、以下のようなものがあります。
● QSPI から RAM にデータを読み出すコマンド(sf probe、sf read)
sf probe は指定された SPI バスおよびチップセレクトでフラッシュデバイスを初期化します。
sf read は 'offset' で始まる 'len' バイトまたは mtd 'partition' の開始から 'addr' のメモリに読み取ります。
【図 12】 U-Boot の sf コマンド
● RAM バッファから FPGA デバイスをロードするコマンド(fpga load)
fpga load は RAM 上にある FPGA コンフィグレーション・データを FPGA デバイスにロードします。
【図 13】 U-Boot の fpga コマンド
3-1. U-Boot 環境変数の確認
まず初めに U-Boot の printenv コマンドを使用して、現在の U-Boot 環境変数の内容を確認してみます。下記の黄色文字の箇所がブートに関連している環境変数です。
【図 14】 U-Boot の printenv コマンドによる U-Boot 環境変数の確認
上の図のブート関連環境変数において、
-
- bootcmd がブートの開始点で、bridge enable コマンドと run bootcmd_qspi を実行しています。
- bootcmd_qspi では、run qspiload と run qspiboot を実行しています。
- qspiload では、sf probe コマンドにより QSPI フラッシュデバイスを初期化し、sf read コマンドにより QSPI フラッシュに格納されている Linux Kernel と Root Filesystem(jffs2)を RAM 上に読み出しています。
- qspiboot では、RAM 上に展開されたデータを使用して、Linux をブートしています。
3-2. U-boot 環境変数の編集
U-Boot のプロンプトから以下のような赤文字で示したコマンドを入力して、FPGA のコンフィグレーションを実行するように、U-Boot の環境変数に qspifpga を追加し、bootcmd_qspi から run qspifpga を実行するように setenv コマンドで設定します。
設定が終わったら saveenv コマンドで設定した内容を U-Boot の環境変数に保存します。
=> setenv qspifpga sf probe\; sf read 0x4000000 0x03C00000 0x400000\; fpga load 0 0x4000000 0x400000\;
=> setenv bootcmd_qspi run qspifpga\; run qspiload\; run qspiboot\;
=> saveenv
Saving Environment to SPIFlash... Erasing SPI flash...Writing to SPI flash...done
Valid environment: 2
OK
=>
ここで再度 U-Boot の printenv コマンドを使用して環境変数の内容を確認してみると、緑色文字の箇所のように、qspifpga が追加され、bootcmd_qspi から run qspifpga が実行されるように設定されているはずです。
【図 15】 U-Boot 環境変数変更後の printenv
3-3. 動作確認(ブート実行)
U-Boot の環境変数に FPGA コンフィグレーションの記述が正しく設定されていることを確認したら、boot コマンドまたは電源の再投入により U-Boot から FPGA がコンフィグレーションされることを確認します。下図では boot コマンドを実行しています。
下図の黄色文字の部分が、FPGA コンフィグレーション・データを QSPI の 0x3C00000 番地から RAM 上へ展開して FPGA にロードしている部分になります。
緑色文字の部分は、Linux Kernel イメージ(zImage)ファイルを QSPI の 0x0230000 番地から RAM 上へ展開している部分になります。
青色文字の部分は、Linux device tree(socfpga_cyclone5_socdk.dtb)を QSPI の 0x0220000 番地から RAM 上へ展開している部分になります。
最終的には Linux が起動するような流れとなっています。
【図 16】 boot コマンドによる起動と FPGA コンフィグレーションの確認
4. 補足: U-Boot ソースコードへの記述追加(ブートローダーへの設定埋め込み)
前章の説明では、U-boot のコマンドプロンプトから setenv / saveenv コマンドを使用して、U-boot の環境変数に追加して FPGA コンフィグレーションを実行する方法を説明しましたが、socfpga_common.h および socfpga_arria5_socdk.h ファイル内に FPGA コンフィグレーションの仕組みを追記して U-boot を生成する方が恒久的な対応としては良いかもしれません。
4-1. U-Boot での Cyclone® V SoC QSPI ブートの仕組み
ここではまず U-Boot ソースコードにおけるデフォルトでの Cyclone® V SoC 開発キット QSPI ブートの仕組みを説明します。
- u-boot-socfpga/configs/socfpga_cyclone5_qspi_defconfig ファイル内では、CONFIG_BOOTCOMMAND として以下のように記述されています。これにより HPS - FPGA 間のブリッジを開通し、bootcmd_qspi を実行しています。
【図 17】socfpga_cyclone5_qspi_defconfig ファイル内の CONFIG_BOOTCOMMAND 定義
- u-boot-socfpga/include/configs/socfpga_common.h ファイル内では、BOOTENV_DEV_QSPI として以下のように記述されています。これにより bootcmd_qspi は qspiload と qspiboot を実行します。
【図 18】 socfpga_common.h ファイル内の BOOTENV_DEV_QSPI 定義
- u-boot-socfpga/include/configs/socfpga_cyclone5_socdk.h ファイル内では、qspiload と qspiboot が以下のように記述されています。これにより QSPI 内に置かれている Linux カーネルと root ファイルシステムを RAM 上に展開して実行します。
【図 19】 socfpga_cyclone5_socdk.h ファイル内の qspiload と qspiboot の定義
4-2. ヘッダーファイルへの FPGA コンフィグ記述の追加
前項で説明した socfpga_common.h と socfpga_cyclone5_socdk.h ファイルへの、FPGA コンフィグレーション記述の追加を行ってみます。
はじめに、u-boot-socfpga/include/configs/socfpga_common.h ファイルに対して run qspifpga; の記述を追加します(赤文字箇所)。
#define BOOTENV_DEV_QSPI(devtypeu, devtypel, instance) \
"bootcmd_qspi=run qspifpga; run qspiload; run qspiboot\0"
続けて、u-boot-socfpga/include/configs/socfpga_cyclone5_socdk.h ファイルに対して FPGA コンフィグレーションの記述を追加します(赤文字箇所)。
/* QSPI boot */
#define QSPI_FPGA_ADDR __stringify(0x03C00000)
#define FPGA_SIZE __stringify(0x00400000)
#define FPGA_LOAD_ADDR __stringify(0x04000000)
#define FDT_SIZE __stringify(0x00010000)
#define KERNEL_SIZE __stringify(0x005d0000)
#define QSPI_FDT_ADDR __stringify(0x00220000)
#define QSPI_KERNEL_ADDR __stringify(0x00230000)
#define SOCFPGA_BOOT_SETTINGS \
"qspifpgaaddr=" QSPI_FPGA_ADDR "\0" \
"qspiloadcs=0\0" \
"fpgadatasize=" FPGA_SIZE "\0" \
"fpgaloadaddr=" FPGA_LOAD_ADDR "\0" \
"qspifpga=sf probe; " \
"sf read ${fpgaloadaddr} ${qspifpgaaddr} ${fpgadatasize}; " \
"fpga load ${qspiloadcs} ${fpgaloadaddr} ${fpgadatasize}\0"
"fdt_size=" FDT_SIZE "\0" \
"kernel_size=" KERNEL_SIZE "\0" \
"qspi_fdt_addr=" QSPI_FDT_ADDR "\0" \
"qspi_kernel_addr=" QSPI_KERNEL_ADDR "\0" \
"qspiboot=setenv bootargs earlycon " \
"root=/dev/mtdblock1 rw rootfstype=jffs2; " \
"bootz ${kernel_addr_r} - ${fdt_addr_r}\0" \
"qspiload=sf probe; " \
"sf read ${kernel_addr_r} ${qspi_kernel_addr} ${kernel_size}; " \
"sf read ${fdt_addr_r} ${qspi_fdt_addr} ${fdt_size}\0"
変更した socfpga_common.h と socfpga_cyclone5_socdk.h ファイルを使用して U-boot を再生成します。その後 U-boot により FPGA コンフィグレーションが実行されるかを確認します。
おわりに
この記事では、Rocketboards.org の "Building Bootloader for Cyclone V and Arria 10" のページにおける、QSPI ブート時 の U-Boot から FPGA コンフィグレーションを行う方法についての捕捉情報を説明しました。
QSPI からブートする際の FPGA コンフィグレーションの参考にしていただければ幸いです。
コメント
0件のコメント
記事コメントは受け付けていません。