Azure RTOS習得(3):新規Azure RTOSプロジェクト

Azure RTOS習得3回目は、新規STM32CubeIDE Azure RTOSプロジェクト作成方法と、STM32CubeMX生成ソースコードの、どこに、何を、追加すれば良いかを説明します。

新規「汎用」Azure RTOSプロジェクト

前稿で、STM32G4(Cortex-M4/170MHz)評価ボード:NUCLEO-G474REへArduinoプロトタイプシールドを追加し、最も基本的なAzure RTOS ThreadXサンプルコードのTx_Thread_Creation動作を解説しました。

このTx_Thread_CreationサンプルコードのTx_Thread_Creation .icoから、新規の「汎用」AzureRtos0プロジェクトを作成します。

汎用の意味は、このAzureRtos0プロジェクトへセマフォやキューなどのRTOS機能を追加し、Azure RTOS習得に使うからです。

残念ながら現時点では、STM32G4用Azure RTOSセマフォやキューのサンプルコードは無いため、これらRTOS単独機能を持つプロジェクトを自作する訳です。

AzureRtos0プロジェクトから自作予定のAzure RTOS機能プロジェクトが以下です。

・AzureRtosEventFlagプロジェクト(本稿)
・AzureRtosQueueプロジェクト
・AzureRtosMutexプロジェクト
・AzureRtosSemaphoreプロジェクト

Tx_Thread_Creation .ico

STM32CubeIDE(以下CubeIDE)の新規STM32プロジェクトは、様々な作成方法があります。

ただ、Azure RTOSプロジェクトは、STM32CubeMX(以下CubeMX)の設定に、ベアメタル開発と異なる注意が必要です。このような時は、既に設定済みのCubeMX Configuration File (.ico)を流用すると、注意事項を含んだ新規プロジェクト作成が簡単にできます。

Azure RTOSプロジェクトのCubeMX設定の注意事項は、別途投稿します。本稿は新規Azure RTOSプロジェクト作成に焦点を置き説明します。

新規汎用AzureRtos0プロジェクト作成

Tx_Thread_Creation .icoを流用したAzureRtos0プロジェクト作成手順が下記です。

① CubeIDEのInformation Centerℹ️でStart new project from STM32CubeMX file(.ioc)クリック
② STM32CubeMX ico fileにTx_Thread_CreationのTx_Thread_Creation .ico選択、Project NameにAzureRtos0を入力しFinishクリック

Tx_Thread_Creation.ico流用の新規プロジェクト作成
Tx_Thread_Creation.ico流用の新規プロジェクト作成

③ PA5ユーザラベルをLD2へ変更、PC4とPC5をGPIO Output、ユーザラベルLED1、LED2に設定、PC7をGPIO Input、ユーザラベルS1に設定(LD2は評価ボード、LED1/2、S1は追加Arduinoプロトタイプシールドのポート)

ユーザラベル変更とArduinoプロトタイプシールドポートLED1/2とS1追加
ユーザラベル変更とArduinoプロトタイプシールドポートLED1/2とS1追加

④ Project>Generate Codeをクリックし、初期設定コードとAzure RTOSプロジェクトファイル生成
⑤ main.c L92へ、下記タイトルVCPメッセージ出力HALコード追記

VCPメッセージ出力HALコード追記
VCPメッセージ出力HALコード追記

⑥ ビルドし、評価ボードへダウンロード
⑦ Tera Termなどのターミナルソフトで追記VCPメッセージを確認し、新規汎用AzureRtos0プロジェクト動作確認

新規汎用AzureRtos0プロジェクト動作確認
新規汎用AzureRtos0プロジェクト動作確認

Azure RTOSイベントフラグ機能追加

AzureRtos0プロジェクトへ、イベントフラグを使ってメインスレッドとスレッド1/2間同期を行う機能を追加し、AzureRtosEventFlagプロジェクトを作成します。

このプロジェクトは、Azure RTOS ThreadXサンプルコードと同じ処理内容です。従って、Azure RTOS ThreadXサンプルコードが、AzureRtos0へ追記するコードの代用に使えます。

始めに、AzureRtos0プロジェクトファイルの、どこに、何を追加するかを説明し、次章で実例を示します。

追記ファイル 追加内容
Core>Src>
app_threadx.c
1) UINT App_ThreadX_Init()へ、イベントフラグ生成関数、追加スレッド生成関数
2) 追加スレッドのエントリ関数(メイン関数)
Core>Inc>
app_threadx.h
追加スレッド優先度、プリエンプション閾値などのマクロ

RTOSであっても、ベアメタル開発で機能追加する時と同じ追記ファイルと追加内容です。

違いは、App_ThreadX_Init()の中でイベントフラグや追加スレッドを生成すると、直にRTOS動作を開始(TX_AUTO_START)する点です。従って、ベアメタル関連main.c/hの変更点は、VCP出力メッセージの変更程度です。

つまり、RTOS関連とベアメタル関連、それぞれのメインエントリー(メイン関数)があり、RTOS動作追加だけなら、main.c/hは不変でも構いません。

筆者は、cファイルとhファイルを一緒に記述したい派です。しかし、CubeMXがこれらを分離してRTOS関連ファイルを生成しますので、このファイル分離に従い追記します。

スレッド優先度やプリエンプション閾値を変えれば、Azure RTOS動作が簡単に変わりますので、分離の方が好ましいのかもしれません(動作変更例は、Azure RTOS習得(2)の4章:メインスレッド参照)。

AzureRtosEventFlagプロジェクト作成

AzureRtos0プロジェクトはテンプレートとして様々なプロジェクトで利用しますので、CubeIDEでAzureRtos0プロジェクトをコピーし、別名のAzureRtosEventFlagプロジェクトとしてペーストして使います。ペースト先のAzureRtos0.icoも、AzureRtosEventFlag.icoへRenameします。

これで、AzureRtosEventFlagプロジェクトのひな型ができました。

AzureRtosEventFlagプロジェクトの追記部分抜粋が下記です。追記コードは、Azure RTOS ThreadXサンプルコードです。

CubeMX生成コメントの、/* USER CODE BEGIN … */、/* USER CODE END …*/が、追記ガイドに役立ちます。

※手抜きご希望の方は、Azure RTOS ThreadXサンプルのapp_threadx.cとapp_threadx.hを、そのままAzureRtosEventFlagのapp_threadx.cとapp_threadx.hへ上書きしてもOKです😅。但し、LED1/2への出力は変更してください。

AzureRtosEventFlagプロジェクトへ追記後、ビルドし評価ボードへダウンロードします。

App_threadx.c追加例

app_threadx.c追記ソースコード抜粋
app_threadx.c追記ソースコード抜粋(下線は要変更)

app_threadx.h追加例

app_threadx.h追記ソースコード抜粋
app_threadx.h追記ソースコード抜粋

AzureRtosEventFlagプロジェクト動作確認

AzureRtosEventFlagプロジェクトは、スレッド1がArduinoプロトタイプシールドのLED1制御、スレッド2がLED2制御を行う以外は、Azure RTOS ThreadXサンプルコードと同じ動作です。

従って、同じ動作を確認しAzureRtosEventFlagプロジェクト作成の成功です。

作成したAzureRtosEventFlagプロジェクトを使って、イベントフラグの制御、スレッド1/2優先度やプリエンプション閾値変更によるArduino LED 1/2動作変化を確認し、イベントフラグ機能を習得してください。

本稿で作成したAzure RTOSイベントフラグの機能は、前稿で説明済みですので、割愛します。

まとめ

Azure RTOS ThreadXサンプルコードのTx_Thread_Creation.icoを流用した、新規汎用AzureRtos0プロジェクト作成方法を示しました。

汎用AzureRtos0プロジェクトに、RTOS機能別プロジェクト例として、イベントフラグ機能を追加したAzureRtosEventFlagプロジェクトを作成し、Azure RTOS ThreadXサンプルコードと同じ動作を、評価ボードにArduinoプロトタイプシールド追加し確認しました。

機能追加したAzureRtosEventFlagプロジェクトにより、汎用AzureRtos0プロジェクトソースコードのどこに、何を追記するかを示しました。

今後、AzureRtos0プロジェクトへセマフォなどの機能を追加し、Azure RTOS機能別習得をすすめます。

付記:日本語文字化け対策

デフォルトのSTM32CubeIDEとSTM32CubeMXを使ってプロジェクト開発時、日本語文字化けが発生します。過去投稿済みの対策を付記します。

STM32CubeMXのプロジェクトGenetate Code実行「前」に、
STM32CubeIDEの設定変更
① Windows>Windows>Prefernces>Colors & font>文字セットを「日本語」へ設定
② Project>Properties>Text file encordhingをOthers:「Shift-JIS」へ設定

以上で、Genetate Codeしソースコードが上書きされても、日本語文字化けは無くなります。

Azure RTOS習得(2):Azure RTOS ThreadXサンプルコード

