RiscFree IDE(０円デバッガ) で SoC FPGAをデバッグ 

# はじめに
今年、Nios®V processor のソフトウェア統合開発環境・デバッガとして、 **無償** で使える RiscFree IDE for Intel® FPGAs(以下 RiscFree IDE）が、リリースされました。この RiscFree IDE には、Nios® V processor だけでなく、Arm Processor をハードマクロで含んだ Cyclone® V SoC や Intel® Arria® 10 SoC もデバッグできる機能も備わっていますが、現状、まだドキュメントではほとんど触れられていません。
ここでは一足先に、RiscFree IDE を Cyclone®V SoC の Arm Processor のデバッガとして使い、bootloader[^3] のダウンロードとデバッグを試してみた内容を書かせていただきます。

環境としては、ボードは Terasic の DE10-nano を使い、デバッガを走らせる Host PC は、Windows を使っています。
[^3]: SoC FPGA の標準 bootloader としては、U-Boot spl (secondary program loader) が使われているのでこれを使います(以前は preloader と呼ばれていました)。

# RiscFree IDE for Intel® FPGAs とは
Ashling (組み込みプロセッサ開発ツールの会社）とインテルが共同で開発したツールです。主には、RISC-V アーキテクチャ の Nios® V processor のソフトウェア開発・デバッグ用に提供されている Eclipse IDE をベースとしたツールです。RiscFree IDE は独自の debug server を持って、Nios® V processor と Arm CPU の混在(ヘテロジーニアス）・マルチコアデバッグが可能という機能もありますが、ここでは Nios® V processor のデバッグ時と同様に OpenOCD を debug server として使い、Cyclone® V SoC の ARM Cortex-A9 processor をデバッグしてみることにします[^2]。

OpenOCD に関しては、拙文 ["OpenOCD がやってきた"](https://qiita.com/eofz/items/c5df493e5290a12e8e8b) でざっと説明していますが、その記事で行っているコマンドラインベースでのデバッグ作業を、RiscFree IDE の GUI を使ってやってみた版、とも言えるかと思います。

[^2]: 試してみたところ、v22.3Pro もしくは v22.1Std では、ここで紹介する OpenOCD を使ったデバッグ方法の方が思うように動いたので。

# 必要なツールのインストール
まず、Intel® Quartus® Prime Pro/Standard/Lite edition software のいずれかがインストールされている必要があります。バージョンは、Pro edition は v22.2 以降、Standard/Lite edition は v22.1 以降です[^4]。Intel® Quartus® Prime Pro/Standard/Lite edition software のインストールにより、OpenOCD が動作する環境が作られます。
[^4]: Intel® Quartus® Prime Pro edition software であれば、Intel® Quartus® Prime Pro Programmer のインストールのみでも RiscFree の使用が可能です。

RiscFree IDE のインストーラですが、こちらも Pro edition 用と Standard edition 用がありますので、使用する Intel® Quartus® Prime software edition のダウンロードページの "Additional Software" タブからダウンロードできるRiscFree IDE のインストーラを使ってください。なお、Intel® Quartus® Prime Lite edition software との組み合わせで使う場合は、Intel® Quartus® Prime Standard edition software のページからダウンロードした RiscFree IDE が使えます。
どの Edition を使ったとしても、これから行うデバッグ作業に必要なツール（OpenOCD および RiscFree IDE ）は無償で使えます。

Intel® Quartus® Prime software のインストールの後に、RiscFree IDE のイントールを行ってください。RiscFree IDE のインストール時に、Intel® Quartus® Prime software の install フォルダを指定する必要があります。

また、デバッグ対象となる、boot コードのビルドできる環境があることを前提としています。 bootloader が U-Boot ベースなので、Linux 環境(Virtual Machine 等でも可)が必要となります。

# 実行例：bootloader のダウンロード
まずは RiscFree IDE を起動します。 Windows なら Start メニューに登録された Intel FPGA フォルダから起動できます。最初に workspace フォルダを聞いてくるので、適当な作業フォルダを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/9524e774-9499-4e37-0193-50d1aebe3248.png)

## Debug Configurations... の各設定
ここでは、コードのビルドは行わず（既にビルドは行っているという前提）、デバッグのみの実施なので、早速デバッグの設定を行います。
メニューから Run -> Debug configurations... を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/19c4f694-1f63-dc1c-593f-ffa3f0e7c097.png)
以下の画面となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/8cc66f4d-170d-50fa-95ea-bdbfaea00066.png)
左側のリストには多くのデバッグモードが並んでいますが、ここでは "GDB OpenOCD Debugging" をダブルクリック（選択）します（ここが第１のポイント）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/10a25572-8773-bb02-ab48-bfc7307a4c85.png)
するとOpenOCD を使ったデバッグ設定(configuration)を新規作成する画面となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/fcda4862-4cf0-3c52-dd47-8cdd91da84e1.png)
以下、この Debug Configurations 設定の各タブでの設定を行って行きます。

