Linux に平行してベアメタルプログラムを走らせる
CPU でリアルタイム処理をしたい†
UI や通信に関する処理を Linux で行いつつ、
リアルタイム性能の必要な処理を別途動かしたい。
Zynq には CPU が2つあるので、1つを Linux に、 1つをベアメタルに使えば完全な並列処理ができるはず?
http://www.wiki.xilinx.com/Real-Time+Linux によれば、
IRQ Affinity という機能で、Linux で受け取る IRQ を特定の CPU
に回すという方法もあるらしい。そちらの CPU を常時 Idle にしておき、
割り込み処理中の追加割り込みを禁止できるなら、Linux
だけでリアルタイム処理ができるのかもしれないけれど、
そういう話にはなっていないようで。
まだまだ道半ばです†
結構大変・・・
資料†
シンプルな AMP : 2 つの Zynq SoC プロセッサ上で動作する Linux およびベアメタルシステム
https://japan.xilinx.com/support/documentation/application_notes/j_xapp1078-amp-linux-bare-metal.pdf
上記に対する最新の補遺
http://www.wiki.xilinx.com/XAPP1078+Latest+Information
むしろこっちが最新か?
http://www.wiki.xilinx.com/Multi-OS+Support+(AMP+%26+Hypervisor)
FPGAマガジンの16に FreeRTOS をメインに動かして、 後から Linux を起動する方法が書かれている。
OpenAmp
https://github.com/OpenAMP/open-amp
http://www.wiki.xilinx.com/OpenAMP
これを読めばいいのかも。
OpenAmp を使えるとよさそう†
https://github.com/OpenAMP/open-amp
Xilinx の OpenAmp というしくみを使うと、 CPU0 で走る Linux アプリから FreeRTOS や ベアメタル アプリを CPU1 で立ち上げたり、 そのリモートアプリとの間で通信をしたり、リモートアプリに Linux の資源を使わせたり できるとのことで、まさに欲しかった機能と言えます。
- OpenAmp の機能
- remoteproc ホストからリモートのプロセスを制御する
- RPMsg ホストとリモートとの間での通信手段を提供する
OpenAmp は petalinux を前提としていて、libmetal に依存しているのだそうです。
petalinux†
Xilinx がメンテナンスしている Linux ディストリビューション。
開発環境、ブートローダ、カーネル、ソフトウェアパッケージ、すべてがこれでまかなえる。
ただし設定、コンパイル、デプロイにものすごく時間がかかるので、 そのままの形で開発に使うには向かないのかも。
- 電気回路/zynq/Petalinux のビルド
とりあえず標準の形で起動可能な SD カードを作成するところまで
- 電気回路/zynq/Petalinux のカスタマイズ
いろいろカスタマイズして開発環境を整えた内容
上記で以下を実現できています。
- カーネルとして Linux 4.6.0-xilinx をカスタマイズして使える
- Ubuntu 16.04 のパッケージングシステムを使える
- /boot/uEnv.txt の書き換えで bootargs その他の起動方法を変更できる
- /boot/system.bit.bin の書き換えでロジックを変更できる
- /boot/devicetree.dtb の書き換えでデバイスを追加できる
- 電気回路/zynq/Device Tree Overlay の手順で、 Linux を再起動せず device tree を書き換えられる
libmetal†
https://github.com/OpenAMP/libmetal
linux, freertos, baremetal で共通に使えるライブラリ API を提供し、 デバイスへのアクセスや割り込み制御、メモリ確保、その他ユーティリティ機能を提供するもの のようです。
- Linux user space (based on UIO and VFIO support in the kernel)
- RTOS (with and without virtual memory)
- Bare-metal environments
となっているので、metal_xxx という共通の名前の関数ではあるものの、 環境によって実装を変え、適切な API 呼び出しに変換してくれる、ということみたい。
petalinux ではチェックボックス一つでインストール可能?†
petalinux-config -c rootfs で選択できるので、 チェックするだけでインストールできルっぽい?
ただこれでやるとユーザープロジェクトもすべて petalinux のビルドシステムを使わなければならなくなってややこしい。
GitHub で公開されているソースから単独でインストールできないものか、
と四苦八苦したのがこちらですが、どうやらこういう使い方をするものじゃないみたい。
電気回路/zynq/libmetal のインストール ← あんまり意味が無いことが後から判明
そうじゃなくて Xilinx SDK から使うべき†
libmetal も openamp も、ビルドには手順に沿って board support package (BSP) を使わないと、 必要なライブラリへのパスを通すのにも一苦労します。
Petalinux の操作を全て覚えればできるのかもしれませんが、片手間でやるには Xilinx SDK の GUI から使わないととてもじゃないけど使いこなせない感じ。
以降、そっちでやってみます。
Xilinx SDK から OpenAMP を使う†
リポジトリは https://github.com/OpenAMP/open-amp にあるけれど、 Xilinx SDK から使う分にはそのあたりを気にする必要はないようです。
これに沿ってやってみるのが良さそう
https://www.xilinx.com/support/documentation/sw_manuals/xilinx2017_3/ug1186-zynq-openamp-gsg.pdf
echo-test†
CPU-0 で実行中の Linux から、
CPU-1 用に standalone 実行ファイルを読み込んで走らせる。
CPU-0 側から送った文字列を CPU-1 側から返して画面に表示する。
standalone 側の準備†
プロジェクトの作成†
- Project name: echo_stdalone
- OS Platform: standalone
- Processor: ps7_cortex9_1
- Language: C (C++ を選ぶと目的のテンプレートが表示されない)
- BSP: Create new
で [Next]
- Available Template: OpenAMP echo test
で [Finish]
プロジェクトができた。
echo_stdalone_bsp を Build する†
まずはいくつか設定
bsp プロジェクトを右クリックから [Board Support Package Settings]
[Overview]-[drivers]-[ps7_cortexa9_1] を選んで [extra_compiler_flags] を確認すると、 _open(), _close(), _read(), _write() をマスター側にリダイレクトするためのオプション
- -DUNDEFINE_FILE_OPS
はすでに登録されていた。
vector table を OCM に置くのが一般的なようで、
- -DVEC_TABLE_IN_OCM
も指定しておくと良いみたい。
リソースの初期化をマスター側で行う場合に必要な
- -DUSE_AMP=1
も指定しておく。
[Ok] して bsp プロジェクトを build した。
LANG:console xscugic.c:248:2: warning: #warning "Building GIC for AMP" [-Wcpp] #warning "Building GIC for AMP" ^ xscugic_hw.c: In function 'DistInit': xscugic_hw.c:118:3: warning: #warning "Building GIC for AMP" [-Wcpp] #warning "Building GIC for AMP" ^
なんか warning 出た。
GIC は Generic Interrupt Controller だけど、 このライブラリを bsp から外した方が良いということかしら???
ソースファイルを見ると、
xscugic.c
LANG:c static void DistributorInit(XScuGic *InstancePtr, u32 CpuID) { u32 Int_Id; u32 LocalCpuID = CpuID; u32 RegValue; #if USE_AMP==1 && (defined (ARMA9) || defined(__aarch64__)) #warning "Building GIC for AMP" /* * GIC initialization is taken care by master CPU in * openamp configuration, so do nothing and return. */ return; #endif RegValue = XScuGic_DistReadReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET); if (!(RegValue & XSCUGIC_EN_INT_MASK)) { ...
xscugic_hw.c
LANG:c static void DistInit(XScuGic_Config *Config, u32 CpuID) { u32 Int_Id; u32 LocalCpuID = CpuID; #if USE_AMP==1 #warning "Building GIC for AMP" /* * The distrubutor should not be initialized by FreeRTOS in the case of * AMP -- it is assumed that Linux is the master of this device in that * case. */ return; #endif XScuGic_WriteReg(Config->DistBaseAddress, XSCUGIC_DIST_EN_OFFSET, 0U); ...
となっていて、むやみに初期化してしまわないようにしている。
たぶん無視していいっぽい。
include の下に大量の .h ファイルができた
echo_stdalone を Build†
Binaries の下に echo_stdalone.elf ができた
Linux 側の準備†
上記の pdf では
- PetaLinux 上でリモート側のアプリをビルドして、
できたファームウェアを /lib/firmware/<myfirmware> に入れる - petalinux-config でカーネルベースアドレスを 0x10000000 にする
ベアメタルアプリのブートサポートがアドレス 0 からになるため - u-boot Configuration で netboot offset を (0x11000000) にする
- Enable loadable module support にチェックを付ける
- Device Drivers ---> Generic Driver Options ---> Userspace firmware loading support にチェックを付ける
- Device Drivers ---> Remoteproc drivers ---> Support ZYNQ remoteproc にチェックを付ける
- Kernel Features ---> Memory split (...)---> 2G/2G user/kernel split を選択 (1G/3G でも可)
- Kernel Features ---> High Memory Support にチェックを付ける
- rootfs の
(以下未稿)
添付ファイル:











