CMake の基礎がある程度ある読者は、ThreadX 移植の再考 - 土星の環の基地 を直接参照することをおすすめします。
ThreadX カーネルの内容紹介
ThreadX は Eclipse Foundation に寄贈されました。現在のオープンソースコードはこちらです。
私が普段使っているのは ST 社のフォークです。実際のところサポートはそれほど良くなっておらず、ハマりどころは相変わらずあります。
ThreadX カーネルには、ThreadX OS カーネル、Modules モジュール、トレースデバッグ監視の 3 つの要素が含まれています。ThreadX のソースコードでは、これらがかなり混在しています。そこで、簡単にドキュメントとしてまとめておきます。移植チュートリアルであると同時に、ライブラリ構成の記録でもあります。

image-20250120113105909
ここにはシステムカーネルの 3 つのバージョンが表示されています。
common通常カーネルcommon_moduleモジュールロード機能を備えたカーネル。ハードウェアドライバとソフトウェアロジックを完全に分離できますcommon_smpマルチコア MCU をサポートするカーネル
カーネル移植の目標は、以下のコンポーネントを使うことです。
- ThreadX OS カーネル
- Modules モジュール
- トレースデバッグ監視
純カーネルの移植
「純カーネル」は私の呼び方です。modules 版カーネルや smp 版カーネルと比べると、実際には FreeRTOS や BIOS のような普通の RTOS と機能は変わりません。ただし、ThreadX 系の他のコンポーネントを移植しやすく、命名も統一されているため、NetX、USBX、FileX などを非常に簡単にシステムへ追加できます。
純カーネルのソースコードはどれ?

image-20250120113135771
ThreadX OS のソースコードの中に、図のように囲った 2 つのフォルダがあります。実際に OS カーネルを移植するのに必要なソースコードは、この 2 つのフォルダだけです。

image-20250120113144296
まず common フォルダを見てください。ここにあるものは実際にはすべて必要なソースコード、つまりプロジェクトに必要なファイルですが、いくつか注意すべき点があります。

image-20250120113152696
stc フォルダの下には、tx_trace_xx という名前のソースファイルがいくつかあります。これらはトレースデバッグ監視で使うソースコードです。

image-20250120113211734
inc フォルダの下にも、tx_trace.h というファイルがあります。

image-20250120113221624
こちらも TX_ENABLE_EVENT_TRACE マクロ定義を有効にしていなければ、ほとんど何もしません。

image-20250120113231145
ソースコードのフォルダに戻って、次に ports フォルダを見てみましょう。

image-20250120113327255
自分の環境に対応するカーネルを見つけます。

image-20250120113335373
自分の環境に対応するコンパイラを見つけます。ソースファイルとヘッダーファイルはどちらもプロジェクトに必要です。さらに注意すべきなのは、tx_misra.S が存在する場合は除外することです。tx_misra.c で既に定義されている可能性があります。

image-20250120113343609
ports/カーネル名/コンパイラ名/inc にある tx_port.h を簡単に紹介します。ここは ThreadX を調整するための唯一のインターフェースです。TX_ENABLE_EVENT_TRACE のように OS の機能を有効/無効にするマクロ定義は、コンパイラ全体の define に書くことができます。
ただ、79 行目を見ると、別の .h インターフェースが定義用に用意されています。TX_INCLUDE_USER_DEFINE_FILE マクロ定義をコンパイラ全体の define に書き、独自に作成した tx_user.h ファイルを介して OS のマクロ定義を制御できます。
この tx_user.h にはサンプルがあります。OS ソースコードの common\inc の下に、tx_user_sample.h または類似の名前のファイルがサンプルとしてあります。ただし、tx_user.h というファイル名は自分で作成するか、サンプルファイルをリネームする必要があります。

image-20250120113414656
common\src の下に tx_thread_initialize.c があります。その中にある変数で、実行時の設定状況を確認できます。この変数は tx_thread.h 内でも extern 宣言されているため、ThreadX OS を使っているときはどこからでもこの変数を参照でき、再宣言は不要です。
どうやって有効にする?

image-20250120113428701
私たちは AC6 コンパイラを使っていますが、まず gnu フォルダを見てみましょう。タスク作成の簡単なサンプルがあるからです。

image-20250120113436203
ここです!

image-20250120113446122
サンプルを簡単に分析します。
- ここはヘッダーファイルで、tx_api.h だけをインクルードしています。
- ここは main のエントリポイントです。
- ここは必ず自分で定義する必要がある関数です。この関数は _tx_initialize_kernel_enter() が ThreadX カーネルを起動する際に呼び出されます。つまり、カーネル起動後にユーザープログラムへ渡されるインターフェースです。

