このページでは

C

アプリケーションのバックエンドの開発 (TRAVEO T2G)

このトピックでは、GHS MULTI IDE を使用してアプリケーションのバックエンドを作成およびビルドする手順について説明します。バックエンドにより、アプリケーションの UI はプラットフォームと通信し、ハードウェアから必要な情報を取得できるようになります。この例では、デバイスインターフェースがオンボードのユーザーボタンのステータスを取得します。 次の図は、これら2つのコンポーネント間の相互作用を示しています:

アプリケーションのUIとバックエンド間の連携。

アプリケーションおよびプラットフォームのソースコードのエクスポート

このセクションでは、Qt for MCUs ツールによってエクスポートされたアプリケーションおよびプラットフォームのソースコードをすべて含んだ、QmlProjectからGHS MULTI IDEプロジェクトを作成するための手順を段階的に説明します。

注: TRAVEO T2G CYT4DNまたはTRAVEO T2G Cluster 4M Lite Kitを使用している場合は 、以下の手順において「tviic2d4m-baremetal 」をそれぞれ「tviic2d6m-baremetal 」または「tviic2d4mlite-baremetal 」に置き換えてください。

  1. 以下のコマンドを含むバッチスクリプトを作成し、qmlprojectexporter を呼び出してGHS Multi IDEプロジェクトを生成します。
    set QUL_ROOT=C:\path\to\QtMCUs\2.12.2
    set QMLPROJECT_FILE=C:\path\to\YourProject.qmlproject
    set BOARDDEFAULTS=%QUL_ROOT%\platform\boards\cypress\tviic2d4m-baremetal\cmake\BoardDefaults_32bpp.qmlprojectconfig
    set GRAPHICS_DRIVER_DIR=C:\path\to\TVII-GraphicsDriver-V2.4.0
    set PROJECT_DIR=C:\path\to\PROJECT_DIR
    
    %QUL_ROOT%\bin\qmlprojectexporter.exe %QMLPROJECT_FILE% --platform=tviic2d4m-baremetal --toolchain=ghs-arm --boarddefaults=%BOARDDEFAULTS% --outdir=%PROJECT_DIR% --project-type=ghs --include-ide-generated-hw-code --board-sdk=%GRAPHICS_DRIVER_DIR%

    スクリプトを実行する前に、以下の変数が設定されていることを確認してください:

    • GRAPHICS_DRIVER_DIR TRAVEO T2G グラフィックスドライバのインストールパス、
    • QUL_ROOT QMLPROJECT_FILE
    • PROJECT_DIR GHSプロジェクトファイルを保存する出力ディレクトリ。

    次に、コマンドプロンプトからスクリプトを実行して、以下の出力を生成します:

    • QMLから生成されたC++ソースは%PROJECT_DIR%/QtMCUs/generated
    • エクスポートされたプラットフォーム用ソースは%PROJECT_DIR%/QtMCUs/platform
    • %PROJECT_DIR%/GHS にあるサブプロジェクトファイルを含むトップレベルのプロジェクトファイル。

    生成された GHS プロジェクトには、以下のものが含まれます:

    • %PROJECT_DIR%/GHS/project.gpj: トップレベルのプロジェクトファイル。
    • %PROJECT_DIR%/GHS/prj/program.gpj: プログラムのコンパイル定義、インクルードディレクトリ、コンパイラおよびリンカのオプション。
    • %PROJECT_DIR%/GHS/prj/drivers.gpj: TVIIグラフィックスドライバのソースコード一覧。
    • %PROJECT_DIR%/GHS/prj/QtMCUs/qul_platform.gpj: TRAVEO T2G CYT3DLプラットフォームのソース一覧。
    • %PROJECT_DIR%/GHS/prj/QtMCUs/qul_app.gpj: メインの.qmlproject ファイルから生成されたソースの一覧。
    • %PROJECT_DIR%/GHS/prj/QtMCUs/qul_module_<ModuleName>.gpj: 各モジュールごとに1つのサブプロジェクトがあり、対応するモジュールの.qmlproject ファイル用に生成されたソースが含まれています。
    • %PROJECT_DIR%/GHS/prj/application.gpj: アプリケーション用の便利な空のサブプロジェクト。次のセクションでこれを編集します。
    • %PROJECT_DIR%/GHS/mcu_<YourProject>_qul_workspace.gmb: 利便性を考慮していくつかのコマンドが追加されたワークスペース。詳細については、「GHS Multi IDE QUL ワークスペース」を参照してください。
    • %PROJECT_DIR%/GHS/qul_flash_jlink.bat: J-Linkプローブを使用してアプリケーションをフラッシュするためのバッチファイル。
    • %PROJECT_DIR%/GHS/qul_flash_miniprog.bat: MiniProg4プローブを使用してアプリケーションをフラッシュするためのバッチファイル。

