本記事は全三回構成の第二回です。前の記事をまだお読みでない方は
第一回記事「PX5 MODULESについて解説してみた Part1」からお読みください。
PX5 MODULESを使用したアプリケーションイメージ
PX5 MODULESを使用したアプリケーションは、マネージャー側といくつかのユーザーモジュール(複数のユーザーモジュールも可)を組み合わせて動作します。

ユーザーモジュールはメモリが許す限り、いくつでも同時に動作させることが可能です。
マネージャー側からモジュールを起動する
マネージャー側からモジュールを起動する前に、モジュール(一般的な設定では、xxx.outファイルやxxx.binファイル)をメモリ上に読み込んでおく必要がありますが、読み込む処理(ダウンロード等)そのものについてはPX5 MODULESには用意されていません。例えばUSBメモリやFTPによるダウンロード等の操作はPX5 MODULES本体の機能とは言えないため、別途マネージャー側のアプリケーションとして用意する必要がありますが、その分読み込み元を限定せずに、各種メディアやネットワークプロトコルを選択できるメリットがあります。またモジュールのコードは読み込まれたメモリ上で動作しますので、コードが実行可能な領域を使用する必要があります。
モジュールを起動する手順は非常にシンプルです。メモリ上にモジュールが読み込まれた後は、モジュールを起動するAPI (px5_module_manager_create())を呼び出すだけでモジュールを起動することができます。px5_module_manager_create()には、モジュールが読み込まれたメモリおよびモジュールで使用するデータ領域を指定します。
px5_module_manager_create()を呼び出した後、モジュール側はエントリ関数(module_entry())から動作を開始し、必要な動作を行います。このためエントリ関数はモジュール内に必ず一つ用意する必要があります。同様に終了関数(module_exit())も用意する必要がありますが、終了時に特に処理が無い場合は、空の関数で問題ありません。
マネージャー側とモジュールの連携
マネージャー側からモジュールを起動する際、モジュールに対してパラメーターを渡すことができます。このパラメーターによって、モジュールの基本動作を変更することが可能で、一つのモジュールであっても、起動時から動作を変更することができます。
またモジュールからは、マネージャー側にリクエストを出すAPI (px5_module_application_request())を使用して、各種処理をマネージャー側で行うことが可能です。px5_module_application_request()を使用するためには、マネージャー側にリクエストを処理するためのハンドラを登録しておく必要がありますが、リクエストの種類や定義に基本的な制限は無く、ハンドラ処理内でのメモリプロテクションの扱いはマネージャー側と同じですので、モジュールでは制限がかかる処理を行うことも可能です。またハンドラ処理を工夫することで、モジュール間でデータをやり取りすることも可能です。

優先度の扱い
マネージャー側とモジュールで動作するスレッドには、それぞれのスレッドに個別に優先度を設定していますが、優先度の扱いはマネージャー側とモジュールで同一です。またモジュール内部でスレッドを追加することも可能ですが、この内部スレッドに設定された優先度の扱いも、マネージャー側のスレッドも含めて同一の扱いです。
ただし、モジュールが高優先度に設定されマネージャー側が動作できなくなるような状態を防ぐため、モジュール内部で設定できる優先度の上限値を指定できるようになっています。範囲内であればモジュールの処理で優先度を操作することはできますが、上限値の制限がありますので、マネージャー側スレッドの優先度設定と合わせて、アプリケーション全体の優先度設定を検討したほうが良いでしょう。
メモリプロテクションとpx5_module_application_request()の動作
マネージャー側はモジュールの管理や割り込み処理を行う前提のため、基本的にはメモリプロテクションを設定できませんが、モジュールはモジュールディスクリプションの設定により、メモリプロテクションを設定することができます。またモジュールは基本的にはメモリ上に自由に配置できますが、メモリプロテクション管理の都合上、使用できるメモリ範囲、実際には通常開始アドレスには制限が付きます。メモリプロテクションはMMU(Memory Management Unit)やMPU(Memory Protection Unit)を利用して実現しているため、制限はターゲットCPUや実装によって異なります。例えば開始アドレスの下位4バイトは0(0xXXXX0000)でなければならない、などがあります。
PX5 MODULES が提供するメモリプロテクション機能はMMU/ MPUを使用する前提ですので、提供可能なCPUはMMU/MPUを持っているものが対象です。またMMU/MPUで使用するTLB(Translation Lookaside Buffer)は、px5_module_manager_create()を呼び出したときに内部で用意しますので、ユーザーアプリケーション側で設定する必要はありません。
px5_module_application_request()はモジュールからマネージャー側へリクエストを送るAPIですが、ソフトウェア割り込み(SWI)を利用して実現しています。メモリプロテクション管理があるため、SWI以外でのリクエスト処理は難しいですが、リクエスト毎にSWI処理のためのオーバーヘッドがかかります。またディスパッチ時にMMU/MPUの設定切り替えのためのオーバーヘッドもかかります。これはマネージャー側のみでディスパッチする場合にも発生します。
アプリケーション全体としては、このオーバーヘッドも考慮する必要があり、例えばモジュールからpx5_module_application_request()を呼び出す頻度等も考慮したほうが良いでしょう。
モジュールでPX5 FILEとPX5 NETを使用する
PX5 MODULE Codeでは、モジュールでPX5 FILEとPX5 NETを使用できる機能を提供しています。recv_zerocopy()などのマネージャー側のメモリを直接操作できるようなAPIは使用できませんが、通常の処理で使用するAPIは一通りサポートしています。
初期化等はマネージャー側で行い、当然マネージャー側でもPX5 FILEとPX5 NETは使用可能です。またマネージャー側でもモジュールでも、使い方は同じです。ただしモジュールではpx5_module_application_request()と同様にSWIによってAPIが実装されているため、オーバーヘッドは考慮しておく必要があります。
