FPGA

【ZynqMP】1. Cortex-R5でHelloworld

1.記事一覧

記事は複数回に分けて投稿する予定です。AMD/XilinxのARM SoC(ZynqMP Kria K26 SOM)で動作する、AMD/Xilinx公式認定Ubuntuやベアメタル開発を勉強していく覚書きです。

Zynq7000(armv7)版はこちら

2.RPU(Real-time Processing Unit)に触ってみる

ZynqMPにはLinuxが動かせる、ARM Cortex-A53 MPCore(以後CA53)が4コア搭載されていて、APU(Application Processing Unit)と呼ばれています。そして、他にCortex-R5F(CR5)が2コア搭載されて、こちらはRPU(Real-time Processing Unit)と呼ばれています。

出典<https://japan.xilinx.com/products/silicon-devices/soc/zynq-ultrascale-mpsoc.html>

Cortex-Rプロセッサはその名の通りリアルタイム処理を目的とした32bitコアになります。どちらかといえばCortex-M系よりCortex-A系に近い構造です。

マイクロコントローラのCortex-M系より、比較的高クロックでL1キャッシュ・AXIバス搭載とリッチな構成になっています。L1キャッシュを搭載していると言うことは、キャッシュヒット率による応答時間の(最悪値の)ばらつきの懸念がでてきます。その場合のために、アクセスウェイトがほとんどかからないTCM(密結合メモリ)を搭載しています。

CR5プロセッサは2コアで1コア分の動作をする、デュアルロックステップ機構を持っています。これはハードの冗長化を行い、故障に対する信頼性を向上させるものです。いわゆる機能安全規格向けの機能になります。自動車のECUに搭載する場合には必要な要件になります。必要ない場合は2コア別で動かすことも出来ます。

Cortex-Rが多く使われている場所は車載向けSoCのCAN通信制御やコンピュータのストレージコントローラ(HDDやSSDの制御chip)に多いとよく聞きます。

最後に動作クロックですが、KR260に搭載されるK26 SOMの場合、533MHzで動作するようです。ZynqMPはスピードグレードによっては最高600MHzです。

2-1. CR5(Cortex-R5)でHello World

長々と紹介してみましたが今回は全然大したことはやりません。シリアルへHello worldを出力するのをやってみます。テンプレートにHelloworldのサンプルがあるのでこちらを使ってみましょう。

3.環境

3-1. 新Vitis Unified IDE(2023.2)を使ってみる

2023.2で、Vitis IDEが新しくなっていることを知りました。Vitis AIやVitis HLSが統合されたメジャーアップデートになるようです。

試しに起動してみるとなんとEclipseベースだった環境がVisual Studio Code(VSCode)ベースになっていました。(ちなみに旧Vitisも入ってます。shell$ vitis -classic & で起動できます)

旧Vitis(Vitis Classic)はUIが今一つだったので、テーマをいろいろいじっては悪化して戻らなくなるという経験をしました。暗色背景に暗色文字(その逆もあり)が見づらく、結局直せませんでした(笑)。VSCodeへの移行は膨大な工数がかかったと予想できますが、AMDさん、Xilinxさんナイスな判断だと思います(日本企業だとおそらく出来ない)。

ところでVSCodeはMicrosoftさんの製品ではあるのですが、2015年?あたりにオープンソース化(github)されてMITライセンスになっています。世の中の組込み向けマイコンベンダの多くは開発環境がEclipseベースですが、いずれVSCodeに移行する流れがくるのでしょうか。

もう一つ驚きなのが、ビルドシステムの刷新です。詳しくはこちらのXilinx-Wikiにあります。ざっくり違いを説明すると、

  • 従来:.xsaからソフトウェア構成にmdd,mld,mssファイルを使用し,Xilinxツール依存大
  • 今回:.xsaからSystem-Device-Tree,lopper(Python),CMake,YAMLを使用し、Xilinxツール依存小

と、ほぼ全面的に変わっているようです(これも相当な工数がかかったと思われます)。Xilinxツール(XSCT,HSIなど)に依存度が高い現状をオープンソースツールを活用して改善しようという試みらしいです。オープンソース文化が強いAMDさんが後押ししたのでしょうか。