詳細については、「プラットフォームソースを含むQt for MCUs プロジェクトのエクスポート」を参照してください。

GHS MULTI IDE でのアプリケーションのビルド

以下の手順では、アプリケーションをビルドするために必要な GHS プロジェクトの調整手順を説明します。

  1. GHS MULTI Launcher(mstart.exe )を起動します。
  2. File > Load Workspace from File... 」を選択し、前のセクションでエクスポートした %PROJECT_DIR%/GHS へ移動します。ワークスペースファイル「mcu_<YourProject>_qul_workspace.gmb 」を選択します。
  3. ワークスペース内の「Project Manager 」エントリをダブルクリックし、プロジェクトマネージャーでプロジェクトを開きます。
  4. 任意のディレクトリに「main.cpp 」という名前の新しいファイルを作成します。このディレクトリを以下、BACKEND_DIRと呼びます:
    #include "YourProject.h"
    
    #include <qul/application.h>
    #include <qul/qul.h>
    
    int main()
    {
        Qul::initHardware();
        Qul::initPlatform();
        Qul::Application app;
        static YourProject item;
        app.setRootItem(&item);
        app.exec();
        return 0;
    }

    このファイルには、アプリケーションのデフォルトのエントリポイントが定義されています。後で、LED やユーザーボタンを使用するために、追加の設定手順を経てこのエントリポイントを拡張することになります。詳細については、アプリケーションのドキュメントにある「Qt Quick Ultralite の実行」を参照してください。前の章で選択したのと同じプロジェクト名(YourProject )を使用するようにしてください。

  5. application.gpj 」を選択して長押しするか、右クリックして「Edit 」を選択します。その内容を以下の内容に置き換えてください。
    #!gbuild
    
    macro APPLICATION_EXPORT_DIR=C:/path/to/PROJECT_DIR/QtMCUs/generated
    macro BACKEND_DIR=C:/path/to/BACKEND_DIR
    
    [Subproject]
        -DQUL_STD_STRING_SUPPORT
        -I${APPLICATION_EXPORT_DIR}
    
    # ----- backend -----
    ${BACKEND_DIR}/main.cpp

    APPLICATION_EXPORT_DIR マクロにはエクスポートされた UI ソースが含まれるディレクトリを、BACKEND_DIRマクロにはバックエンドソースとmain.cpp が含まれるディレクトリを必ず設定してください。

    注: .gpj のプロジェクトファイルでは、インデントが 重要です。ソースファイルを含め、行頭に空白文字がないことを確認してください。詳細については、MULTI IDEのドキュメントを参照してください。

  6. アプリケーションのバイナリ名は、デフォルトで「application.elf 」です。別の名前を使用するには、program.gpj プロジェクトファイル内の-o application.elf-o YourProject.elf に変更してください。
  7. この時点で、これまでの手順が正しく実行されていることを確認するために、部分的に実装済みのアプリケーションをビルドし、GHS MULTI IDE ワークスペースのショートカットから、プロジェクトのエクスポート時に `qmlprojectexporter ` が生成した便利なバッチファイルを使用して、TRAVEO T2G ボードにフラッシュすることができます。

    注: TRAVEO T2G Cluster 4M Lite (KIT_T2G_C-2D-4M_LITE) プラットフォーム・ポート・ボードは 、デフォルトで USB ディスプレイ出力が設定されています。 詳細については、「ディスプレイ出力(TRAVEO T2G CYT3DL 4M LITE KIT および CYT4DN 6M LITE KIT)」を参照してください。

    バッチファイル(qul_flash_jlink.bat およびqul_flash_miniprog.bat )は、メインのプロジェクトファイルと同じディレクトリに配置されており、J-Link または MiniProg4 プローブを使用してアプリケーションをフラッシュするために必要なコマンドが含まれています。

    お使いのプローブに対応するバッチファイルは、GHS MULTI IDE のワークスペースから直接実行できます。

    注: これらのバッチファイルから実行されるコマンドの詳細については 、「 Infineon ボードのフラッシュ手順」を参照してください。

    このバッチファイルは、Infineon Auto Flash Utility 1.4 がデフォルトの場所にインストールされているか、そのパスが環境変数INFINEON_AUTO_FLASH_UTILITY_DIR に設定されていることを前提としています。

    また、TRAVEO T2GボードのCM0+コアにブートローダーを書き込む必要があります。詳細な手順については、「 Infineon ボード用ブートローダー書き込み手順」を参照してください。

