組込み製品開発に不可欠なクロスプラットフォーム開発とは
組込み製品をセルフプラットフォーム開発することの難しさ
汎用PC上で動作するソフトウェアは、開発から実行までを同じアーキテクチャ上で行うセルフプラットフォーム開発(セルフ開発:下図)で実装されます。汎用PC上で動作するエディタや開発ツール、統合開発環境(IDE)などを利用してプログラムを実装し、ビルドして、テストします。一連の開発は、実行環境と同じ汎用PCのCPU、メモリ、ストレージなどのリソースを利用し、アーキテクチャをまたぐことなくソースコードからバイナリイメージを生成します。近年注目を集めているVisual Studio Code等の開発ツールを簡単に利用できることも、セルフ開発のメリットです。

汎用PC(エンタープライズLinux)は十分なリソースを持つため、セルフ開発手法が一般的
一方、組込み機器上で動作するソフトウェアを同じ組込み機器上で開発することはほぼ不可能です。組込み機器は、その用途に必要で十分な最低限のハードウェアリソースのみを有し、これらのリソースを最大限活用し、最良のパフォーマンスを達成するように設計されています。そのため、開発ツールや統合開発環境を実行するために必要な余剰なリソースは一切ありません(下図)。GUIの無い組込み機器も珍しくないでしょう。そのため、Visual Studio Code等のモダンなツールを活用したセルフ開発は不可能です。さらには、組込み機器のCPU、メモリ、ストレージといったコンピューティングリソースはビルドのワークロードに適した設計でないため、バイナリイメージを生成する作業には多大な時間を浪費してしまいます。こうした理由から、組込み機器の開発では基本的にセルフ開発を採用しません。

組込みシステムは実行に必要なリソースのみを持ち、開発に必要なリソースを搭載しない
クロスプラットフォーム開発(クロス開発)
こうした理由から、組込みLinuxのソフトウェア開発では、開発時と実行時でアーキテクチャが切り替わる「クロスプラットフォーム開発」が主流となっています。クロスプラットフォーム開発では、ソースコードを汎用PCアーキテクチャ上で、プログラムをエディタや統合開発環境(IDE)により実装し、クロスコンパイラを使用して組込み製品のアーキテクチャに対応したバイナリイメージを生成し、プラットフォームをまたいで、ターゲットデバイスのアーキテクチャ上でバイナリイメージを実行します(下図)。

ホストPCによりターゲットデバイス用のソフトウェアを実行できるクロスプラットフォーム開発
クロス開発により生成できるバイナリイメージは、組込みLinuxに組み込まれるアプリケーション、ミドルウェア、デバイスドライバ、カーネルなど多岐に渡ります。いずれもターゲットデバイスのCPUに対応した命令(ISA:命令セットアーキテクチャ)で構成され、ターゲットデバイス上にインストールされている組込みLinuxのミドルウェア、ライブラリ、カーネルと連携して動作可能です。また、クロス開発により汎用PCを開発に利用できることから、GUIを備えていないターゲットに対しても、Visual Studio Code等のモダンなツールで開発することができます(右図)。

ホストPC上のVisual Studio Codeを使って開発できる
クロスプラットフォーム開発に欠かせないQEMU
クロス開発により汎用PC上でターゲットデバイスのソフトウェアを開発することはできますが、組込み製品開発では、肝心なターゲットデバイスを入手出来ないことが多々あります。その背景には、ソフトウェアとハードウェアを並行して開発するプロジェクトである場合や、世界的な半導体の供給不足の影響によるもの、ターゲットデバイス1基が非常に高価であり開発者全員分のターゲットデバイスを準備する予算を確保できないことなど様々な理由があります。
こうした状況を打破できる開発ツールがQEMUです。仮想的なハードウェアプラットフォームを生成できるQEMUは、リードタイムゼロ、コストゼロであらゆるターゲットデバイスを汎用PC上に生成することができます。CPUの種別(Intel x86 64-bit、Arm、PowerPC、etc.)や、CPUの構成(シングルコア/マルチコア)、メモリの搭載量、ストレージの搭載量、仮想ネットワークデバイスなどをはじめとする周辺装置(ペリフェラル)の構成など様々なコンフィグレーションが可能です。ただし、QEMUは汎用PC上で、ターゲットデバイス向けのアセンブラコード(例:Arm 64-bit)をすべてソフトウェアにより解読し、エミュレートすることから、実機と比べると動作が非常に遅くなります。特にGUIなど、リッチな機能をテストするためには多くの時間が必要となることを覚えておきましょう。
QEMUを使うことにより、お客様の組込み製品に採用予定のターゲットデバイスと同等の仮想ハードウェアを汎用PC上に生成し、クロス開発で生成したバイナリイメージを手元で直ぐに実行して評価することができます。これによりターゲットデバイスのない状況であってもソフトウェアの開発を推進できる、ターゲットレスな組込み製品開発を実現可能です(下図)。