### Main タブ
右上の "Name:" の欄には適当に設定名を入れておきます。ここでは preloader_debug としています。また、"C/C++ Application:" の欄にデバッグをしたい elf ファイルのパスを Browse... ボタンを押して入力します[^1]。この例では、別途作成済みの bootloader の elfファイルを指定しています(......\spl\u-boot-spl)。なお、この ......\spl\ フォルダには u-boot-spl と同時に生成された u-boot-spl-dtb.bin ファイルも存在している必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/668fe180-fe55-cd28-39fc-f3846c215839.png)
[^1]: ここでの指定では変数($を使った記述) を使うとdebugger起動時にエラーになるので注意。

### Debugger タブ
次に隣の Debugger タブをクリックします。デフォルトの設定から下図の様に変更します。
変更点は、
\- OpenOCD の "Executable path:" に Intel® Quartus® Prime software に付属の openocd.exe を指定
\- OpenOCD の "Config options:" に図のように追記 
\- GDB Client の "Executable name:" に RiscFree に付属の arm 用 gdb を指定
\- GDB Client の "Commands:" に図のように追記 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/13c6afc1-14af-7fa3-788e-3d156295318a.png)
OpenOCD の起動には、 "Config options:" に　```-f <configuration_file>``` の指定が必要です（第２のポイント）。上の例では workspace フォルダに置いてある cyclone5_client.cfg というファイルを指定しています。configuration file の内容については、["OpenOCD がやってきた"](https://qiita.com/eofz/items/c5df493e5290a12e8e8b) を参照してください。この記事と同一の cyclone5_client.cfg を使っています[^5]。一応こちらにも再掲しておきます。
```tcl:cyclone5_client.cfg
###############################################################
# Point:  Driver として aji_client を指定
adapter driver aji_client

###############################################################
# Chip 名: 好きな名前に変更可(cvsoc としておきます)
set _CHIPNAME cvsoc

###############################################################
# HPS TAP(Test Access Port)/DAP(Debug Access Port) の JTAG ID
set _DAP_TAPID 0x4ba00477

###############################################################
# JTAG TAP(Test Access Port) として HPS DAP を宣言
jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_DAP_TAPID

###############################################################
# HPS の TAP は ARM DAP(Debug Access Port) であることを宣言. 
# ARMv6-M, ARMv7, ARMv8 が target の時にやっておく
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu

###############################################################
# gdb debugger で操作する target は、 HPS DAP の core0 とする
target create $_CHIPNAME.cpu.0 cortex_a -dap $_CHIPNAME.dap -coreid 0 -dbgbase 0x80110000
```
[^5]: この.cfg ファイルの最終行からお分かりのように、この設定では、デバッグアクセスできる対象は core0 のみとなります。他の core との接続もできそうな気がしますが、試してません。


### Startup タブ
次に隣の Startup タブをクリックします。デフォルトの設定から下図の様に変更します。
変更点は、
\- "Initial Reset" のチェックボックスをはずす。
\- "Initialization command" に "delete breakpoints" を追加
\- "Enable Arm semihosting" のチェックボックスをはずす。今回デバッグするコードは semihosting 機能は使わないので。
\- "Load symbols" で "Use file" を選択し、u-boot-spl を指定（デバッグを行うコード）
\- "Load executable" のチェックボックスをはずす。（下の Run/Restart Commands で、devicetree が付加されたバイナリ形式のコードを読み込ませるのでここは必要なし）
\- "Pre-run/Restart reset" のチェックボックスをはずす。
\- "Run/Restart Commands" に ```restore u-boot-spl-dtb.bin binary 0xffff0000``` と ```set $pc=0xffff0000``` を追加.
\- "Set breakpoint at:" に "spl_boot_device" を設定（デバッガ開始後、u-boot-spl を ここで停止させる）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/00017952-5ce4-a50b-f223-bb890895399a.png)
最近の u-boot-spl (2020.xx 以降、build の際に u-boot-spl-dtb.bin というファイルも生成されるバージョン）は、プログラムコードの最後に device tree blob (dtb) が付加されたイメージ(u-boot-spl-dtb.bin)をメモリにロードする必要があり、それを "Run/Restart Commands" で行っています。あと、コードのロードを elf ではなく、binary ファイルで行っているため、自動で実行開始アドレスが設定されないので、コマンドで```$pc```を設定しています。

u-boot-spl(bootloader) は spl_boot_device まで実行すれば、HPS の起動に必要なすべての初期化が終わっているので、"Set breakpoint at:" で spl_boot_device を指定しています。
ちなみに、spl_boot_device 関数は、u-boot-spl(bootloader) の最終段階に実行される関数で、次のバイナリ(通常は、フル機能のU-Boot コード)を、SDRAM にロードし、それに実行を移すというフローの入り口となる関数です。

現状の OpenOCD では、Intel® FPGA Download Cable (旧名称 USB Blaster cable) を使った rest command がサポートされていないようで、"Initial Reset", "Pre-run/Restart reset" のチェックボックスを off にしています。（On のままだと OpenOCD の Console window にエラーメッセージが表示されてしまうため。On ままでも実害は無いとは思います。）

### SVD Path タブ
最後に SVD path タブをクリックします(Source タブと Commen タブの設定はデフォルトのままでよい)。ここでは、RiscFree のインストールフォルダに提供されている Cyclone® V SoC 用の .svd ファイルを読み込ませます。これは、Cyclone® V SoC の Peripheral の Register Map が定義されたファイルです。これを読み込ませることで、Peripheral の Register アクセスが簡単に行えるようになります（以降で紹介します）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/0030615b-9a28-dc60-f310-471227a39455.png)