次のセクションでは、ユーザーボタンを介してアプリケーションの UI とハードウェアとの相互作用を可能にするロジックを追加します。

C++ バックエンドの開発

以下の手順に従って、アプリケーション用の C++ バックエンドを開発してください。

  1. 新しい C++ ソースファイルとヘッダーファイルを作成し、それぞれを「deviceinterface.cpp 」および「deviceinterface.h 」と命名します。これらのファイルを、先ほど作成したBACKEND_DIRディレクトリに保存します。
  2. deviceinterface.h の内容を以下のように置き換えます:
    #ifndef DEVICEINTERFACE_H
    #define DEVICEINTERFACE_H
    
    #include <qul/signal.h>
    #include <qul/singleton.h>
    #include <qul/eventqueue.h>
    
    typedef int HWButtonEvent;
    
    class DeviceInterface : public Qul::Singleton<DeviceInterface>, public Qul::EventQueue<HWButtonEvent>
    {
    public:
        Qul::Signal<void(int button)> buttonEvent;
        void onEvent(const HWButtonEvent &inputEvent);
    
        void toggleLED();
    };
    
    #endif //DEVICEINTERFACE_H

    このヘッダーファイルでは、`Qul::Singleton ` および `Qul::EventQueue` を継承する `DeviceInterface ` クラスを宣言しています。また、`buttonEvent `、Signal 、および `HWButtonEvent ` イベントタイプも宣言しています。これにより、シングルトンインスタンスをグローバルに利用できるようになります。これは C++ と QML 間のインターフェースを提供し、`HWButtonEvent ` 入力イベントを受信した際に`changed`シグナルを発行します。 詳細については、「QML でのシングルトンの定義」および「割り込みハンドラから QML へのデータ転送」を参照してください。

  3. 同様に、deviceinterface.cpp の内容を以下のように置き換えてください:
    #include "deviceinterface.h"
    #include "boardutils.h"
    
    #include <platforminterface/log.h>
    
    extern "C" void DeviceInterface_handleButtonEvent()
    {
        DeviceInterface::instance().postEventFromInterrupt(0);
    }
    
    void DeviceInterface::onEvent(const HWButtonEvent &inputEvent)
    {
        buttonEvent(inputEvent);
    }
    
    void DeviceInterface::toggleLED()
    {
        Qul::PlatformInterface::log("Toggling LED\n");
        BoardUtils_toggleLED();
    }
  4. 新しい C ソースファイルとヘッダーファイルを作成し、それぞれboardutils.c およびboardutils.h と名付けます。これらのファイルをBACKEND_DIRディレクトリに保存します。
  5. boardutils.h 内のコードを以下の内容に置き換えてください:
    #ifndef BOARDUTILS_H
    #define BOARDUTILS_H
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    void BoardUtils_configure();
    void BoardUtils_toggleLED();
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif //BOARDUTILS_H
  6. BoardUtils_configure() およびBoardUtils_toggleLED() の TRAVEO T2G 向け実装を、boardutils.c に追加してください:
    #include "boardutils.h"
    
    #include <stdint.h>
    
    #include <cy_project.h>
    
    #define USER_LED1_PORT CY_USER_LED1_PORT
    #define USER_LED1_PIN CY_USER_LED1_PIN
    #define USER_LED1_PIN_MUX CY_USER_LED1_PIN_MUX
    
    #define USER_BUTTON1_PORT CY_USER_BUTTON_WAKE_PORT
    #define USER_BUTTON1_PIN CY_USER_BUTTON_WAKE_PIN
    #define USER_BUTTON1_PIN_MUX CY_USER_BUTTON_WAKE_PIN_MUX
    #define USER_BUTTON1_IRQN CY_USER_BUTTON_WAKE_IRQN
    
    extern void DeviceInterface_handleButtonEvent();
    
    void ButtonInterruptHandler(void)
    {
        uint32_t interruptStatus = Cy_GPIO_GetInterruptStatusMasked(USER_BUTTON1_PORT, USER_BUTTON1_PIN);
        if (interruptStatus) {
            DeviceInterface_handleButtonEvent();
            Cy_GPIO_ClearInterrupt(USER_BUTTON1_PORT, USER_BUTTON1_PIN);
        }
    }
    
    void BoardUtils_configure()
    {
        // GPIO configuration for LED
        cy_stc_gpio_pin_config_t user_led_port_pin_cfg = {
            .outVal = 0x00,
            .driveMode = CY_GPIO_DM_STRONG_IN_OFF,
            .hsiom = USER_LED1_PIN_MUX,
            .intEdge = 0,
            .intMask = 0,
            .vtrip = 0,
            .slewRate = 0,
            .driveSel = 0,
            .vregEn = 0,
            .ibufMode = 0,
            .vtripSel = 0,
            .vrefSel = 0,
            .vohSel = 0,
        };
    
        Cy_GPIO_Pin_Init(USER_LED1_PORT, USER_LED1_PIN, &user_led_port_pin_cfg);
    
        // GPIO configuration for button
        static cy_stc_gpio_pin_config_t user_button1_port_pin_cfg = {
            .outVal = 0x00,
            .driveMode = CY_GPIO_DM_HIGHZ,
            .hsiom = USER_BUTTON1_PIN_MUX,
            .intEdge = CY_GPIO_INTR_FALLING,
            .intMask = 1,
            .vtrip = 0,
            .slewRate = 0,
            .driveSel = 0,
            .vregEn = 0,
            .ibufMode = 0,
            .vtripSel = 0,
            .vrefSel = 0,
            .vohSel = 0,
        };
    
        Cy_GPIO_Pin_Init(USER_BUTTON1_PORT, USER_BUTTON1_PIN, &user_button1_port_pin_cfg);
    
        // IRQ configuration for button
        cy_stc_sysint_irq_t irq_cfg = {
            .sysIntSrc = USER_BUTTON1_IRQN,
            .intIdx = CPUIntIdx2_IRQn,
            .isEnabled = true,
        };
    
        Cy_SysInt_InitIRQ(&irq_cfg);
        Cy_SysInt_SetSystemIrqVector(irq_cfg.sysIntSrc, ButtonInterruptHandler);
    
        NVIC_SetPriority(CPUIntIdx2_IRQn, 3);
        NVIC_ClearPendingIRQ(CPUIntIdx2_IRQn);
        NVIC_EnableIRQ(CPUIntIdx2_IRQn);
    }
    
    void BoardUtils_toggleLED()
    {
        Cy_GPIO_Inv(USER_LED1_PORT, USER_LED1_PIN);
    }

    configure関数は、LEDおよびボタンのピンを初期化します。その後、TRAVEO T2GグラフィックスドライバのGPIOおよびIRQ APIを使用して、ButtonInterruptHandler() をユーザーボタンイベントの割り込み要求ハンドラとして登録します。

    注: バックエンドロジックを実装した後 、ボード上の SW5 ハードウェアボタンを押して、ボタンイベントをトリガーしてください。

  7. TRAVEO T2GのLEDとボタンを適切に設定するには、main.cpp を変更してboardutils.h ヘッダーをインクルードし、通常のプラットフォーム初期化の後にBoardUtils_configure() を呼び出すようにしてください:
    #include "boardutils.h"
    ...
    
    int main()
    {
        Qul::initHardware();
        Qul::initPlatform();
        BoardUtils_configure();
        ...
    }
  8. application.gpj に新しいソースファイルを追加してください:
    #!gbuild
    ...
    
    # ----- backend -----
    ${BACKEND_DIR}/main.cpp
    
    ${BACKEND_DIR}/boardutils.c
    ${BACKEND_DIR}/deviceinterface.cpp