System-Device-Tree(SDT)とはLinuxのdevicetreeのスーパーセットに当たるもので内容が拡張されています。これをハードウェアメタデータの代わりとするようです。lopperはdevicetree.orgが提供するPythonライブラリでdevicetreeのパースを行うことが出来るようです。

SDT導入に関してベアメタルアプリの開発の気になる点がありました。

  1. ベアメタルドライバの互換性が一部なし
  2. timerライブラリ(xiltimer)の組込みが必須になる

xparameters.hからDeviceIDを調べてドライバの初期化関数を使用していましたが、これがデバイスのベースアドレスに変わるようです。この部分の関数の互換性がありません。devicetree自体がデバイスの区別をベースアドレスで行うことからこの仕様になったと思われます。

以下にAXI-GPIOのベアメタルドライバのサンプルコードの抜粋を貼っておきます。

C
//AXI GPIOベアメタルドライバの例
#ifndef SDT
	Status = XGpio_Initialize(InstancePtr, DeviceId);
#else
	Status = XGpio_Initialize(InstancePtr, BaseAddress);
#endif
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

また、DeviceIDがなくなったことと、SDTに親割込みコントローラの情報を持つことによって、割込みの初期化周りの関数の扱いも変わるようです。こちらはAXI-GPIOのドライバのサンプルを見る限りは初期化処理がよりシンプル…というか1関数一発で設定完了できているようです。

次にxiltimerライブラリの使用が必須の件ですが、スリープや周期タイマの機能をハードウェアタイマが提供します。K26 SOMの場合はTTCタイマを使用します。APU側で認定Ubuntuを動かす場合、FAN制御のPWM出力用にTTC0を使っていますので、OpenAMPなどを動かす場合気をつける必要があります。

3-2. 前提条件

CR5でHelloworldするにあたっての前提条件をまとめます。

開発PCUbuntu20.04 LTS
開発ツールADM/Xilinx社 Vivado・Vitis Unified IDE v2023.2.1
ターゲットボードXilinx社製 Kria KR260 ロボティクススターターキット(SK-KR260-G)
SOM : Xilinx社 Kria K26 SOM (Zynq UltraScale+ MPSoCベース)
   APU : Arm CA53x4 1333MHz arm64
   RPU : Arm CR5x2 533MHz armv7-R
SDRAM : DDR4 4GB
その他MicroUSBケーブル1本(JTAG, USB-UART用)

4.VivadoでPLを作成

注意:Vivadoの詳しい操作方法は説明しません。要点だけ載せます。

4-1. プロジェクト作成

Note:プロジェクトを作成するときの注意点です。Project Typeでは
“Project is an extensible Vitis platform”にチェックを入れません

理由はチェックを入れるとVitisを起動した際、以下のようにアプリケーションプロジェクトでデバッグ機能が働かないからです。理由はわかりません。

本来は以下の内容が出てほしいです。

この現象はかなり困ったのですが、Whitney Knitter氏のGetting Started with the Kria KD240 in Vitis Unified 2023.2の記事で対策方法を見つけることが出来ました。先人に感謝。

4-2. IPブロック作成

IPブロックは今回は何も接続しません。

ビットストリームを生成できたらbitstreamを含む設定でエクスポートします。

5.Vitis Unified IDEでプロジェクト作成

Vitis Unified IDEを起動します。Vivadoのツールタブで起動する方法の他に、Linuxならshellで起動できます。旧Vitis(Vitis classic)も入っているので不具合が出たときにこちらを選ぶことも出来ます。

起動できたらOpen Workspaceで作業フォルダを指定します。

ShellScript
#おまじない
$ source /tools/Xilinx/Vitis/2023.2/settings64.sh

# Vitis Unified IDE
$ vitis &

# 旧Vitisも起動可能
$ vitis -classic &

5-1. Platformコンポーネントを作成

今までもそうでしたが、Vitisで組込み開発する場合はplatformプロジェクトをベースにapplicationプロジェクトを作成する2段構成になります。platform側はBSPを構成するためのプロジェクトになります。ただし、Vitis 2023.2からはプロジェクトではなくコンポーネントと呼ばれるようになっています。