image-20250120113503114
このユーザーインターフェース関数を簡単に分析すると、ThreadX の主要な API を一通りデモしています。メモリ領域の確保、そのメモリを使ったタスクの作成、メッセージキューの作成、セマフォの作成など、よく使う API が含まれています。詳しい使い方はソースコードを直接確認してください。
このサンプル全体から、ThreadX カーネルを使うための基本操作は次の通りだとわかります。
tx_api.hをインクルードするvoid tx_application_define(void *first_unused_memory)を定義し、この関数が呼び出されたタイミングでタスクを作成する(この時点で ThreadX カーネルは起動済み)- メインプログラムで
tx_kernel_enter();を呼び出して ThreadX カーネルを起動する

サンプルと同じフォルダにあるこのファイルに注目してください。

image-20250120113526759
ここには、チップの割り込み処理を引き継いで ThreadX OS を動作させるための割り込み関数が定義されています。SYSTEM_CLOCK と SYSTICK_CYCLES を修正する必要があります。図の例では、600000 はチップのメインクロックが 6MHz であることを示し、100 は OS のクロック基準が 10ms であることを示します。つまり、tx_thread_sleep(1); は実際には 10ms 待機することになります。
実はこの .S ファイルはまだ修正が必要な箇所があります。一部の割り込みが定義されていないようです。STM32CubeMX で自動生成してから自分のプロジェクトに貼り付けるのが良いでしょう。OS が正常に動作しない場合、最も可能性が高いのはこの tx_initialize_low_level.s に問題があることです

image-20250120113610189
コンパイラ全体の define に、次の 1 行 TX_INCLUDE_USER_DEFINE_FILE を追加します。
モジュールマネージャー付きカーネルの移植
まず、モジュールマネージャーとモジュールが何かを確認しましょう。
モジュールマネージャーは ThreadX カーネルを持ち、ハードウェアを駆動できます。何らかのストレージメディアからモジュールの実行可能バイナリをロードできます(例:チップ内蔵フラッシュの 0x8100000 アドレスからモジュールをロード)。一方、モジュールはハードウェアを駆動できず、ThreadX カーネルも持たないため、単独では動作しません。ただし、独立したプロジェクトとして存在し、単独でコンパイル・リリースできます。
つまり、モジュールマネージャーとモジュールは別々のプロジェクトであり、移植に必要なソースコードも異なります。
なぜそんなことをする必要があるのかについては、ここでは触れません。
モジュールマネージャー付きのソースコードはどれ?

image-20250120113627567
図で囲った 3 つのフォルダが、モジュールマネージャー付きカーネルの移植に必要なすべてのソースコードです。とりあえず細かいことは考えず、この 3 つのフォルダを自分のプロジェクトに貼り付けてしまいましょう。
すでに純カーネル移植の内容を読んでいる前提なので、基本カーネルとトレースデバッグ追跡については理解しているものとします。それらの説明は繰り返さず、純カーネルと異なる点だけを説明します。
common_modules フォルダを見てください。

image-20250120113919648
モジュールマネージャー用カーネルとして必要なのは、囲った 2 つのソースコードフォルダです。module_lib はモジュール側に移植するためのソースコードです。
とりあえず細かいことは気にせず、この 2 つのフォルダのすべての内容を自分のプロジェクトに含め、後で調整するのがよいでしょう。
ports_modules フォルダを見てください。

image-20250120114052337
自分の環境に対応するアーキテクチャを見つけます。

image-20250120114059902
自分の環境に対応するコンパイラを見つけます。

image-20250120114113463
必要なのは、囲った 2 つのソースコードフォルダです。module_lib はモジュール側に移植するためのソースコードです。
細かいことは気にせず、この 2 つのフォルダのすべての内容を自分のプロジェクトに含めてしまい、後で調整しましょう。

image-20250120114125196
次に、サンプルから見つけるか、STM32CubeMX で tx_initialize_low_level.S を自動生成します。STM32CubeMX は modules プロジェクトの生成に対応しておらず、実際には適していません。modules を問題なく使うには、多くの独自の適応作業と操作が必要です。
この図のプロジェクトでは、サンプルから探すことをおすすめします。
純カーネル移植の説明で tx_initialize_low_level.S についてはすでに紹介したので、ここでは繰り返しません。

image-20250120114214674
このフォルダに戻り、txm_module_user_sample.h というファイルを見つけて、コピーして txm_module_user.h にリネームします。コンパイラ全体の define に TXM_MODULE_INCLUDE_USER_DEFINE_FILE が設定されている場合、モジュールマネージャープロジェクトとモジュールプロジェクトの両方で txm_module_user.h というヘッダーファイル(同じものでなければなりません)が呼び出され、OS の機能を制御します。

image-20250120114227489
txm_module_user.h の中身はだいたい次のような内容です。
tx_user.h も作成する必要があることを忘れないでください。純カーネルの説明にあります。
どうやって有効にする?
実際には、純カーネルの有効化方法と同じです。ただし、このカーネルを使う場合、標準的な方法はビジネスロジックをすべてモジュール化してロードすることです。しかし、モジュールプロジェクトの構築と両者のすり合わせはかなり面倒で、まだ完全には理解できていないため、ドキュメントにもしていません。
ただ、これを普通のカーネルとして使うぶんには問題ありません。