Azure RTOS習得2回目は、STM32G4 Azure RTOS ThreadXサンプルコードを解説します(コチラの投稿3章でAzure RTOS開発ツール動作確認に使ったコード)。

STM32G4 Azure RTOS ThreadXサンプルコードは、スレッド優先度とプリエンプション閾値を、スレッド実行時に変更する例と、スレッド間同期にイベントフラグを用いる例を示しています。

STM32G4 Azure RTOS ThreadXサンプルコードの3スレッド

注意)サンプルコードのプリエンプション閾値とREADME記述が異なります。正しくは下記です。

スレッド名 処理内容

(LD2:評価ボード単体)

優先度 プリエンプション閾値
メインスレッド スレッド1/2優先度と閾値変更→LD2点灯シナリオ制御 5 5
スレッド1 LD2を5秒間500msで点滅 10 10
スレッド2 LD2を5秒間200msで点滅 10 9

評価ボード:NUCLEO-G474REは、ユーザLED:LD2を1個実装しています。1個のLD2を2個のスレッド1/2で制御するため、点滅間隔を変えることでどちらのスレッド制御かを示します。また、メインスレッドとスレッド1/2間の同期に、Azure RTOSイベントフラグを用います。

この評価ボードに、2個LED1/2、1個SWを実装したArduinoプロトタイプシールドを追加し、各スレッド処理を、下記のように工夫しました。

スレッド名 処理内容