左上のFile>New Component>Pratformを選択します。

pratform名を決めます。

vivadoからエクスポートした.xsaを選択します。

次に行くと.xsaを解析するのに少し時間がかかります。構成が自動設定されます。ProcessorをCR5の0番コアに設定します。

  • Operating system: standalone
  • Processor: psu_cortexr5_0

デフォルトでGrenerate Boot artifactsにチェックが付きますが、これはFSBLを自動生成します。FSBLの実行コアはCA53がデフォルトになりますが、このままで行きます。

次にサマリが表示され、Finishでコンポーネント生成が始まります。生成はそこそこ時間がかかります。

5-2. Platformコンポーネント(BSP)の設定の確認

BSPの設定周りを見ていきます。左のファイルツリーからPlatform>Settings>vitis-comp.jsonを選択します。

まずはライブラリ周りからです。xiltimerがデフォルトで有効になっています。先程も記述しましたが、ベアメタルドライバでxiltimerは必須項目になっているためです。

コンパイラ周りの設定です。

標準出力stdoutと標準入力stdinのポート設定です。psu_uart_1はPSのuart1で、KR260ではJTAG用のUSBケーブルを経由する、USBシリアルとして使えます。

ちなみに、VivadoでAXI-UartLite IPをPLに実装してあると、ここに選択肢として選ぶことが出来るようになります。uart1はLinux側でシリアルコンソールとして使用するので、これを無効化したくない場合は、AXI-UartLite IPでRX,TX線を外部出力し、USBシリアル(FTDIなど)チップで接続するといった方法が使えます。

xiltimerの設定です。PSのTTCタイマを利用するので、使用するタイマがバッティングする場合は変更しておきます。認定UbuntuではFAN制御にTTC0を使うのでLinuxを同時に動作させる場合は注意が必要です。

driversは使用しているverを確認できます。

今回はBSPはデフォルトのままの設定で使用します。platformをビルドします。FlowウィンドウののBuildボタンを押します。

5-3. Applicationコンポーネントの作成

Applicationコンポーネントはテンプレートから作成することにします。左側のバーでExamplesを押し、Hello Worldを押して、Create Application Component from Templateを押します。

Application名を入力します。

先程作成したPlarformを選択します。

ドメイン選択です。デフォルトのままで次に行きます。

最後にサマリを確認してFinishボタンを押して完了です。

5-4. Applicationコンポーネント設定の確認

vitis-comp.jsonを見てみます。特段設定するところは無さそうです。Navigate to BSP SettingsはPlatromのvitis-comp.jsonへのリンクです。

続いてCMakeLists.txtです。

UserConfig.cmakeはUIで設定できるようになっています。四角で囲った部分のボタンでコードを表示もできます。

最後にlaunch.jsonです。デバッグ用設定になります。UIモードとjsonモードがあります。

デバッグ設定で注意しないとならないのが、デバッグ実行時のPLへダウンロードするビットストリームファイルはApplicationコンポーネントフォルダ内にPlatformコンポーネントからコピーしたものを参照しているようです。

つまり、Vivadoでハードウェアファイル(.xsa)を更新したときにPlatform側でvitis-comp.jsonの”switch xsaボタン”による更新(←そもそもこれが正規手順なのか?)をした場合でも、デバッグ時は古いビットストリームファイルのままになります。とりあえず下記のパスをPlatform側に変えるか、手動でビットストリームファイルをコピーする対策をします。

6.Hello worldをJTAGデバッグする

作成されたHello worldのソースを見てみます。シンプルですね。

Applicationコンポーネントをビルドします。旧VitisではPlatformコンポーネントに変更が合った場合自動で逆上ってリビルドを掛けてくれますが、新Vitisではそれをやってくれないみたいなので、手動でビルドし直します。

6-1. KR260のbootmodeをJTAGbootに切り替える

Vitisでデバッグ開始する前に、ZynqMPはboot設定端子でbootmodeをJTAGbootに設定しますが、KR260キャリアボードには設定端子がありません。基本的にK26 SOMはQSPI ROMからFSBL、u-bootを起動しますので、QSPI boot固定のようです。

