C
Qt Quick Ultraliteの使用Zephyr
Zephyr は組み込みシステム用の RTOS です。完全にプリエンプト可能なティックレスカーネル、協調スレッドとプリエンプティブスレッド、セマフォとキューを提供します。
サポートされるアーキテクチャ、プラットフォーム、Zephyr バージョン
Qt Quick Ultraliteは以下のハードウェアをサポートしています:
| ハードウェアボード | マイコン | アーキテクチャ | コンパイラ | 対応Zephyr バージョン |
|---|---|---|---|---|
| NXP IMXRT1060-EVKB | IMXRT1062DVL6B | ARM Cortex-M7 | GNUアームGCC 12.3.rel1 | 4.1.0 |
| NXP IMXRT1064-EVK | IMXRT1064DVL6A | ARM Cortex-M7 | GNUアームGCC 12.3.rel1 | 4.1.0 |
Zephyr プラットフォームへのQt Quick Ultralite の移植
Qt Quick Ultraliteプラットフォーム移植ガイドに従って、Qt Quick UltraliteをZephyr プラットフォームに移植することができます。リファレンス・ポートでは、以下の部分がZephyr API を使用して実装されています:
- currentTimestamp() はk_uptime_get() を呼び出します。
- タッチサポートはキーボードスキャンAPIを使用しています。
- Qt Quick Ultralite Queues は Zephyr メッセージ・キューを使用しています。
- セマフォは Qt Quick Ultralite スレッド操作の中断と再開に使用されます。
- ディスプレイ割り込みはZephyr を使って設定され、有効化される:
void setInterruptPriorities() { IRQ_CONNECT(LCDIF_IRQn, 3, displayIRQHandler, NULL, 0); irq_enable(LCDIF_IRQn); }
- LCD スクリーン pinmux はZephyr ピン制御 API を使用して初期化されます。
#define LCDIF_DEV DT_NODELABEL(lcdif) void initializeLcdPinmux() { PINCTRL_DT_DEFINE(LCDIF_DEV); pinctrl_apply_state(PINCTRL_DT_DEV_CONFIG_GET(LCDIF_DEV), PINCTRL_STATE_DEFAULT); }
注: サポートされているリファレンス・プラットフォーム・ポートのいずれかをインストールしている場合、リファレンスZephyr ポートのソースコードは<QT_INSTALL>/QtMCUs/2.9.0/platform/boards/nxp/common/zephyr ディレクトリにあります。
Zephyr KConfig オプション
Qt Quick Ultralite を使用するようにZephyr プロジェクトを構成する場合は、以下のオプションを含めます:
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048CONFIG_REQUIRES_FULL_LIBC=yCONFIG_NEWLIB_LIBC=yCONFIG_COMMON_LIBC_MALLOC=yCONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=2097152CONFIG_NEWLIB_LIBC_NANO=yCONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=8192CONFIG_CPP=yCONFIG_STD_CPP14=yCONFIG_EXTERNAL_LIBCPP=yCONFIG_FORTIFY_SOURCE_NONE=y
注: プラットフォーム・ポートでカスタム・アロケーション・システムを使用する場合、malloc 関連のオプションを設定する必要はありません。
メイン・スレッドからQt Quick Ultralite アプリケーションを実行したい場合は、メイン・スレッドのスタック・サイズを大きくしてください。例えば、リファレンス・プラットフォーム・ポートではCONFIG_MAIN_STACK_SIZE=12288 を使用していますが、これはthermo デモとサポートされているすべてのサンプルを実行するのに十分です。
構築済みのQt Quick Ultralite ライブラリを使用する場合は、以下のオプションを追加してください:
CONFIG_FPU=yCONFIG_LTO=yCONFIG_ISR_TABLES_LOCAL_DECLARATION=y
ワークフロー
Qt Quick Ultraliteは、既存のZephyr プロジェクトと簡単に統合できるツールを提供します。
Qt Quick Ultraliteアプリケーションの作成とコンパイルの全体的なワークフローは以下のとおりです:
Qt Quick Ultralite アプリケーションを作成し、コンパイルするワークフローです。" src="images/qtul-zephyr-workflow.png" title="Zephyr を使って Qt Quick Ultralite アプリケーションを作成し、コンパイルするワークフローです。"/>
新しいQt Quick Ultralite アプリケーションの作成
Qt Quick Ultralite アプリケーションを作成するには、Qt Design Studio on MCUsドキュメントを参照してください。
アプリケーションを CMake プロジェクトとしてエクスポートする
CMakeプロジェクトの生成ページには、CMakeプロジェクトを生成するためにqmlprojectexporterで使用できるフラグのリストが含まれています。プラットフォームのソースをエクスポートする必要がない場合は、qmlprojectexporter に --no-export-platformを追加してください。プラットフォームのエクスポートを伴わない qmlprojectexporter 呼び出しについては、プラットフォームなしでエクスポートされたプロジェクトを統合するを参照してください。
エクスポートした CMake プロジェクトをZephyr プロジェクトに追加する
エクスポートした CMake プロジェクトを追加するには、CMake プロジェクトファイルの作成手順に従ってください:
- CMakeLists.txt 内で新しいプロジェクトを指定する必要はありません。ただし、プロジェクトが
LANGUAGES C CXX ASMを指定していることを確認してください。 find_packageとtarget_*のすべての呼び出しをfind_package(Zephyr).target_*を指定する場合は、Qt Quick Ultralite アプリケーションがZephyr プロジェクトにビルドされるように、appをターゲットとして使用してください。
リンカスクリプトにQt Quick Ultralite 固有のセクションを追加する。
Qt Quick Ultralite はリンカスクリプトに、Qt Quick Ultralite アプリケーションに関連するすべてのデータを格納できるいくつかのセクションを含めることを要求します。これらのセクションの説明はここにあります。
ただし、カスタムリンカースクリプトを使用しない限り、Zephyr が自動的にスクリプトを生成します。自動生成されたスクリプトにQt Quick Ultralite で必要なセクションを追加するには、リンカースクリプトでZephyr-固有のセクション記述表記を使用し、zephyr_linker_sources(SECTION_NAME "path/to/linkerscript.ld") を使用してインクルードする必要があります。zephyr_linker_sources の詳細と表記法については、ZEPHYR_DIR/zephyr/cmake/modules/extensions.cmake を参照してください。
Qt Quick Ultraliteリファレンス・プラットフォーム・ポートでは、3つのファイルでリンカ ー・セクションを定義します:
qul_data_sections.ldSECTION_PROLOGUE (QulModuleResourceData,,SUBALIGN(4)) { __ModuleResourceDataCacheStart = .; *(QulModuleResourceData) __ModuleResourceDataCacheEnd = .; } GROUP_LINK_IN(RAMABLE_REGION) AT > ROMABLE_REGION __ModuleResourceDataStart = LOADADDR(QulModuleResourceData);qul_ram_sections.ldSECTION_PROLOGUE (QulPreloadData,,SUBALIGN(4)) { __preloadRamStart = .; *(QulPreloadData) . += 10M; __preloadRamEnd = .; } GROUP_LINK_IN(RAMABLE_REGION)qul_rom_sections.ldSECTION_PROLOGUE (QulFontResourceData,,) { . = ALIGN(4); *(QulFontResourceData) . = ALIGN(4); } GROUP_LINK_IN(ROMABLE_REGION) SECTION_PROLOGUE (QulResourceData,,SUBALIGN(4)) { *(QulResourceData) } GROUP_LINK_IN(ROMABLE_REGION)
これらのファイルは、zephyr-linker-sources.cmake を使用してZephyr プロジェクトに追加されます:
# Copyright (C) 2025 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial
zephyr_linker_sources(DATA_SECTIONS "${CMAKE_CURRENT_LIST_DIR}/cmake/armgcc/qul_data_sections.ld")
zephyr_linker_sources(RAM_SECTIONS "${CMAKE_CURRENT_LIST_DIR}/cmake/armgcc/qul_ram_sections.ld")
zephyr_linker_sources(SECTIONS "${CMAKE_CURRENT_LIST_DIR}/cmake/armgcc/qul_rom_sections.ld")
# Workaround for https://github.com/zephyrproject-rtos/zephyr/issues/90581
target_link_options(app INTERFACE -Wl,-u,image_vector_table -Wl,-u,boot_data)Qt Quick Ultraliteアプリケーションの反復ビルド
Qt Quick Ultraliteアプリケーションの内容を変更する場合は、Zephyr プロジェクトをリビルドするだけです。qmlprojectexporter が実行されると、変更を読み取り、Qt Quick Ultralite アプリケーションのソースを再エクスポートし、QulExport パッケージを更新して、Zephyr プロジェクトで変更を利用できるようにします。
Qt Quick Ultraliteスレッドの作成
もし --generate-entrypointQt Quick を使用する場合、メインスレッドがアプリケーションへのエントリポイントとして使用されます。スレッドの作成をより制御したい場合は、Qt Quick Ultraliteアプリケーションを実行する Zephyr スレッドを生成することもできます。これを行うには --generate-entrypoint引数を省略します。
Zephyr プロジェクトで、まずQt Quick Ultralite アプリケーションスレッドを宣言し、スタック領域を割り当てます:
k_tid_t QulThread; static K_THREAD_STACK_DEFINE(qul_stack_area, 12288);
注: スタックサイズはQt Quick Ultraliteアプリケーションの複雑さによって異なります。スタック・サイズはQt Quick Ultralite アプリケーションの複雑さによって異なります。Ultralite Thermostat Demo では、この例の値で十分です。
次に、Qt Quick Ultralite アプリケーションスレッドを定義します:
void Qul_Thread(void *arg1, void *arg2, void *arg3) { (void) arg1; (void) arg2; (void) arg3; Qul::Application app; static MainScreen item; app.setRootItem(&item); while (true) app.update(); }
注: MainScreen は、Qt Quick Ultralite アプリケーションのメイン qml ファイルをMainScreen.qml と想定しています。項目名をアプリケーションのメインqmlファイル名に合わせて変更してください。
この後、Qt Quick Ultralite アプリケーションスレッドを作成します:
struct k_thread qul_thread_data; QulThread = k_thread_create(&qul_thread_data, qul_stack_area, K_THREAD_STACK_SIZEOF(qul_stack_area), Qul_Thread, NULL, NULL, NULL, 4, 0, K_NO_WAIT);
注: Qt Quick Ultralite アプリケーションを実行する前に、ハードウェアを初期化していることを確認してください。
Qt Quick Ultralite アプリケーションスレッドを生成する完全なZephyr プロジェクト main.cpp は、例えば次のようになります:
#include "MainScreen.h" #include <zephyr/kernel.h> k_tid_t QulTask; static K_THREAD_STACK_DEFINE(qul_stack_area, 12288); static void Qul_Thread(void *arg1, void *arg2, void *arg3); int main() { Qul::initHardware(); Qul::initPlatform(); struct k_thread qul_thread_data; QulThread = k_thread_create(&qul_thread_data, qul_stack_area, K_THREAD_STACK_SIZEOF(qul_stack_area), Qul_Thread, NULL, NULL, NULL, 4, 0, K_NO_WAIT); return 0; } static void Qul_Thread(void *arg1, void *arg2, void *arg3) { (void) arg1; (void) arg2; (void) arg3; Qul::Application app; static MainScreen item; app.setRootItem(&item); while (true) app.update(); }
Zephyr プラットフォームで特注のQt Quick Ultralite を使用する。
Qt Quick Ultraliteをソースからビルドするには、 Qt Quick Ultraliteをソースからビルドする の指示に従ってください。
mkdir -p <builddir>/.cmake/api/v1/query && touch <builddir>/.cmake/api/v1/query/codemodel-v2 cmake -S $QUL_ROOT -B <builddir> -DQul_ROOT=$QUL_ROOT -DQUL_TARGET_TOOLCHAIN_DIR=<toolchaindir> -DQUL_GENERATORS=$QUL_ROOT/lib/cmake/Qul/QulGenerators.cmake -DCMAKE_TOOLCHAIN_FILE=$QUL_ROOT/lib/cmake/Qul/toolchain/armgcc.cmake -DQUL_PLATFORM_ARCHITECTURE=cortex-m7-hf-fpv5-d16 -DQUL_BUILD_PLATFORM=OFF -DCMAKE_INSTALL_PREFIX=<installdir> -DQUL_PLATFORM_ARCHITECTURE_FILE=$QUL_ROOT/platform/architecture/cortex-m7-hf-fpv5-d16/armgcc/architecture.cmake make -C <builddir> install
ビルドが完了したら、ビルドしたライブラリを含むQt Quick Ultralite アプリケーションをエクスポートできます:
$QUL_ROOT/bin/qmlprojectexporter $QUL_ROOT/examples/chess/mcu_chess.qmlproject --boarddefaults=<path/to/>BoardDefaults_24bpp_default.qmlprojectconfig --toolchain GNU --cxx-standard=c++17 --platform <platform_name> --outdir <target_dir> --qul-source-dir <installdir> --project-type cmake --no-export-platform --generate-entrypoint --platform-metadata <installdir>/lib/cortex-m7-hf-fpv5-d16-export.json
エクスポート後、エクスポートした CMake プロジェクトをZephyr プロジェクトに追加します。