GUIXをThreadX以外のOSで動かす

UI開発

はじめに

GUIXとは、ExpressLogic社が開発した組込み向けのGUI (Graphical User Interface) ツールです。
現在はEclipseFoundationが管理・公開しているOSS (Open Source Software) です。
過去の記事にも記載がありますのでご興味がある方は参照してみてください。

GUIXの動作環境

GUIXは組込み向けのGUIツールですが、デフォルトでは「Eclipse ThreadX(以後ThreadX)」のAPIを使用するようにコーディングされています。

GUIXは動作する際に一般的なタイマなどの組込みOSの機能を必要とするため、ThreadX以外の組込みOSで動作させる場合、この部分の対応が必要となります。

GUIXのOSインタフェース

GUIXのマニュアルにも記載がありますが、GUIXをThreadX以外の組込みOSで動作させる場合の為に、OSインタフェースが定義されています。

GUIXをビルドする際に「GX_DISABLE_THREADX_BINDING」と言うコンパイルスイッチを定義することでThreadXではなく、ThreadX以外のOSを使用するためのインタフェースを呼び出すようになります。

OSインタフェースの実装について

GUIXのThreadX以外のOS機能を呼び出す実装は以下のソースコードに実装します。

gx_system_rtos_bind.c
gx_system_rtos_bind.h

「GX_DISABLE_THREADX_BINDING」を定義すると、GUIXのソースコードからはgx_system_rtos_bind.hに記載されている「GX_RTOS_BINDING_INITIALIZE」のようなマクロが呼び出されます。
マクロでは「gx_generic_rtos_initialize()」の様に小文字の関数が定義されており、この関数の実体がgx_system_rtos_bind.cにあります。
ですので、gx_system_rtos_bind.cの各関数の中身を実装し、使用するOSの機能を使用するようにポーティングできれば、動作が可能になります。
ポーティングの必要な関数の詳細はGUIXのマニュアルを参照頂きたいですが、おおよその必要な機能は、初期化(セマフォなどの資源生成やタスクの生成など)、イベントキュー処理(イベントキューへ入れたり取り出したりする機能など)、タイマ関係の処理になります。
以下に当記事の執筆時点での関数一覧を載せます。

#関数名内容
1gx_generic_rtos_initialize初期化関数
2gx_generic_thread_startタスク(スレッド)の開始
3gx_generic_event_postイベントをイベントキューに入れる
4gx_generic_event_popイベントキューからイベントを取り出す
5gx_generic_event_foldイベントをイベントキューに入れるが同じイベントがある場合は1つにまとめる
6gx_generic_event_purgeWidgetに関連するイベントを削除する
7gx_generic_timer_startタイマ開始(多くの場合、タイマタスクのレジュームを行います)
8gx_generic_timer_stopタイマ停止(多くの場合、タイマタスクのサスペンドを行います)
9gx_generic_system_mutex_lock排他制御開始
10gx_generic_system_mutex_unlock排他制御終了
11gx_generic_system_time_get現在のシステム時刻取得(チック数)
12gx_generic_thread_identifyタスク(スレッド)識別子の取得
13gx_generic_time_delayタスク(スレッド)の休止
14gx_generic_error_processエラー発生時のコールバック関数

ポーティングの際の注意点

ポーティングする際の注意点を書いておきます。

gx_generic_event_fold

gx_generic_event_fold()は、イベントキューに入れようとする種類のイベントが既にキューにあった場合にまとめて1つのイベントにする必要があります。
主にドラッグ時やタイマイベント時に使用されます。
どちらも、短時間で大量のイベントを発生させる可能性があるため、まとめる機能が無いとイベントキューが溢れてしまいます。

gx_generic_event_purge

gx_generic_event_purge()はイベントキューから指定されたWidgetのイベントを削除します。
主にWidgetを削除する際に使用されます。Widgetがなくなるのでイベントキューからも削除する必要があります。

guix_timer_task_entry

guix_timer_task_entry()はGUIXのチックを生成するタスクになります。
ThreadXを使用する場合はThreadXのタイマ機能を使用するので不要ですが、ThreadX以外のOSを使用する場合にGUIXにチックを供給する必要があります。
実装としては複雑ではなく一定周期で_gx_system_timer_expiration()を使い、GUIXのイベントキューにタイマイベントを送るだけになります。
この時、「OSチック=GUIXチック」としてしまうと、GUIXのタイマ精度は良いですが負荷が大きくなります。かと言ってGUIXチックを大きくしてしまうとGUIXのタイマ精度が粗くなりドラッグやボタンWidgetのリピートなどに影響が出る場合があります。
この辺りの調整はシステムとしてのタスク設計なども絡みますので一概に「この値」と言うものはありません。
ですが、GUIでは機器制御のような数msなどの精度は必要ないと思いますのであまりシビアに考えなくても良いと思います。

動作確認

ポーティングできているかの動作確認には、GUIXに付属するサンプルやチュートリアルを動かしてみるのが良いと思います。
特にdemo_guix_medicalやdemo_guix_home_automationでは、タイマを使用した動きのあるサンプルなのでポーティングを一通り確認することが出来ると思います。
ただし、GUIXのサンプルの画面サイズと使用する機器の画面サイズが異なるとうまく表示が出ない可能性もありますのでご注意ください。

まとめ

いかがでしたでしょうか。
GUIXは元々ThreadXで動作するように作られていますが、OSのインタフェースが定義されていますのでThreadX以外のOSでも比較的短期間で動作させることは可能と思います。
当社では過去にuITRONで動作させることも行っています。また、デモでの動作になりますが、現在当社で取り扱っている「PX5 RTOS」でも動作させています。
GUIXは比較的性能の低いCortex-M系のCPUでも動作するように設計されている、非常に軽いGUIツールになります。そのため、組込みLinuxが動作できない環境で選択される、uITRON環境でのGUIツールとしても選択肢になると思います。
もしご興味があれば当社までご連絡いただければと思います。