DE0-Nano-SoC用ベアメタルアプリとFPGAコンフィギュレーション

FPGA

DE0-Nano-SoCのベアメタルアプリをSDカードからブートするとき、FPGAのコンフィギュレーションも同時に行う場合の手順です。

ベアメタルアプリとFPGAコンフィギュレーション

FPGAのコンフィギュレーションは、HPSでFPGAのデータをFPGA Portionにロードすることで行います。具体的には、FPGAのデータをFPGA Portionにロードするようなプログラムを作り、通常処理の前にFPGAのコンフィギュレーションをプログラム的に行います。FPGAのコンフィギュレーション用データは、ベアメタルアプリのデータと結合して1つのバイナリにします。

FPGAコンフィギュレーションのサンプル

サンプルデータがQuartus II(SoC EDS)に格納されています。サンプルの場所はembedded/examplessoftware、ファイル名はAltera-SoCFPGA-HardwareLib-FPGA-CV-GNU.tar.gzです。このサンプルを参考に、自分のベアメタルアプリにFPGAデータのコンフィギュレーションプログラムを追加します。

プログラムの追加例

自分のベアメタルアプリのmain関数の先頭部分に、FPGAコンフィギュレーション用関数の呼びだしを追加します。この例ではfpga_configがFPGAコンフィギュレーション用の関数です。

int main(int argc, char** argv) {
  fpga_config(); // FPGAのコンフィギュレーション
  run();         // 本来のベアメタルアプリの処理
}

fpga_configの処理

FPGAデータをロードするfpga_configの処理内容は次の通りです。

  • HPSのDMAコントローラのセットアップ
  • SDカードに格納されたバイナリ中のFPGAコンフィギュレーションデータの確認
  • DMAコントローラを使ったFPGAデータのロード
  • AXIブリッジの有効化

具体的なコードは次の通りです。なお、fpga_config内で呼び出している関数socfpga_*は、Altera-SoCFPGA-HardwareLib-FPGA-CV-GNU.tar.gzに格納されているhwlib.cに定義されているものをそのまま流用しています。

void fpga_config() {

  ALT_DMA_CHANNEL_t channel;
  // DMAコントローラのセットアップ
  socfpga_dma_setup(&channel);

  // FPGAデータの確認
  extern char _binary_soc_system_rbf_start;
  extern char _binary_soc_system_rbf_end;

  // 上記シンボルでFPGAイメージを解凍
  const char *   fpga_image      = &_binary_soc_system_rbf_start;
  const uint32_t fpga_image_size = &_binary_soc_system_rbf_end - &_binary_soc_system_rbf_start;
  // FPGAデータのロード
 socfpga_fpga_setup_dma(fpga_image, fpga_image_size, channel);

  // AXIブリッジの有効化
  socfpga_bridge_setup(ALT_BRIDGE_LWH2F);   // Lightweight HPS-to-FPGA
  socfpga_bridge_setup(ALT_BRIDGE_H2F);     // HPS-to-FPGA
  socfpga_bridge_setup(ALT_BRIDGE_F2H);     // FPGA-to-HPS
}

FPGAデータのロード関数socfpga_setup_dmaの内部では、Cyclone VのMSEL[4:0]の確認とalt_fpga_configure_dma関数によるFPGAデータのロードが行われています。DE0-Nano-SoCのMSEL[4:0]の設定は、ON/OFF/ON/OFF/ON(デフォルト)に設定する必要があります。

コンパイル

コンパイルは、Altera-SoCFPGA-HardwareLib-FPGA-CV-GNU.tar.gzの格納されているMakefileが参考になります。注意点は次のとおりです。

defineの追加

ALT_FPGA_ENABLE_DMA_SUPPORTをdefineする必要があります。defineしないと、一部の関数がリンクされません。

CFLAGS  :=   -c -fmessage-length=0 -save-temps -O3  -Wall  -std=c99 $(MULTILIBFLAGS) -I$(HWLIBS_ROOT)/include -I$(HWLIBS_ROOT)/include/$(ALT_DEVICE_FAMILY) -D$(ALT_DEVICE_FAMILY) -I . -DALT_FPGA_ENABLE_DMA_SUPPORT=1

.rbfの圧縮

FPGAのコンフィギュレーションデータ(.sof)は、.rbfに変換後、さらに.oに変換してアプリケーションのバイナリとリンクします。.rbfに変換するときには、圧縮オプションを有効にする必要があります。圧縮しないとうまくロードできませんでした。

SOC_SYSTEM = ../qtproject/soc_system.sof

soc_system.rbf: $(SOC_SYSTEM)
	$(RM) cpf_option.txt
	echo bitstream_compression=on > cpf_option.txt
	quartus_cpf -c -o cpf_option.txt $< $@
	$(RM) cpf_option.txt