(LD2:評価ボード+

LED1/LED2/S1:Arduinoプロトタイプシールド

優先度 プリエンプション閾値
メインスレッド スレッド1/2優先度と閾値変更→LD2点灯シナリオ制御 5 5
スレッド1 LED1を5秒間500msで点滅 10 10
スレッド2 LED2を5秒間200msで点滅 10 9

評価ボード単体で複数スレッド動作を確認するよりも、断然判り易くなります。

もちろん、評価ボード単体でも確認可能です。しかし、イベントフラグだけでなくセマフォなど今後様々なAzure RTOS機能習得にも、Arduinoプロトタイプシールド追加は、役立ちます。

また、VCP:Virtual Com Portへメッセージを出力する工夫も加え、タイトルやエラー表示を行います(評価ボード+Arduinoプロトタイプシールド動作例は、5章図)。

イベントフラグ

Microsoft公式Azure RTOS ThreadXサイト第 3 章:Azure RTOS ThreadX 機能を開き、右コラム“この記事の内容”のイベント フラグをクリックすると、イベント フラグの説明が示されます。要旨を抜粋すると、

・イベントフラグは、スレッド間同期手段。32フラグ単位グループ化可能、待ちタイムアウトなどあり
・tx_event_flags_set でフラグ設定、tx_event_flags_get でフラグ取得(AND/OR演算可能)
第 4 章:APIに、tx_event_flags_setやtx_event_flags_getの詳細記述

例えば、4章でtx_event_flags_set は、ソースコードへひな型をコピー&ペーストできる形で表現されています。

tx_event_flags_setのAPI
tx_event_flags_setのAPI

スレッド1/2

以下、説明が簡単になるので、オリジナル評価ボードソースにコメント追記したコードで説明します。

スレッド1/2は、初期設定+無限ループの簡単で単純な構成です。

スレッド1(評価ボード単体動作ソースコード)
スレッド1(評価ボード単体動作ソースコード)

スレッド1は、500msトグルを5秒間繰返し、5秒経過後、イベントフラグ:THREAD_ONE_EVTをセットします。スレッド2は、200msトグルとイベントフラグ:THREAD_TWO_EVTがスレッド1と異なるのみです。

フラグセットAPI失敗時は、Error_Handle内で停止します。

メインスレッド

メインスレッド(評価ボード単体動作ソースコード)
メインスレッド(評価ボード単体動作ソースコード)

メインスレッドは、LD2点滅シナリオを作成します。優先度が5で高優先なので、低優先スレッド1/2からのイベントフラグセットを常時ゲットできます。

スレッド1/2優先度は同一の10ですが、L170でスレッド1のイベントフラグを永遠に待つので、スレッド2はスレッド1と多重動作ができません。

スレッド2のプリエンプション閾値が9なのに、スレッド1が先に動作するのは、スレッド1がtx_thread_createで先に生成、開始(TX_AUTO_START)するからです。試しに、スレッド2を先に生成すると、LD2は200ms点滅から始まりシナリオは進みません。スレッド1→2の生成順序なら、スレッド2のプリエンプション閾値は、10でもLD2は、同じシナリオで点滅します。

スレッド1のイベントフラグを得た後、スレッド2優先度と閾値を(8、8)へ変更するのは、スレッド2単独動作のためです。その後、L179でスレッド2のイベントフラグを永遠に待ちます。

スレッド2のイベントフラグを得ると、スレッド2優先度と閾値を元の(10、9)へ変更します。このシナリオを3回繰返します。

シナリオ終わりにスレッド1/2をterminateさせるのは、動作不要だからです。terminateしなくても、メインスレッドプリエンプション閾値が5なので、スレッド1/2は動作しません。従ってLD2動作シナリオは変わりません。

シナリオは変わりませんが、terminateをコメントアウトした時のThreadX Thread Listとオリジナルの時のListが下記です。不要スレッドは、Terminate Stateへ入れると他へ影響を与えないメリットがあります。

スレッド1と2 terminate有無の差
スレッド1と2 terminate有無の差

RTOS習得とArduinoプロトタイプシールド追加

ベアメタル開発のLチカ理解に相当するのが、本稿説明のスレッド間同期イベントフラグをはじめとする多様なRTOS機能理解です。

本稿サンプルコード動作程度であれば、ベアメタルで開発する方が簡単です。但し、ベアメタルでは、動作に必要な機能を全てユーザが開発します。

一方、RTOS開発では、RTOSが提供する機能を活用し、残りの差分をユーザ開発しさえすればアプリが完成します。下図のようにベンダー提供資産(RTOS、セキュリティなどのミドルウェアやドライバ)有効活用が、現代的MCUユーザアプリケーション開発の肝です。RTOS機能が多すぎるのが、玉に瑕ですが…😂。

現代的ユーザMCU開発の例(出展:The ST blog)
現代的ユーザMCU開発の例(出展:The ST blog)

RTOS活用で、ユーザアプリケーションが資産化できます(RTOSの目的が、アプリケーション資産化なので当然です)。

メインスレッド章で説明したように、スレッド1/2はそのままで、RTOSのスレッド生成順序やプリエンプション、イベントフラグのみでLD2点滅シナリオ変更が簡単にできます。ソフトウェア規模が大きくなれば、このメインテナンス性の良さが活きてきます。

多様なAzure RTOS機能を手間なく効率的に学ぶには、Arduinoプロトタイプシールドを評価ボードに追加し、思いついたRTOS機能を直に試すことをお勧めします。

Arduinoプロトタイプシールド追加により、スレッド毎の動作を別々のLEDで目視でき、メインスレッドがスレッド2の優先度、閾値を変更しない場合、スレッド1と並列動作するか等々、様々な試行を簡単に確認できます。この試行で、ベアメタル開発経験も活かせます。

つまり、過去に開発したベアメタル機能が、RTOSに有るか無いかを、多くのRTOS機能をふるい(経験)にかけながらRTOS習得ができる訳です。

今後のAzure RTOS習得は、Arduinoプロトタイプシールドを評価ボードへ追加した構成で、新規Azure RTOSプロジェクトをRTOS機能毎に作成し行います。

新規Azure RTOS機能プロジェクト作成方法は、次回投稿予定です。

評価ボードへArduinoプロトタイプシールドを追加しスレッド毎にLED点滅中
評価ボードへArduinoプロトタイプシールドを追加しスレッド毎にLED点滅中

まとめ

STM32G4 Azure RTOS ThreadXサンプルコードを解説しました。本稿で説明したAzure RTOS APIは、下記です。

・スレッド間同期イベントフラグ:tx_event_flags_set/getと、待ち処理
・スレッド優先度、プリエンプション閾値変更:tx_thread_priority/preemption_change
・スレッド終了:tx_thread_terminateと、Terminate State目的
・スレッド生成:tx_thread_createと、TX_AUTO_START、生成順序

優先度とプリエンプション閾値をスレッド実行時に変更できる機能は、スレッド開発が容易で流用性を高め、ユーザ開発アプリケーションの資産化に効果があります。

ユーザLEDが1個のみ搭載の評価ボードを使い複数スレッド動作を確認するよりも、2個LEDやユーザS1搭載のArduinoプロトタイプシールド追加により、RTOS APIパラメタ変更時の各スレッド動作確認が容易です。

意図しないスレッド並列処理も直ぐに判るので、効率的にAzure RTOS習得ができます。Arduinoプロトタイプシールド付属の小さなブレッドボード利用も試行実験に便利です。

多くのパラメタを持つAzure RTOS効率的習得に、評価ボード+Arduinoプロトタイプシールドをお勧めします。