Design Studio での UI とバックエンドの統合

Qt Design Studio 内のDeviceInterfaceシングルトンオブジェクトを使用して、前のセクションで実装した低レベルのバックエンド関数にアクセスします。

  1. Qt Design Studio でプロジェクトを開き、「Connections 」ビューを選択します。
  2. Connections 」タブ( )にある「さらに 」ボタンを選択し、新しい接続を追加します。

    [接続] ビューで新しい接続を追加します。

  3. 新しい接続を選択し、「Connection 」パネル を使用して、「Code 」ビューに移動します。

    「接続」パネルを使用して、「コード」ビューに移動する。

  4. Code 」ビューで、最初の接続 を追加し、「target 」に「statusRect 」を、「onPressedChanged 」信号のアクションに「DeviceInterface.toggleLED() 」を指定します。

    コードビューで最初の接続を追加します。

  5. Code ビューで、2つ目の接続 を追加し、targetDeviceInterface を、onButtonEvent シグナルのアクションにstatusRect.pressed = !statusRect.pressed を指定します。

    コードビューで 2 つ目の接続を追加します。

    これで、ボタンを押すと、イベントが QML コンテキストに伝播し、statusRect.pressed プロパティが変更されます。その結果、UI アイテムの色が変更されます。statusRect.pressed プロパティの変更に応答して、DeviceInterface.toggleLED() メソッドが LED の点灯状態を切り替えます。

  6. テキストエディタを使用して `yourproject.qmlproject ` を変更し、シングルトンオブジェクトに必要な C++/QML インターフェースを生成してください:
    InterfaceFiles {
        files: ["C:/path/to/BACKEND_DIR/deviceinterface.h"]
    }

    BACKEND_DIRのパスを、deviceinterface.h ファイルが含まれているディレクトリに変更してください。

    詳細については、QmlProjectInterfaceFiles を参照してください。

UIに変更を加えた後、GHSプロジェクトを更新してください

アプリケーションの UI 部分に変更を加えたため、qmlprojectexporter を使用して UI ソースを再度エクスポートしてください。

--update-projectコマンドライン引数を使用して、UI コードの新しい変更を既存の GHS プロジェクトに反映させます。以下のいずれかの方法を使用してください。

  1. GHS MULTI Launcherのワークスペース内にある「Sync Qmlproject files 」の下にある定義済みコマンドを使用します。UI上でそれをダブルクリックして、プロジェクトファイルを更新します。
  2. 次のバッチスクリプトを使用して、qmlprojectexporter を手動で実行します:
    set QUL_ROOT=C:\path\to\QtMCUs\2.12.2
    set QMLPROJECT_FILE=C:\path\to\YourProject.qmlproject
    set PROJECT_DIR=C:\path\to\PROJECT_DIR
    set QMLPROJECT_DIR=%PROJECT_DIR%\QtMCUs\generated
    
    %QUL_ROOT%\bin\qmlprojectexporter.exe %QMLPROJECT_FILE% --update-project=%PROJECT_DIR%/GHS/project.gpj

特定の Qt ライセンスの下で利用可能です。
詳細はこちら。