このページでは

C

Qt Quick Ultralite freertos_app_switch の例

Qt Quick のUltraliteアプリケーションと別のアプリケーションを、ソフトリセットを介して切り替える方法を示します。

概要

freertos_app_switch は、ソフトリセットと、ソフトリセットの合間に状態を保持するメモリ位置を利用して、Qt Quick のUltraliteアプリケーションと別のアプリケーションを切り替える方法を示しています。また、この例では、Qt Quick のUltraliteアプリケーションを再起動し、アプリケーションの初期化手順を再実行する方法についても説明しています。

起動時には、2つのアプリケーションを切り替えるために特定のメモリアドレスが使用されます。

  • Application #1 は「Qt Quick 」Ultraliteアプリケーションそのものであり、ブート選択メカニズムへのユーザーインターフェースを提供します。

    Freertos_app_switch のサンプル。次回の起動時に使用するアプリケーションを選択するための「App #1」および「App #2」のラジオボタンと、「リセット」ボタンが表示されています。

  • Application #2 は、フレームバッファに直接書き込みを行い、LEDを数秒間点滅させた後、デバイスを再起動して最初のアプリケーションを起動する別のアプリケーションです。

    アプリケーション #2 の画面が表示されました

注: ソフトリセットを使用する際は注意が必要です 。ハードウェア周辺機器が正しく再初期化できることを確認してください。一部の周辺機器は、プログラムを行う前にリセット信号を必要としたり、特定の状態にある必要がある場合があります。

注: ここで紹介したリセットメカニズム、ハードリセット(電源の再投入)や、状態を保持するための不揮発性メモリを使用するように適応させることも可能です。

対象プラットフォーム

コードの概要

アプリケーションのエントリポイント

main() 関数は、ハードウェアおよびプラットフォームの初期化を行い、さらにボード固有のInitLED() 関数を使用してLEDを初期化します。

...
int main()
{
    Qul::initHardware();
    Qul::initPlatform();
    initLED();
    ...

次に、メモリからboot の値が読み込まれます。

    int boot = readBootValue();

readBootValue() メソッドは、単に特定のメモリ位置から読み取るだけであり、boardutils.c で定義されています。

int readBootValue()
{
    int *ptr = &__BOOT_VAL_ADDR;
    return *ptr;
}

boot 変数のアドレスは、board.cmake ファイル内のリンカ定義シンボルを介して設定できます。

set(BOOT_VAL_ADDR 0x81400000)
if (IAR)
    target_link_options(freertos_app_switch PRIVATE --define_symbol __BOOT_VAL_ADDR=${BOOT_VAL_ADDR})
else()
    target_link_options(freertos_app_switch PRIVATE -Xlinker --defsym=__BOOT_VAL_ADDR=${BOOT_VAL_ADDR})
endif()

boot の値に基づいて、異なるFreeRTOS タスクが作成されます。Application #1 を実行するQt Quick Ultraliteタスク、あるいはApplication #2 を実装する別のタスクのいずれかです。

    if (boot != APP2) {
        Qul::PlatformInterface::log("Application #1...QUL Application Switch\r\n");
        if (xTaskCreate(App1_thread, "QulExec", QUL_STACK_SIZE, 0, 4, &QulTask) != pdPASS) {
            Qul::PlatformInterface::log("Task creation failed!\r\n");
            configASSERT(false);
        }
    } else {
        Qul::PlatformInterface::log("Application #2...blinking LED\r\n");
        if (xTaskCreate(App2_thread, "LedToggle", configMINIMAL_STACK_SIZE, 0, 4, &LedTask) != pdPASS) {
            Qul::PlatformInterface::log("LED task creation failed!\r\n");
            configASSERT(false);
        }
    }

    vTaskStartScheduler();
    ...

Qt Quick Ultralite を実行するApplication #1 タスクは、単にアプリケーションのルート項目を設定し、exec() 関数を呼び出すだけです。

static void App1_thread(void *argument)
{
    (void) argument;

    Qul::Application app;
    static appswitch item;
    app.setRootItem(&item);
    app.exec();
}

Application #2 タスクは、displayApp2Background() を介して生画像をフレームバッファに直接書き込み、その後、数サイクルにわたってLEDを点滅させます。

static void App2_thread(void *argument)
{
    (void) argument;
    displayApp2Background();

    //Blink for N_BLINKS times then reboot into App1
    for (int i = 0; i < N_BLINKS; ++i) {
        xTaskNotifyWait(0, ULONG_MAX, NULL, pdMS_TO_TICKS(500));
        toggleLED();
        taskYIELD();
    }
    reset(APP1);
}
QML

Qt Quick Ultralite のユーザーインターフェースは、freertos_app_switch.qml で実装されています。次の起動時に実行するアプリケーションは 2 つのラジオボタンで選択され、リセットボタンでソフトリセットが実行されます。

                ...
                Button {
                    id: resetButton
                    text: "Reset!"
                    anchors.centerIn: parent
                    onClicked: {
                        console.log("Chosen application #", DevControl.application, "...Resetting system!")
                        DevControl.resetDevice();
                    }
                }
                ...

DevControl オブジェクトは、UI と抽象化されたハードウェア間のインターフェースとして使用されます。

void DevControl::HWResetDevice()
{
    reset(application.value());
}

パブリックメソッド `resetDevice() ` を使用すると、`Qul::Property<int> application ` の値をブートメモリの指定位置に書き込み、その後 `NVIC_SystemReset()` を通じてソフトリセットをトリガーできます。

void writeBootValue(int app)
{
    int *ptr = &__BOOT_VAL_ADDR;
    *ptr = app;
    QUL_CleanInvalidateDCache_by_Addr((void *) ptr, 4);
}

void reset(int app)
{
    writeBootValue(app);
    NVIC_SystemReset();
}

注: NXP i.MX RT1170 バイナリの書き込み直後、デバイスをもう一度リセットする必要があります。そうしないと、NVIC_SystemReset() によるソフトリセットが正常に動作しない可能性があります。

ファイル:

FreeRTOS アプリケーションのビルドプロセスも参照してください

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