soc_system.o: soc_system.rbf
	$(OC) --input-target binary --output-target elf32-little --alt-machine-code 40 $< $@

実際にmakeを行うと、次のようなログが表示されます。この例ではhello-mkimage.binが最終的なバイナリです。このバイナリの中に、FPGAのコンフィギュレーションデータとベアメタルアプリが格納されています。

rm -rf cpf_option.txt
echo bitstream_compression=on > cpf_option.txt
quartus_cpf -c -o cpf_option.txt ../qtproject/soc_system.sof soc_system.rbf
Info: *******************************************************************
Info: Running Quartus II 64-Bit Convert_programming_file
    Info: Version 15.0.0 Build 145 04/22/2015 SJ Web Edition
    Info: Copyright (C) 1991-2015 Altera Corporation. All rights reserved.
:(中略)

arm-altera-eabi-objcopy --input-target binary --output-target elf32-little --alt-machine-code 40 soc_system.rbf soc_system.o
arm-altera-eabi-objcopy: this target does not support 40 alternative machine codes
arm-altera-eabi-objcopy: treating that number as an absolute e_machine value instead
arm-altera-eabi-g++ -TcycloneV-dk-ram-modified.ld -march=armv7-a -mfloat-abi=softfp -mfpu=neon-fp16  src/tex_cubes.o io.o hwlib.o alt_hps_detect.o alt_clock_manager.o alt_interrupt.o alt_globaltmr.o alt_timers.o alt_watchdog.o alt_cache.o alt_mmu.o alt_address_space.o alt_bridge_manager.o alt_dma.o alt_dma_program.o alt_fpga_manager.o ./pplib/pl_romtbl.o soc_system.o -o src/tex_cubes.axf
arm-altera-eabi-objdump -d -x src/tex_cubes.axf > src/tex_cubes.axf.objdump
arm-altera-eabi-nm src/tex_cubes.axf > src/tex_cubes.axf.map
arm-altera-eabi-objcopy -O binary src/tex_cubes.axf src/tex_cubes.bin
mkimage -A arm -T standalone -C none -a 0x100040 -e 0 -n "baremetal image" -d src/tex_cubes.bin hello-mkimage.bin
Image Name:   baremetal image
Created:      Thu Mar 15 10:15:50 2065
Image Type:   ARM Linux Standalone Program (uncompressed)
Data Size:    2293808 Bytes = 2240.05 kB = 2.19 MB
Load Address: 00100040
Entry Point:  00000000
cp -f C:/Altera/15.0/embedded/examples/hardware/cv_soc_devkit_ghrd/software/preloader/uboot-socfpga/spl/u-boot-spl u-boot-spl.axf
arm-altera-eabi-objdump -d u-boot-spl.axf > u-boot-spl.axf.objdump

実行ログ

出来上がったhello-mkimage.binを、ベアメタル用のSDカードに入れてDE0-Nano-SoCの電源をONにすると、FPGAコンフィギュレーション後に通常のアプリの処理が始まります。

U-Boot SPL 2013.01.01 (Jan 20 2016 - 07:19:29)
BOARD : Altera SOCFPGA Cyclone V Board
CLOCK: EOSC1 clock 25000 KHz
CLOCK: EOSC2 clock 25000 KHz
CLOCK: F2S_SDR_REF clock 0 KHz
CLOCK: F2S_PER_REF clock 0 KHz
CLOCK: MPU clock 925 MHz
CLOCK: DDR clock 400 MHz
CLOCK: UART clock 100000 KHz
CLOCK: MMC clock 50000 KHz
CLOCK: QSPI clock 3613 KHz
RESET: COLD
SDRAM: Initializing MMR registers
SDRAM: Calibrating PHY
SEQ.C: Preparing to start memory calibration
SEQ.C: CALIBRATION PASSED
SDRAM: 1024 MiB
ALTERA DWMMC: 0
reading hello-mkimage.bin
reading hello-mkimage.bin
INFO: Setup DMA System ...
INFO: Channel 0 allocated.
INFO: Setup of DMA successful.

INFO: FPGA Image binary at 0x1a62b8.
INFO: FPGA Image size is 1960824 bytes.
INFO: Setup FPGA System ...
INFO: MSEL [10] configured correctly for compressed FPGA image.
INFO: Setup of FPGA successful.

INFO: Setup Bridge [2] ...
INFO: Setup of Bridge [2] successful.

INFO: Setup Bridge [1] ...
INFO: Setup of Bridge [1] successful.

INFO: Setup Bridge [0] ...
INFO: Setup of Bridge [0] successful.

RESULT: FPGA configuration completed successfully.

まとめ

FPGAコンフィギュレーションをHPSで行うと、Programmerで毎回.sofをロードする処理が不要になります。電源投入ですぐにアプリケーションが起動するので、期待以上に快適です。

タイトルとURLをコピーしました