## ダウンロード＆実行
ここまでで一通りの設定ができたので、デバッグ（ダウンロード＆実行）を行ってみます。

予め DE10-nano ボードは、Intel® FPGA Download Cable (旧名称 USB Blaster cable) 用 USB 端子が PC と USB ケーブルで接続されていて、SD card が抜いた状態で、電源が入っている状態にしておいてください。

右下の "Apply" ボタンをクリックしてこれまでの設定内容をセーブしてから、"Debug" ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/ef7d9327-19a4-9019-189f-63d361be8c35.png)
すると（Debug perspective に切り替えても良いか.. といった旨を確認するダイアログが出て来たら、OK を押してください）、下の図の様に Console から OpenOCD からのメッセージ（赤色文字）が表示され、ターゲットの DE10-nano ボード接続を行っている状態になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/453e7ab0-5747-1845-4296-5acb2a12231a.png)
（コードのダウンロードにがちょっと時間がかかる様ですが、10 秒ほどすると) OpenOCD からのメッセージが Console に追加表示され、接続が完了し、下記の画面となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/6e650b72-0778-435a-ec56-815458c4b39d.png)
これは、先の Debug Configurations の Startup タブで設定した通り、 u-boot-spl(bootloader) をダウンロードし、その開始アドレスから実行を開始し、break を指定した spl_boot_device 関数の先頭で実行が停止している状態です(上部中央の spl_gen5.c のウインドウ)。
また、この時 DE10-nano ボードの Serial 用の USB 端子を PC に接続しておき、Serial ターミナルを起動しておけば、以下の表示が出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/0b878381-5352-0615-7820-58b92463cfa6.png)
これらにより、正常に bootloader (u-boot-spl) がダウンロード＆実行できていることが確認できました。
(この先の RTOS のダウンロード&実行は、[こちらの記事](https://qiita.com/eofz/items/2911f61dffd88c6117b1#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E5%AE%9F%E8%A1%8C)で触れてます。）

## Peripheral Register アクセス
続いて、 Peripherals ウインドウを使って周辺回路のレジスタアクセスを確認してみます。（今の状態は、デバッガがターゲットに接続され、CPU 実行が、spl_boot_device の先頭で停止させている状態であるという前提です。）
Peripherals ウインドウが表示されていない場合は、メニューの Window -> Show view -> Peripherals を選択してください。この様に Peripherals が表示されるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/a20d3eaf-89c4-3f8f-e152-2dad9201e595.png)
Debug Configurations の SVD path の設定で svd ファイルを設定したことにより、HPS の各 Peripheral が簡単にアクセスできるようになっています。試しに、WatchDogTimer0 の状態を見てみましょう。Peripherals ウインドウを下にスクロールして、l4wd0 を探し、左側のチェックボックスにチェックを入れます。
すると、下図の様に、Memory ウインドウに WatchDogTimer0 (l4wd0) の全レジスタの状態が表示されます。(Memory ウインドウの状態がこの様にならない場合は、再度 Peripherals ウインドウで l4wd0 のチェック・アンチェックを繰り返してみてください。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/1056f8aa-fd38-4cc2-1628-3e77b81442ae.png)
Memory ウインドウで、l4wd0 の wdt_cr の ">" をクリックして  wdt_cr レジスタの各ビットを見てみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/8ee3cb86-98a0-2c92-319d-90b3a4d93eb5.png)
l4wd0 の wdt_cr レジスタの wdt_en (bit-0) が 0x1:enabled となっており、WatchDogTimer が動作中だということがわかります。
デバッガコントロールの Step over ボタンをクリックして　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/559a5e9e-fe5c-2cc0-254e-9b5cd065836a.png)
l4wd0 の状態を見てみると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/8394b73b-247b-5eb9-db22-3605bd57697e.png)
wdt_ccvr レジスタが黄色でハイライト表示され、値に変化があったことが示されています(0x01F542CD → 0x01F542BE にカウントダウンされている)。
ちなみに、この l4wd0 を停止させるには、リセットマネージャー(rstmgr) から、l4wd0 にリセットを入れてやる(rstmgr の permodrst レジスタの bit-6 を 1 にする) ことで可能です。この作業も Peripherals/Memory ウィンドウを使って簡単にできるので試してみてください（ rstmgr の permodrst レジスタの bit-6 の Value の所を書き変える）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175992/e522dead-cdc1-0568-3862-4909da78b71e.png)