ターゲットレスな開発を実現できるクロスコンパイラとQEMU
Wind River LinuxのSDKは、クロスプラットフォーム開発環境を提供します。クロスコンパイラをはじめとするターゲットデバイス向けの開発ツールをはじめ、ターゲットデバイスのISAをエミュレートできるQEMUを同梱しています。さらに詳しいWind River Linuxの特徴は、下記の「Wind River Linuxが選ばれる理由」をご参照ください。
Wind River Linuxが選ばれる理由「基礎からわかるWind River Linux -商用組込みLinux製品のメリットとは」
はじめてのクロスプラットフォーム開発で組込みLinuxアプリケーションを開発しよう
それでは実際に、汎用PCと異なるアーキテクチャ(プラットフォーム)上で動作するWind River Linux 向けの組込みLinuxアプリケーションを開発する方法についてご説明します。Wind River Linuxのアプリケーション開発では、Wind River Linuxで生成できるSDKを利用します。開発は下記の手順で行います。
- 開発/実行環境の準備
- Wind River SDKの生成とインストール
- アプリケーションの開発
- アプリケーションのデプロイと実行
開発/実行環境の準備
Wind River Linux をQEMUで実行するには、LinuxをインストールしたホストPCが必要です。推奨されるホストPCの要件は「Wind River Linux Release Notes:Host System Recommendations and Requirements」をご確認ください。また、「Necessary Linux Host System Libraries and Executables」に掲載されているパッケージも事前にインストールしてください。
Wind River Linux SDKの生成とインストール
Wind River Linuxでは、"bitbake"コマンドのオプションに"-c popurate_sdk"を付与することで、作成したLinuxディストリビューションに対応したSDKを生成することができます。生成したSDKを利用することにより、ターゲットデバイス用のアプリケーションやミドルウェアを汎用PC上で開発することができます。また、QEMUも同梱されており、ターゲットデバイス無しで作成したLinuxディストリビューションの実行が可能です。
図は”bitbake”コマンドで生成されたSDKです。SDKの名前は"wrlinux-10.24.33.4-glibc-x86_64-bcm_2xxx_rpi4-wrlinux-image-std-sdk.sh"です。

”bitbake”コマンドで生成されたSDK"wrlinux-10.24.33.4-glibc-x86_64-bcm_2xxx_rpi4-wrlinux-image-std-sdk.sh"
SDKのインストールは” wrlinux-10.24.33.4-glibc-x86_64-bcm_2xxx_rpi4-wrlinux-image-std-sdk.sh”を実行し、/home/

アプリケーションの開発
それでは実際にアプリケーションを実装してみましょう。Visual Studio CodeとExtensionのインストールは「Installing the Wind River Studio Extension Visual Studio Code Getting Started, 24.08」を参照下さい。まず使用するSDKを設定します。Wind River Studio Extension ViewのRESOURCESの右の”+”をクリックして、Add SDK -> Add SDK from Local SDK Folderを選択して、"wrlinux-10.24.33.4-glibc-x86_64-bcm_2xxx_rpi4-wrlinux-image-std-sdk.sh"をインストールしたフォルダを選択します。

設定されるとRESOURCESのSDK Managerのcustomized-sdkに設定したSDKが✓マークで表示されます。
次にSDKに同梱されているQEMUターゲットを登録します。Wind River Studio ExtensionのRESOURCESの右の”+”をクリックして、Add Target -> qemu -> Wind River Linuxを選択し、SDKをインストールしたフォルダ配下のsysroots/x86_64-wrlinuxsdk-linux/usr/bin/qemu-system-aarch64を選択します。Select kernel file to bootのウインドウでSDKをインストールしたフォルダ配下のsysroots/cortexa72-wrs-linux/boot/Imageを選択し、Select rootfs image fileのウインドウでWind River Linuxをビルドしたフォルダのbuild/tmp-glibc/deploy/images/bcm-2xxx-rpi4/wrlinux-image-std-bcm-2xxx-rpi4.rootfs.ext4を選択します。最後にターゲットの名前を指定します(例:qemu_WindRiverLinux_rpi4)。登録したターゲットはRESOURCESのTarget Connectionsに表示されます。

この例ではアプリケーション開発で使うフォルダをmy-wr-appとします。Visual Studio Code Explorer ViewでFile -> Add Folder to Workspaceとしてmy-wr-appフォルダを追加します。WORKSPACEに追加されたmy-wr-appを右クリックし、New WR Application Projectを選択します。インストールしたSDKを選択、次にMakefile APP、environment-setup-cortexa72-wrs-linuxを選択すると、helloworld.cを含むサブディレクトリがmy-wr-app配下に作成されます。my-wr-appを右クリックしてBuild WR Application Projectを選択します。

ビルドが成功すると、OUTPUTウインドウに以下のように表示されます。

アプリケーションのデプロイと実行
アプリケーションを実行するために、QEMUを起動します。Wind River Studio Extension ViewのRESOURCESのTarget Connectionsに登録したqemu_WindRiverLinux_rpi4を右クリックし、Launch Simulatorを選択します。

qemuの起動が完了するとログインプロンプトが表示されます。

Explorer Viewのmy-wr-app.outを右クリックし、Add WR Application Launchを選択し、登録したターゲット(qemu_WindRiverLinux_rpi4)を選択します。

Run and Debug Viewで上の緑の三角をクリックし、アプリケーションを起動します。

起動後、結果がOUTPUTウインドウに表示されます。
