このページでは

C

Qt Quick Ultralite freertos_app_switch 例

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

概要

freertos_app_switch は、ソフトリセットとソフトリセット間の状態を保持するメモリ位置によって、Qt Quick Ultralite アプリケーションと別のアプリケーションを切り替える方法を示しています。この例では、Qt Quick Ultraliteアプリケーションを再起動し、アプリケーションの初期化ステップを再トリガーする方法も示しています。

起動時に特定のメモリー・アドレスを使用して、2つのアプリケーションを選択します:

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

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

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

注: ここで紹介したリセット・メカニズムは、ハード・リセット(パワー・サイクルのトリガー)と状態を保持する不揮発性メモリを使用するように適応させることができます。

ターゲット・プラットフォーム

コード概要

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

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();
                    }
                }
                ...

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

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 ライセンスによっては利用可能です。