あと、ここでは紹介していませんが、デバッグでよく使う Memory、Variables、Expressions、Registers ウインドウでの表示やアクセスは普通に動作します。


# 注意点 & Tips
最後に、気が付いた注意点などをリストしておきます。

- gdb のコマンド入力は、Debugger Console Window から可能です。入力プロンプトはでませんが、Debugger Console をクリックして、キーボードからコマンド入力ができます。（ブレークポイントの設定 hb, thb など、コマンド入力の方が便利な場面もありますので。）

- GUI で行うブレークポイントの設定でも、hardware break point を使うことをお勧めします。hardware break point の方が確実に動作します。

- OpenOCD からのメッセージが標準エラー出力から出されてくるので、Console に表示される文字色が赤となっています。赤色の文字が気になる場合は、Console の Prefercence 設定 (Console window 内で 右クリックで選択可能)で Standard Error text color を落ち着いた色にしてみてください。

- Disassembly ウィンドウを表示させていると debug 接続が切れてしまう場合がたまにあります。Disassembly ウィンドウの表示は必要な時のみにしておいた方が良いかもしれません。

- OpenOCD から Arm processor にリセットが入れられないので、直前の CPU core の状態によっては、デバッグ開始時に、ボードのリセットスイッチか電源ON/OFF で代用する必要がある場合があります。

# まとめ
今年リリースされた Intel® Quartus® Prime software から、 Nios® V processor 用のソフトウェア統合開発環境として　RiscFree IDE がバンドルされるようになりました。この **RiscFree IDE のデバッガを、SoC FPGA の Arm processor のデバッガとして使ってみる** ということを試してみました。

OpenOCD server のおかげで、現時点でも各種デバッグ作業が GUI で問題なく行えるようになっています。有料のデバッガと比較すると動作の機敏さとか、機能の充実性など差はありますが、無償で気軽に使える SoC FPGA 用のデバッガとして活用できるものと思います。

# 参考資料
* [Qiita: OpenOCD がやってきた](https://qiita.com/eofz/items/c5df493e5290a12e8e8b)

# Notices & Disclaimers

Intel technologies may require enabled hardware, software or service activation. No product or component can be absolutely secure. Your costs and results may vary. 
© Intel Corporation.  Intel, the Intel logo, and other Intel marks are trademarks of Intel Corporation or its subsidiaries.  Other names and brands may be claimed as the property of others.