1.記事一覧
記事は複数回に分けて投稿する予定です。AMD/XilinxのARM SoC(ZynqMP Kria K26 SOM)で動作する、AMD/Xilinx公式認定Ubuntuやベアメタル開発を勉強していく覚書きです。
ZynqMP(APU:Cortex-A53,Arm64) 組込みLinux入門編
- 【ZynqMP】1. 認定UbuntuでPLのGPIOを使う
- 【ZynqMP】2. 認定Ubuntuのカーネルビルド
- 【ZynqMP】3. 認定UbuntuのDeviceTree変更
- 【ZynqMP】4. 認定UbuntuでOpenAMPを試す【CR5Lockstep】
- 【ZynqMP】4. 1. 認定UbuntuでOpenAMPを試す【CR5Split】←本記事
- 【ZynqMP】5. UARTでAMP【コア間通信】
- 【Linux】6. crash toolでカーネルメモリを見る
ZynqMP(RPU:Cortex-R5,Arm32) RPU入門編
2.前回に引き続き、Splitモード(2コア)を試す
注:この記事の内容は2024/7頃の内容になります。情報が古い場合はご了承ください。
前回、OpenAMPでCR5のLockstepモード(冗長1コア)での動作を試しました。今回はSplitモード(2コア)での動作を試したいと思います。
2-1. 参考情報
前回のものを転載します。貴重な情報に感謝です。
- 実践的!FPGA開発セミナー vol.12 フィックスターズ様
- Kria KV260 環境構築メモ(Ubuntu22.04 版) Ryuz88様
- Understanding OpenAMP On Zynq+ZynqMP AVNET
- Building RPU Split Mode Applications AVNET
- support.xilinx.com : Usage of the remoteproc functionality via Ubuntu 22.04 (5.15.0-1025-xilinx-zynqmp) on a KR260 board.
2-2. 環境条件
前回と同じです。
開発PC | Ubuntu20.04 LTS |
開発ツール | AMD/Xilinx社 Vivado・Vitis Classic v2024.1.1 |
ターゲットOS | Xilinx認定Ubuntu22.04 Linux Kernel : 5.15.0-1031-xilinx-zynqmp |
ターゲットボード | 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 |
OpenAMP Echo test | Github : https://github.com/OpenAMP/openamp-system-reference/tree/v2024.05/examples/linux/rpmsg-echo-test branch=v2024.05 |
この記事で使用したコード類 | Github :https://github.com/kern-gt/ZynqMP-OpenAMP |
2-3. 先に結論:動いたが2回目の実行不可. 原因もわからず
前回の始めに記載した、結果のまとめをこちらにも転載します。
2記事分の長い内容なので、先にこのチャレンジの結果を記載します。
- Splitモード、LockstepモードでCR5のELFロード・起動・停止は出来た
- ECHOサンプルのみを試した。詳細は↓
- CR5のベアメタルファームウェアサンプルは正常動作したが、再接続不可
- 上記の原因は不明・今後も調査を続ける
CR5はSplitモード、Lockstepモードの起動方法があり、前者は2コア、後者は1コア(2コアを冗長構成で使用)になります。
結果はもやもやする内容となりました。一度Echo testを実行するとVirtIOがbusy状態に入り、デバイスファイルがOpenできなくなって再接続不可となる症状が出ました。一度CR5コアを停止して再起動する必要があります。原因は今も不明です。
原因を突き止められなかったのは、自分の実力不足が根本原因ですが、今後も調査を続けたいと思います。特にLinuxとCR5を動作させた状態でデバッグする技術が私に足りないので、まずはもう少しZynqMPと開発ツールをを使いこなせるようになってからですね。(Linux動作させた状態でJtag接続するとCA53がハングしてしまう…←解決済)
また、認定Ubuntuはkernel v5.15系を使っていますが、XilinxのGithubのKernelリポジトリを見ても最近のコミット履歴が見受けられますし、Kernel v6.x系でRPMesgドライバがいくつか機能分割された新設計?になりそうな予感です。XilinxのOpenAMPのサポート状況の内情を知らないのでわかりませんが、何かの過渡期なのかもしれません。
リリースされるかどうかわかりませんが、認定Ubuntu24.04はKernel v6.x系になると予想されるので、いま本腰入れて原因調査しても意味が薄くなるかもしれません。とりあえず本件は様子見したいと思います。
OpenAMPの代替となる方法について
OpenAMPでELFロードと起動管理は出来ましたが、コア間通信が使えないと、今後CR5開発の幅が狭まってしまうので、変わりの方法を考えてみます。せっかくPL(FPGA)が載っているのでここを活用してみたいですね。
代替AMP案としては今思いつくのは以下2つくらいです。
- PLにAXI UARTLite IPを載っけてUARTをFIFOとして使う
- PLにAXI QSPI IPを載っけてSPIをFIFOとして使う
基本はコマンドを送り合う用途を想定しているので、速度を出す必要は無いです。だとするとこんなもので十分ではないかと思います。気が向いたらやってみます。
SPIはクロック同期なので比較的高速ですが、スレーブ側の開発がネックになりそうです。転送タイミングを自身で決められませんからね…。CTS、RTS信号をAXI GPIOで用意してフロー制御やるか…いやシンプルに出来ないならOpenAMP代替のメリットが薄くなるな…
3.CR5のSplitモード(2コア)でOpenAMP Echo testを試す
- DevicetreeをCR5 Splitモード版に変更する
- CR5-1コア用のEcho testサンプルを作成する
- CR5-0、CR5-1の2テストを実行
- 2回目のEcho test実行は不可
3-1. Splitモード版のDevicetree
Splitモード版のDevicetreeを作成していきます。といっても中身を理解しているわけでは無いので、Web上の先駆者の方の知識を借りながら見様見真似で作ってみます。
特にAVNETさんの公開情報が参考になります。DevicetreeとCR5側ファームウェアの両方の設定が一致しないと動作しません。両方の修正内容が載っていて参考になります。
最終的に完成したものが以下になります。
- zynqmp_openamp_r5_split.dtsi
- 5.15.0-1031-xilinx-zynqmp
- この後説明するEcho test用CR5ファームウェアにもdtsiに一致した設定が必要
/*
* SPDX-License-Identifier: MIT
*
* dts file for ZynqMP OpenAMP
*
* Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
*
*/
&{/} {
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
rproc_0_reserved: rproc@3ed00000 {
no-map;
reg = <0x0 0x3ed00000 0x0 0x40000>;
};
rpu0vdev0vring0: rpu0vdev0vring0@3ed40000 {
no-map;
reg = <0x0 0x3ed40000 0x0 0x4000>;
};
rpu0vdev0vring1: rpu0vdev0vring1@3ed44000 {
no-map;
reg = <0x0 0x3ed44000 0x0 0x4000>;
};
rpu0vdev0buffer: rpu0vdev0buffer@3ed48000 {
no-map;
reg = <0x0 0x3ed48000 0x0 0x100000>;
};
rproc_1_reserved: rproc@3ef00000 {
no-map;
reg = <0x0 0x3ef00000 0x0 0x40000>;
};
rpu1vdev0vring0: rpu0vdev0vring0@3ef40000 {
no-map;
reg = <0x0 0x3ef40000 0x0 0x4000>;
};
rpu1vdev0vring1: rpu0vdev0vring1@3ef44000 {
no-map;
reg = <0x0 0x3ef44000 0x0 0x4000>;
};
rpu1vdev0buffer: rpu0vdev0buffer@3ef48000 {
no-map;
reg = <0x0 0x3ef48000 0x0 0x100000>;
};
};
tcm_0a: tcm_0a@ffe00000 {
no-map;
reg = <0x0 0xffe00000 0x0 0x10000>;
status = "okay";
compatible = "mmio-sram";
power-domain = <&zynqmp_firmware 15>;
};
tcm_0b: tcm_0b@ffe20000 {
no-map;
reg = <0x0 0xffe20000 0x0 0x10000>;
status = "okay";
compatible = "mmio-sram";
power-domain = <&zynqmp_firmware 16>;
};
tcm_1a: tcm_0a@ffe90000 {
no-map;
reg = <0x0 0xffe90000 0x0 0x10000>;
status = "okay";
compatible = "mmio-sram";
power-domain = <&zynqmp_firmware 17>;
};
tcm_1b: tcm_0b@ffeb0000 {
no-map;
reg = <0x0 0xffeb0000 0x0 0x10000>;
status = "okay";
compatible = "mmio-sram";
power-domain = <&zynqmp_firmware 18>;
};
rf5ss@ff9a0000 {
compatible = "xlnx,zynqmp-r5-remoteproc";
xlnx,cluster-mode = <1>;
ranges;
reg = <0x0 0xff9a0000 0x0 0x10000>;
#address-cells = <0x2>;
#size-cells = <0x2>;
r5f_0: r5f@0 {
compatible = "xilinx,r5f";
#address-cells = <2>;
#size-cells = <2>;
ranges;
sram = <&tcm_0a>, <&tcm_0b>;
memory-region = <&rproc_0_reserved>, <&rpu0vdev0buffer>, <&rpu0vdev0vring0>, <&rpu0vdev0vring1>;
power-domain = <&zynqmp_firmware 7>;
mboxes = <&ipi_mailbox_rpu0 0>, <&ipi_mailbox_rpu0 1>;
mbox-names = "tx", "rx";
};
r5f_1: r5f@1 {
compatible = "xilinx,r5f";
#address-cells = <2>;
#size-cells = <2>;
ranges;
sram = <&tcm_1a>, <&tcm_1b>;
memory-region = <&rproc_1_reserved>, <&rpu1vdev0buffer>, <&rpu1vdev0vring0>, <&rpu1vdev0vring1>;
power-domain = <&zynqmp_firmware 8>;
mboxes = <&ipi_mailbox_rpu1 0>, <&ipi_mailbox_rpu1 1>;
mbox-names = "tx", "rx";
};
};
zynqmp_ipi1 {
compatible = "xlnx,zynqmp-ipi-mailbox";
interrupt-parent = <&gic>;
interrupts = <0 29 4>;
xlnx,ipi-id = <7>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
ipi_mailbox_rpu0: mailbox@ff990600 {
reg = <0xff990600 0x20>,
<0xff990620 0x20>,
<0xff9900c0 0x20>,
<0xff9900e0 0x20>;
reg-names = "local_request_region",
"local_response_region",
"remote_request_region",
"remote_response_region";
#mbox-cells = <1>;
xlnx,ipi-id = <1>;
};
};
zynqmp_ipi2 {
compatible = "xlnx,zynqmp-ipi-mailbox";
interrupt-parent = <&gic>;
interrupts = <0 30 4>;
xlnx,ipi-id = <8>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
ipi_mailbox_rpu1: mailbox@ff990400 {
reg = <0xff990400 0x20>,
<0xff990420 0x20>,
<0xff990040 0x20>,
<0xff990060 0x20>;
reg-names = "local_request_region",
"local_response_region",
"remote_request_region",
"remote_response_region";
#mbox-cells = <1>;
xlnx,ipi-id = <2>;
};
};
};
3-2. Devicetreeの予約メモリ領域
予約メモリで定義されているのはLinux側とCR5側で情報のやり取りをするための、共有メモリです。
“rproc_0_reserved”は0x3ed00000から始まるDRAM領域です。これをずらして重ならないように、”rproc_1_reserved”を定義します。
- rproc_0_reserved: 0x3ED00000
- rproc_1_reserved: 0x3EF00000
他の領域(vring0,vring1,buffer)もおなじく定義します。
領域の用途ですが、正直よくわかっていません。重要なのはCR5の各コアでメモリ領域がオーバーラップしてはだめなことです。ただし、あとで触れますが、サンプルで使われている0x3ED00000付近はCMAメモリアロケータと干渉します。
rproc_N_reserved (N = 0,1) | CR5の一部のセクションがここに置かれる。 .text .bss .resource_table <-RPMsg用に必要な情報ヘッダ |
rpuNvdev0vring0 (N = 0,1) | VirtIOのリングバッファに見えるが実際はわからない。そうだとしたら送受信のどちらか。IPIのMailboxとどう役割分担しているのかもわからない |
rpuNvdev0vring1 (N = 0,1) | ↑に同じ |
rpuNvdev0buffer (N = 0,1) | debugfsに出力するためのトレースバッファ。 “/sys/kernel/debug/remoteproc/remoteprocN/trace0 “をcatして読める。 CR5の出力するメッセージを記録する。 |
3-3. DevicetreeのTCM(密結合メモリ)
CR5にはTCMと呼ばれる1サイクルアクセスが可能な低レイテンシメモリが搭載されています。CR5は0番地から実行を開始し、かつ、TCMも0番地から割当てのため、CA53側からバイナリをロードする必要があります。
TCMはATCMとBTCMの領域に分かれていて、バスもそれぞれ分かれています。
ここでポイントとなるのは3つです。
- SplitモードはATCMとBTCMが各64KB
- LockstepモードはATCMとBTCMが各128KB
- TCMはCA53から見えるようにアドレス空間に割当てられている
TCMはCR5から見て0番地から割当てられているのですが、バイナリを外部からロードできるようにCA53のアドレス空間では別アドレスからアクセスできるようになっています。DevicetreeではCA53から見える(Global Address)、TCMアドレスを定義します。
<引用:UG1085 Ch.4 Real-time Processing Unit>
3-4. DevicetreeのCR5コア
CR5コアのELFロード、起動停止管理を行う、Remoteprocドライバのための設定を定義します。Webで検索すると様々な記述方法がありますが、おそらくKernel v5.10系とv5.15系で仕様が変更されたことが要因の一つかもしれません。
注意点として以下をまず認定UbuntuのKernelのVerを確認します。
Xilinx Ubuntu22.04
$ uname -r
5.15.0-1031-xilinx-zynqmp
v5.15系ですね。次にデバイスドライバ(zynqmp_r5_remoteproc.c)のコンパチを見ると以下のようになります。Ubuntuの場合、Linux kernelのソースコードをgit cloneできます。詳しくは以前の記事を参照。
- v5.10以下 : compatible = “xlnx,zynqmp-r5-remoteproc-1.0”;
- v5.15以上 : compatible = “xlnx,zynqmp-r5-remoteproc”;
Webの検索でv5.10系は読み飛ばすと混乱しなくなります。
次にSplit、Lockstepモードの切替ですが、”1″と”0″で指定します。これもWeb上でどっちがどっちだ論争が繰り広げられていました。本環境では以下となります。
Xilinx認定Ubuntu22.04
5.15.0-1031-xilinx-zynqmp
- Splitモード(2コア):xlnx,cluster-mode = <1>;
- Lockstepモード(冗長1コア):xlnx,cluster-mode = <0>;
確認方法はKernelのドライバのソースコードを確認するしかないと思います。以前カーネルビルド記事を作成したのでリンクを貼っておきます。同じ5.15.0-1031-xilinx-zynqmpのソースを取得して、zynqmp_r5_remoteproc.cを確認します。
イメージ掴めないと思いますので、参考にXilinxのKernelを貼っておきます。認定Ubuntuで使用されているLinux Kernelではありませんので、あくまでも参考程度になります。
xlnx,cluster-mode = <>;を読み出しているドライバの箇所からたどります。
- https://github.com/Xilinx/linux-xlnx/blob/xlnx_rebase_v5.15_LTS/drivers/remoteproc/zynqmp_r5_remoteproc.c#L926
- https://github.com/Xilinx/linux-xlnx/blob/xlnx_rebase_v5.15_LTS/include/linux/firmware/xlnx-zynqmp.h#L261
3-5. DevicetreeのIPIとMailbox
IPIはコア間割込み機能(inter processor interrupts)で、Mailbox機能向けのバッファメモリ機能もあります。
Mailboxは正直難解で、まだよくわかっていません。
試行錯誤した結果、AVNETさんが公開されている情報で動かすことが出来ました。
“xlnx,ipi-id”を指定する箇所がIPI1つにつき2箇所あり、どちらかがCA53のIPIチャネル番号でもう一方がCR5のチャネル番号と思われます。しかし、Web検索するとばらばらで、明らかにCHが違う場合もあり、結局わかりませんでした。RPMsgドライバを読むのも諦めました。ちなみに、CR5ファームウェアもこのDevicetreeに一致した設定にする必要があり、これもデバッグの難しさを増す要因になりました。
“reg”の項目はMailboxに使用する、メッセージバッファの先頭アドレスです。
<引用:UG1085 Ch.13 Interrupts>
メッセージバッファはアドレス0xFF990000から割当てられています。Lockstep版(冗長1コア)Devicetreeの例では、CA53(APU)がチャネル7、CR5(RPU)がチャネル1に割当てられています。
各チャネルには32byteのRequestバッファとResponseバッファを8つ(SI Agent Nunberの数分)持っていています。
Lockstep版(冗長1コア)Devicetreeの例では以下のようになっています。
CA53->CR5 Request | Ch7,0xFF990600,32bytes | local_request_region |
CA53->CR5 Response | Ch7,0xFF990620,32bytes | local_response_region |
CR5->CA53 Request | Ch1,0xFF9900c0,32bytes | remote_request_region |
CA5->CA53 Response | Ch1,0xFF9900e0,32bytes | remote_response_region |
メッセージバッファのオフセットアドレスは以下のようになっているはずです…(ここは自信ありません)。TRMを見ても私の頭ではよく理解できませんでした。
Ch Number | Agent Number | MessageBuffer Offset |
---|---|---|
Ch0 | Agent1 | Request=0x00 Response=0x20 |
Ch1 | Agent2 | Request=0x40 Response=0x60 |
Ch2 | Agent3 | Request=0x80 Response=0xA0 |
Ch3 | Agent8 | Request=0x1C0 Response=0x1E0 |
Ch4 | Agent8 | Request=0x1C0 Response=0x1E0 |
Ch5 | Agent8 | Request=0x1C0 Response=0x1E0 |
Ch6 | Agent8 | Request=0x1C0 Response=0x1E0 |
Ch7 | Agent4 | Request=0xC0 Response=0xE0 |
Ch8 | Agent5 | Request=0x100 Response=0x120 |
Ch9 | Agent6 | Request=0x140 Response=0x160 |
Ch10 | Agent7 | Request=0x180 Response=0x1A0 |
この表を元に、Mailboxのアドレス設定を読み解くと、
CA53->CR5 Request(local_request_region)はCh7のMessagebuffer(0xFF990600)を割当て、”Requestオフセット=0x00″はCh0へのRequestを示していることになっています。Ch7ではなくなぜCh0なのか?と思いますが、意図はわかりません。
結局、設計意図が読み取れなかったので、解読は諦めました。
Split(2コア)の場合、Lockstep版のチャネルをCR5-0コアに設定し、CR5-1コアは新たなチャネルを割当てます。CR5Lockstep版のDevicetree設計意図が不明なので、Web上から動作する記述を探し、トライアンドエラーで実験しました。
Devicetreeのビルドとインストール方法は前章で説明したとおりです。
結果、先程記載したとおり、AVNETさんの公開情報で動かすことが出来ました。
3-6. CR5-0、CR5-1コアのEcho testファームウェア
CR5側もファームウェアのコードに修正を入れる必要があります。CR5-0コアはCR5Lockstep版をそのまま流用できます。CR5-1は修正が必要です。
まず、CR5-1用のプラットフォームプロジェクトと、アプリケーションプロジェクトを前回の記事と同じ様に追加で作成します。”Cortex-r5_1″で作成します。
リンカスクリプトの変更
リンカスクリプトでDRAMに配置するセクションがCR5-0コアと重ならないようにずらします。MEMORY定義でDDRの開始アドレスを変更します。
CR5-0 : DRAM開始アドレス 0x3ED00000
CR5-1 : DRAM開始アドレス 0x3EF00000
lscript.ldの該当箇所
(...)
_DDR_START = DEFINED(LINKER_DDR_BASE) ? LINKER_DDR_BASE : 0x3EF00000;
(...)
MEMORY
{
psu_ddr_S_AXI_BASEADDR : ORIGIN = _DDR_START, LENGTH = 0x00040000
psu_ocm_ram_1_S_AXI_BASEADDR : ORIGIN = 0xFFFF0000, LENGTH = 0x00010000
psu_r5_tcm_ram_0_S_AXI_BASEADDR : ORIGIN = 0x00000000, LENGTH = 0x00010000
psu_r5_tcm_ram_1_S_AXI_BASEADDR : ORIGIN = 0x00020000, LENGTH = 0x00010000
}
(...)
DRAMに配置するセクションは主に次の3つです。
- .text
- .bss
- .resource_table
resource_tableはRPMsgの情報ヘッダになっているので、DRAMに配置する必要があります。RemoteprocドライバがELFを解析する際に読み取るようです。デフォルトではDRAM開始アドレス+0x20000に配置されますので、特に修正する必要はありません。
IPI(コア間割込み)の設定変更
platform_info.hにIPI割込みの定数が定義されています。以下のマクロに変更が必要です。
- IPI_IRQ_VECT_ID
- POLL_BASE_ADDR
- IPI_CHN_BITMASK
該当箇所は”VERSAL_NET”、”versal”、”ZynqMP”の3環境分あるので、注意が必要です。今回は”ZynqMP”の部分を変更します。
//plarform_info.h
(...)
#else /* ZynqMP case */
#ifndef IPI_IRQ_VECT_ID
#define IPI_IRQ_VECT_ID XPAR_XIPIPSU_0_INT_ID
#endif /* IPI_IRQ_VECT_ID */
#ifndef POLL_BASE_ADDR
#define POLL_BASE_ADDR XPAR_XIPIPSU_0_BASE_ADDRESS
#endif /* POLL_BASE_ADDR */
#ifndef IPI_CHN_BITMASK
#define IPI_CHN_BITMASK 0x01000000
#endif /* IPI_CHN_BITMASK */
#endif /* VERSAL_NET */
(...)
表にまとめてみました。
マクロ | CR5-0 | CR5-1 |
IPI_IRQ_VECT_ID | XPAR_XIPIPSU_0_INT_ID ->XPAR_PSU_IPI_1_INT_ID ->->65U 説明:IPI_Ch1 GIC IRQ番号 | XPAR_XIPIPSU_0_INT_ID ->XPAR_PSU_IPI_2_INT_ID ->->66U 説明:IPI_Ch2 GIC IRQ番号 |
POLL_BASE_ADDR | XPAR_XIPIPSU_0_BASE_ADDRESS ->XPAR_PSU_IPI_1_S_AXI_BASEADDR ->->0xFF310000U 説明:IPI Ch1(RPU0) | XPAR_XIPIPSU_0_BASE_ADDRESS ->XPAR_PSU_IPI_2_S_AXI_BASEADDR ->->0xFF320000U 説明:IPI Ch2(RPU1) |
IPI_CHN_BITMASK | 0x01000000 IPI RPU_0_IERレジスタ 説明:割込み許可 bit24 : Ch 7 | 0x02000000 IPI RPU_1_IERレジスタ 説明:割込み許可 bit25 : Ch 8 |
IPI_IRQ_VECT_IDとPOLL_BASE_ADDRマクロはCR5-1用のプラットフォームプロジェクトとアプリケーションプロジェクトを作成していれば、xparameters.hの内容が対応するので、変更の必要がありません。ただし、一応実装を確認したほうが良いと思います。
AVNETさんの例ではCA53->CR5-1のIPI割込みのうち、CR5-1側はCh8を使用するようです。Devicetreeの”xlnx,ipi-id = <8>;”の記述はおそらくCR5-1側のIPI-Ch番号を指定していると思われます。
以上の修正が終わったらビルドします。
ビルドしたELFでセクションを確認してみます。
# CR5-0 FW
$ readelf -S app_echo_test_r5_0.elf
There are 31 section headers, starting at offset 0xcb818:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .vectors PROGBITS 00000000 010000 000638 00 AX 0 0 8
[ 2] .text PROGBITS 3ed00000 020000 012fd4 00 AX 0 0 8
[ 3] .init PROGBITS 00000638 010638 00000c 00 AX 0 0 4
[ 4] .fini PROGBITS 00000644 010644 00000c 00 AX 0 0 4
[ 5] .rodata PROGBITS 00000650 010650 001fad 00 A 0 0 8
[ 6] .data PROGBITS 00002600 012600 001100 00 WA 0 0 8
[ 7] .bootdata PROGBITS 00003700 013700 000180 00 WA 0 0 8
[ 8] .eh_frame PROGBITS 00003880 013880 000004 00 A 0 0 4
[ 9] .ARM.exidx ARM_EXIDX 00003884 013884 000008 00 AL 2 0 4
[10] .init_array INIT_ARRAY 0000388c 01388c 000004 04 WA 0 0 4
[11] .fini_array FINI_ARRAY 00003890 013890 000004 04 WA 0 0 4
[12] .ARM.attributes ARM_ATTRIBUTES 00003894 040100 00002f 00 0 0 1
[13] .bss NOBITS 3ed20100 040100 00175c 00 WA 0 0 4
[14] .heap NOBITS 00003894 013894 00400c 00 WA 0 0 1
[15] .stack NOBITS 000078a0 013894 003800 00 WA 0 0 1
[16] .resource_table PROGBITS 3ed20000 040000 000100 00 WA 0 0 256
[17] .comment PROGBITS 00000000 04012f 000012 01 MS 0 0 1
[18] .debug_line PROGBITS 00000000 040141 018149 00 0 0 1
[19] .debug_line_str PROGBITS 00000000 05828a 000138 01 MS 0 0 1
[20] .debug_info PROGBITS 00000000 0583c2 0258ad 00 0 0 1
[21] .debug_abbrev PROGBITS 00000000 07dc6f 007800 00 0 0 1
[22] .debug_aranges PROGBITS 00000000 085470 000708 00 0 0 8
[23] .debug_str PROGBITS 00000000 085b78 0230e3 01 MS 0 0 1
[24] .debug_loclists PROGBITS 00000000 0a8c5b 00fcb5 00 0 0 1
[25] .debug_rnglists PROGBITS 00000000 0b8910 00180d 00 0 0 1
[26] .debug_macro PROGBITS 00000000 0ba11d 008012 00 0 0 1
[27] .debug_frame PROGBITS 00000000 0c2130 0022b0 00 0 0 4
[28] .symtab SYMTAB 00000000 0c43e0 004690 10 29 640 4
[29] .strtab STRTAB 00000000 0c8a70 002c66 00 0 0 1
[30] .shstrtab STRTAB 00000000 0cb6d6 000140 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
D (mbind), y (purecode), p (processor specific)
# CR5-1 FW
$ readelf -S app_echo_test_r5_1.elf
There are 30 section headers, starting at offset 0x982c4:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .vectors PROGBITS 00000000 010000 000638 00 AX 0 0 8
[ 2] .text PROGBITS 3ef00000 020000 012fd4 00 AX 0 0 8
[ 3] .init PROGBITS 00000638 010638 00000c 00 AX 0 0 4
[ 4] .fini PROGBITS 00000644 010644 00000c 00 AX 0 0 4
[ 5] .rodata PROGBITS 00000650 010650 001fad 00 A 0 0 8
[ 6] .data PROGBITS 00002600 012600 001100 00 WA 0 0 8
[ 7] .bootdata PROGBITS 00003700 013700 000180 00 WA 0 0 8
[ 8] .eh_frame PROGBITS 00003880 013880 000004 00 A 0 0 4
[ 9] .ARM.exidx ARM_EXIDX 00003884 013884 000008 00 AL 2 0 4
[10] .init_array INIT_ARRAY 0000388c 01388c 000004 04 WA 0 0 4
[11] .fini_array FINI_ARRAY 00003890 013890 000004 04 WA 0 0 4
[12] .ARM.attributes ARM_ATTRIBUTES 00003894 040100 00002f 00 0 0 1
[13] .bss NOBITS 3ef20100 040100 00175c 00 WA 0 0 4
[14] .heap NOBITS 00003894 013894 00400c 00 WA 0 0 1
[15] .stack NOBITS 000078a0 013894 003800 00 WA 0 0 1
[16] .resource_table PROGBITS 3ef20000 040000 000100 00 WA 0 0 256
[17] .comment PROGBITS 00000000 04012f 000012 01 MS 0 0 1
[18] .debug_line PROGBITS 00000000 040141 013602 00 0 0 1
[19] .debug_line_str PROGBITS 00000000 053743 000138 01 MS 0 0 1
[20] .debug_info PROGBITS 00000000 05387b 01fb87 00 0 0 1
[21] .debug_abbrev PROGBITS 00000000 073402 006622 00 0 0 1
[22] .debug_aranges PROGBITS 00000000 079a28 000660 00 0 0 8
[23] .debug_str PROGBITS 00000000 07a088 004b9e 01 MS 0 0 1
[24] .debug_loclists PROGBITS 00000000 07ec26 00ec12 00 0 0 1
[25] .debug_rnglists PROGBITS 00000000 08d838 0016c8 00 0 0 1
[26] .debug_frame PROGBITS 00000000 08ef00 001fa8 00 0 0 4
[27] .symtab SYMTAB 00000000 090ea8 004680 10 28 639 4
[28] .strtab STRTAB 00000000 095528 002c66 00 0 0 1
[29] .shstrtab STRTAB 00000000 09818e 000133 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
D (mbind), y (purecode), p (processor specific)
3-7. Echo testを実行する
前回同様、Devicetreeをインストールして再起動します。remoteprocが2つ出現すれば成功です。
$ ls -1 /sys/class/remoteproc/
remoteproc0
remoteproc1
CR5-0、CR5-1のELFをZynqMPの/lib/firmwareに移動しておきます。
CR5の両コアを起動します。ELFのファイル名は適宜変えてください。
$ sudo sh -c "echo app_echo_test_r5_0.elf > /sys/class/remoteproc/remoteproc0/firmware"
$ sudo sh -c "echo app_echo_test_r5_1.elf > /sys/class/remoteproc/remoteproc1/firmware"
$ sudo sh -c "echo start > /sys/class/remoteproc/remoteproc0/state"
$ sudo sh -c "echo start > /sys/class/remoteproc/remoteproc1/state"
$ ls -1 /sys/bus/rpmsg/devices/
virtio0.rpmsg-openamp-demo-channel.-1.1024
virtio0.rpmsg_ctrl.0.0
virtio0.rpmsg_ns.53.53
virtio1.rpmsg-openamp-demo-channel.-1.1024
virtio1.rpmsg_ctrl.0.0
virtio1.rpmsg_ns.53.53
RPMsgのVirtIOが2つ出現したら成功です。
Echo test(Linux)を実行する
前回OpenAMP公式のGithubリポジトリでソースビルドして実行しました。v2024.05ブランチの最新のものであれば、SysfsのVirtIOファイルを検索してくれるので、CR5-0、CR5-1コア用の修正は必要ありません。ただし、VirtIOが2つあると判別できないようなので、CR5-0を停止します。
$ sudo sh -c "echo stop > /sys/class/remoteproc/remoteproc0/state"
$ ls -1 /sys/bus/rpmsg/devices/
virtio1.rpmsg-openamp-demo-channel.-1.1024
virtio1.rpmsg_ctrl.0.0
virtio1.rpmsg_ns.53.53
Echo testを実行します。
#ドライバのロード
$ sudo modprobe rpmsg_char
# Echo test実行
$ sudo ./openamp-system-reference/examples/linux/rpmsg-echo-test/echo_test
Echo test start
using dev file: virtio1.rpmsg-openamp-demo-channel.-1.1024
open /sys/bus/rpmsg/devices/virtio1.rpmsg-openamp-demo-channel.-1.1024/driver_override
write virtio1.rpmsg-openamp-demo-channel.-1.1024 to /sys/bus/rpmsg/drivers/rpmsg_chrdev/bind
opendir /sys/bus/rpmsg/devices/virtio0.rpmsg_ctrl.0.0/rpmsg
opendir /sys/bus/rpmsg/devices/virtio1.rpmsg-openamp-demo-channel.-1.1024/rpmsg
open /dev/rpmsg_ctrl0
main():137 app_rpmsg_create_ept: rpmsg-openamp-demo-channel[src=0,dst=0x400]
checking /sys/class/rpmsg/rpmsg_ctrl0/rpmsg0/name
svc_name: rpmsg-openamp-demo-channel
.
open /dev/rpmsg0
**************************************
Echo Test Round 0
**************************************
sending payload number 0 of size 17
echo test: sent : 17
received payload number 0 of size 17
sending payload number 1 of size 18
echo test: sent : 18
received payload number 1 of size 18
sending payload number 2 of size 19
echo test: sent : 19
(...)
sending payload number 470 of size 487
echo test: sent : 487
received payload number 470 of size 487
sending payload number 471 of size 488
echo test: sent : 488
received payload number 471 of size 488
**************************************
Echo Test Round 0 Test Results: Error count = 0
**************************************
VirtIO1側がOpenされ、テストが通りました。CR5-0側も同様にクリアしました。
しかし、再起動は前回と同じくVirtIO busyになってしまい、2コアともに不可能でした。
4.まとめ
続編となる今回は、CR5 Split(2コア)動作をやってみました。
- CR5 Split動作でELFのロード及びコアの起動、停止
- Echo testサンプルを実行し、Pass
- CR5側のファームウェアはベアメタル版で作成
- Echo testサンプルの2回目の実行はVirtIO busyのため不可
今回もEcho testサンプルの2回目の実行は一度も成功せず、原因もまだわかっていません。もう一度動かしたい場合はLockstepの場合と同じく、CR5を一度停止して再起動する必要がありました。
この記事のコード類は私のGithubに残しておきます。