新Vitisではデバッグ実行するとJTAGbootモードに強制的に移行しますか?とダイアログが出て、そのままJTAGダウンロードを開始できます。しかし、JTAGを再接続したりすると、DAP周りでのエラーが出ます。これはボードの電源を入れ直すと解消できました。

しかし、開発体験が悪いのでいい方法がないか調べてみると、公式Docでは、JTAG経由でTCLを実行して、bootmodeレジスタを上書きする、ことで対応出来るようです。これを試すと、何度かJTAGを接続し直してもDAPエラーが出ることはなくなりました。

手順は以下のとおりです。

  1. SDカードを外す(Linuxイメージが入っている場合破損の危険があるので)。
  2. JTAG起動用のTCLファイル作成
  3. JTAG/シリアル用USBケーブル接続とボード電源のON
  4. XSCTでTCLを実行
  5. Vitisによるデバッグ
  6. ボードの電源をOFFにすると元のQSPI bootmodeに戻る

順にやっていきます。

1.SDカードを外します。

2.以下のTCLファイルを作ります。ファイル名はboot_jtag.tclにします。

TCL
proc boot_jtag { } {
############################
# Switch to JTAG boot mode #
############################
targets -set -filter {name =~ "PSU"}
# update multiboot to ZERO
mwr 0xffca0010 0x0
# change boot mode to JTAG
mwr 0xff5e0200 0x0100
# reset
rst -system
}


# Jtag接続
connect
puts stdout "Connect Jtag"

# JtagBoot切り替え
puts -nonewline stdout "Start transition to jtag boot mode..."
boot_jtag
puts stdout "done."

# Jtag切断
puts -nonewline stdout "Disconnect Jtag..."
disconnect
puts stdout "done."

3.ボードにJTAG/シリアル用のUSBケーブルを接続します。

ここで、Ubuntuならscreenコマンド(WinならTeraterm)でu-bootのメッセージを観察してうまく行くか様子を確認してみましょう。成功すればresetがかかるはずなので、メッセージが途中で止まるはずです。

ボードの電源を入れます。シリアルにu-bootのログが出てきます。

4.XSCTでTCLを実行します。

ShellScript
# おまじない
$ source /tools/Xilinx/Vitis/2023.2/settings64.sh
$ ls
boot_jtag.tcl

# TCl実行
$ xsct boot_jtag.tcl

実行結果です。

$ xsct boot_jtag.tcl 
attempting to launch hw_server

****** Xilinx hw_server v2023.2.1
  **** Build date : Dec  8 2023 at 09:27:31
    ** Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.
    ** Copyright 2022-2023 Advanced Micro Devices, Inc. All Rights Reserved.

INFO: hw_server application started
INFO: Use Ctrl-C to exit hw_server application

INFO: To connect to this hw_server instance use url: TCP:127.0.0.1:3121

Connect Jtag
Start transition to jtag boot mode...done.
Disconnect Jtag...done.
$

u-bootログも途中で止まりました。resetが掛かったようです。

6-2. JTAGデバッグ実行

デバッグを実行します。launch.jsonのデバッグ設定はデフォルトのままで行きます。

デバッグ画面に切り替わります。元に戻りたいときは左端のバーで切り替えます。

CA53の0番コアとCR5の0番コアがブレーク状態になっています。これはPlatformコンポーネント作成時にFSBLの実行コアをCA53に設定したためです。CA53側がアクティブになっているため、右側の逆アセンブリはCA53がFSBLの処理が完了し、Handoff後のExitでブレークしている状態です。

CR5側をアクティブにします(上画像の緑枠を押す)。main関数先頭でブレークしています。

試しに実行してみます。Hello worldが無事出ました。旧Vitisにあったシリアルコンソールはなくなっていますが、開発PCにUbuntuなどのLinuxを使っている方であれはターミナルshellを内部に表示出来るので、screenなどが使えます。

ABOUT ME
sh-goto
組込エンジニア. 最近の遊びはLinuxの低レイヤいじりとXilinxのZynqとFPGAを使った電子工作
関連記事