STM32のFreeRTOSでシグナル(タスク通知)の使い方を、サンプルコードと合わせてわかりやすく解説します。
シグナルとは
CMSIS RTOSにおいてタスク通知のことをシグナルと呼びます。本記事でもこれ以降、タスク通知のことをシグナルと表記します。
作成するプログラム
まずはゴールを確認しましょう。今回はシグナルを使って、ボタンが押される度にLEDが点灯・消灯するプログラムを作ります。
バイナリセマフォを使ったプログラムのシグナル版ですね。バイナリセマフォの時のソースコードと比較すると、シグナル版のシンプルさがよくわかるかと思います。
前提条件
前提条件は目次の記事を参照してください。
プログラムの作成
割込みハンドラの設定
割り込みハンドラの設定については下記の記事で書いていますので、そちらを参照してください。
スレッドの作成
スレッドはデフォルトで用意されているdefaultTaskをそのまま使うことにしました。
設定が終わったらコードを自動生成してください。
ボタン押下時の処理を実装
ここからはコードを実装していきます。まずはボタン押下時の処理を実装しましょう。割り込みハンドラを使い、割込みの度にシグナルを通知しています。
main.c:割込みハンドラ
/* USER CODE BEGIN 4 */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { osSignalSet(defaultTaskHandle, 0b0001); } /* USER CODE END 4 */
osSignalSet()でシグナルを通知します。第1引数で通知先のスレッドのハンドルを指定します。第2引数で通知するシグナルのフラグを指定します。ここでは1ビット目にフラグを立てて通知しています。
なお、STM32のFreeRTOSでは、フラグは8ビットまで使用できます。
スレッドを実装
続いてdefaultTaskスレッドの中身を実装してあげましょう。ここではシグナルがある度にLEDを点灯・消灯するだけです。
main.c:defaultTask
void StartDefaultTask(void const * argument) { /* USER CODE BEGIN 5 */ /* Infinite loop */ for(;;) { osEvent event = osSignalWait(0b0001, osWaitForever); if (event.status == osEventSignal && event.value.signals == 0b0001) { HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); } } /* USER CODE END 5 */ }
osSignalWait()で通知を待ちます。第1引数で待機するフラグを指定します。第2引数で待機時間をms間隔で指定します。返り値はosEventです。
osEventを使ってシグナルイベントであることと、フラグを確認しています。
ここで、シグナルのフラグについてCMSIS RTOSの仕様と異なる箇所があるので補足しておきます。
まず前提として、今回の例ではフラグは1つだけでしたが、一度に複数指定することができます。例えば『0b0011』という感じです。
そしてCMSIS RTOSの仕様では、全てのフラグが発生した時のみ、osSignalWait()で処理が戻ることになっています。しかし、STM32のFreeRTOSでは、複数のフラグの内1つでもフラグが発生していたら、osSignalWait()の待機が解除されてしまいます。
サンプルコードでosEventSignalの確認だけでなく、フラグも確認しているのはそのためです。
なぜこのような実装なのかは正確なことはわかりませんが、私はこれは意図したものではないかと考えています。現在の実装であれば、1つのタスクで複数のフラグを待機することができますし、全てのフラグの発生を待機することも工夫すればできるからです。CMSIS RTOSの仕様だと、前者の1つのタスクで複数のフラグを待機することは難しいです。直列的にフラグを待機することもできますが、あまり美しい書き方とは言えません。
CMSIS RTOSもそれに気づいたのか、v2になると両方の方法で待機できるようにオプションが追加されました。
長くなってしまいましたが、CMSIS RTOSと仕様が異なる部分がありますが、これはこれで悪くない仕様ですので、ここはそういうものと割り切って使いましょう。
プログラムの作成は以上です。実際に動かしてボタン押下の度にLEDが点灯・消灯することを確認してみてください。
まとめ
STM32のFreeRTOSのシグナルの使い方は以上です。
CMSIS RTOSにおいてタスク通知のことをシグナルと呼びます。STM32のFreeRTOSのシグナルは、CMSIS RTOS準拠でない部分がありますが、目くじら立てず、注意して使いましょう。