1.記事一覧
記事は複数回に分けて投稿する予定です。AMD/XilinxのARM SoC(ZynqMP Kria K26 SOM)で動作する、AMD/Xilinx公式認定Ubuntuやベアメタル開発を勉強していく覚書きです。
ZynqMP(APU:Cortex-A53,Arm64) 組込みLinux入門編
ZynqMP(RPU:Cortex-R5,Arm32) RPU入門編
- 【ZynqMP】1. Cortex-R5でHelloworld
- 【ZynqMP】2. Cortex-R5でRTOS+GPIO
- 【ZynqMP】2.1. GPIO割込みが入らない? ←本記事
- 【ZynqMP】2.2. GICv1の設定まわりを歩く
2.AXI-GPIO割込みが入らない(ベアメタル)
前回の【ZynqMP】2.Cortex-R5でRTOS+GPIOで作業中に出会ったプチ不具合の謎解き話をしようと思います。
起こった現象:
- ボタンを押下しても割込みハンドラが呼ばれない
割込み実装時あるあるの話ですが、ブレークポイントを貼っても一向に処理がやって来ませんでした。前回の構成は以下の感じです。Cortex-R5+FreeRTOSでGPIO割込みをやろうとしていました。
想定できる原因を可能性の高い順に並べると、以下の感じかなと思いました。
- VivadoでIPブロックの配線、IPの設定、その他のミス
- AXI-GPIO IPのドライバの設定ミス
- GICの設定ミス
- Vitisのビルド設定ミス
- ドライバの不具合(SDT対応によるデグレ)
- Vitisのビルドシステムの不具合(2023.2で新しくなった)
Vivadoの操作はまだまだ慣れていないのでミスる可能性は高そうです。また可能性は低いですが、IDEが今回から新しくなったので、もしかしたら初期の不具合が出るかもしれません。
2-1. VivadoでIPブロック設定ミスの可能性
Vivadoを開いて確認しましたが、IPブロックは今回の構成では設定項目が多いわけではないので、見当たりませんでした。Linux編でAXI-GPIOはそれなり使っているので癖もわかっている感じです。この可能性は一旦保留にして次を調べます。
2-2. AXI-GPIO IP・GICのドライバの設定ミスの可能性
今回はGithubのサンプルコードをコピって改変しているので、改変した部分を再確認して見ましたが、特に間違ってはいないようでした。GICに関してはSDT対応版は1関数一発で設定できるので、ほとんどユーザが決めるパラメータが無いです。
そうは言ってもGPIOとGICのハード面、ソフト面のどれかに原因はあると思うので、ハード面から確認してみます。まずはGPIOとGICの間を区切る、割込み信号線がアクティブになっているか確認します。
ASICのSoCであれば割込み信号線を直接観測するのは出来ないのですが、AXI-GPIOはPL(FPGA上に)あるのでILAと呼ばれる内蔵ロジックアナライザIPを用いて信号を観測できます。今回初めて使ってみようかと思います。
2-3. ILAで割込み信号線を観測する準備
やり方はいろいろあるようですが、論理合成後のNetlistからセッティングしてみましょう。
割込み信号線(ip2intc_irqt)をデバッグ対象にします。サンプリングクロックはPL_CLK0(99.9MHz)から取ります。
ILAの設定です。サンプリングバッファは4096(=4096/100MHz=40.96us)、input pipe stagesはよくわからないのですが、webで例を調べてみて4にすることにしました(もっと少なくて良いかも)。
ビットストリームを生成してExportします。
2-4. Exportファイル(.xsa)を新Vitisで更新するときの注意
Vitisを開いてハードウェアExportファイル(.xsa)を再読込します。やることは以下の2つです。
- Platformコンポーネントで.xsaを再読込してBSPを再生成
- Applicationコンポーネントのデバッグ用ビットストリームファイルを更新
2つ目はデバッグ開始時にJTAG経由でコンフィグレーションするビットストリームのことで、Application作成時にPlatform側からコピーされたものを参照するようです。そのため、.xsaをPlatformで更新してもデバッグ時に古いビットストリームがダウンロードされます。これに気づかずに調査が難航しましたので気をつけてください。
Platformコンポーネントで.xsaを再読込してBSPを再生成します。”Switch XSA”を押してxsaを読み込むとBSPが再生成されます。
Platformを一度クリーンしてフルビルドしておきます。
次にApplicationコンポーネントのデバッグ用ビットストリームファイルを更新します。ファイルは下記のパスにあるのでこのパスのファイルをPlatformから手動でコピーし直すか、pathをPlatform側のファイルに変更するかします。
私は”<Platformコンポーネント>/hw/sdt/design_1_wrapper.bit”に変更しました。
2-5. ILAで割込み信号線を観測
VitisとVivadoを両方立ち上げておきます。やり方は以下のとおりです。
- Vitisでデバッグを実行し、main()先頭でブレーク状態にする(PLコンフィグレーションさせる)
- VivadoでHardware managerを開き、open target>Auto connectで接続する
- Hardware managerでILAのトリガを設定する
- ILAの計測を開始し、Vitisで実行
- スイッチを押下して様子を見る
最初にVitisでデバッグ実行をしてILA入りビットストリームをコンフィグレーションさせます。そのあとVivadoで接続すると、ILAを検知してデバッグレイアウトに自動で切り替わります。
次にトリガを掛けます。AXI-GPIOのマニュアル”AXI GPIO v2.0 Product Guide (PG144)“によると、割込み線はActive-Highのレベルセンシティブとあるので以下のトリガ条件とします。
- Operator “==”
- Radix “[B] (Binary)”
- Value “1”
ILAの計測を開始します。waiting状態になります。
Vitisで実行してスイッチを押してみます…トリガが掛かる気配がありません。手順が間違ったのかと最初は思いましたが、そうではないようでした。原因はAXI-GPIO側にありそうです。
2-6. あれ…GPIOの割込み許可の処理してなくない?
そういえばペリフェラル側(AXI-GPIO)の割込み許可はあるはずだけどやっていたっけ?と気づき、もう一度Githubのサンプルコードを確認してみました。するとSDT非対応分岐の処理ではしっかりAXI-GPIOの割込み許可APIを呼んでいました。どうやらSDT対応コードではこれが抜けていたようです。無いものに気づくのは意外と難しいですね。
割込み許可を追加してもう一度やってみると、トリガがかかり、割込みハンドラが呼ばれました。ひとまず一見落着です。
ちなみに割込み線がアクティブになってから割込みハンドラが呼ばれて、GPIOの割込み要因クリア完了まで70サンプルでした。70/100MHz=0.7usなのでとても速いですね。ちなみに1発目だけ146サンプルと2倍の時間がかかりました。リンカスクリプトでは割込みハンドラのある、.text=DDR領域なので、キャッシュによる違いが出たのでしょうか。キャッシュ搭載プロセッサをベアメタルで扱うのは初めてなので、今後いろいろパフォーマンス測定してみたいですね。