STM32のFreeRTOSでバイナリセマフォ使い方を、サンプルコードと合わせてわかりやすく解説します。
作成するプログラム
まずはゴールを確認しましょう。今回はバイナリセマフォを使って、ボタンが押される度にLEDが点灯・消灯するプログラムを作ります。Thread1スレッドはセマフォを取得し、取得できる度にLEDを点灯・消灯します。割込みハンドラ内でセマフォをリリースすることで、ボタン押下の度にLEDの点灯・消灯を実現します。
前提条件
前提条件は目次の記事を参照してください。
プログラムの作成
割込みハンドラの設定
割り込みハンドラの設定については下記の記事で書いていますので、そちらを参照してください。
スレッドの作成
Thread1はデフォルトで用意されているdefaultTaskを変更して作りました。
バイナリセマフォの作成
バイナリセマフォを作ってみましょう。
- Pinout & Configurationsタブ→Middleware→FREERTOS→Timers and Semaphoresタブ
- Binary SemaphoresのAddボタンをクリックしてバイナリセマフォの設定画面を開いてください
- 下記の図のように入力し、OKボタンをクリックしてください
ここでの設定項目については下記の表を参照してください。
項目 | 説明 |
Semaphore Name | セマフォの名前 |
Allocation |
メモリ確保の方法を指定します Dynamicだと動的に生成。 Staticだと静的に生成。 |
Control Block Name | コントロールブロックの名前。Staticの時のみ使用。 |
設定が終わったらコードを自動生成してください。
ボタン押下時の処理を実装
ここからはコードを実装していきます。まずはボタン押下時の処理を実装しましょう。割り込みハンドラを使い、割込みの度にセマフォをリリースしてあげます。
main.c:ボタン押下時の処理
/* USER CODE BEGIN 4 */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { osSemaphoreRelease(BinarySem1Handle); } /* USER CODE END 4 */
HAL_GPIO_EXTI_Callbackはweak宣言されたデフォルトの関数があるので、main.cの中で新たに作って上書きしています。
スレッドを実装
続いてThread1スレッドの中身を実装してあげましょう。ここではセマフォをリリースする度にLEDを点灯・消灯するだけです。
main.c:Thread1の実装
void Thread1Func(void const * argument) { /* USER CODE BEGIN 5 */ /* Infinite loop */ for(;;) { if (osSemaphoreWait(BinarySem1Handle, osWaitForever) == osOK) { HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); } } /* USER CODE END 5 */ }
osSemaphoreWait()でセマフォのリソースを取得します。第1引数でセマフォのIDを指定しています。第2引数がリソースの取得待ち時間で、osWaitForeverを指定することでずっと待つようにしています。
返り値でリソースの取得可否を判断し、osOKだった場合にLEDの点灯・消灯を行っています。なお、この動作はCMSIS RTOS v1の仕様ではなくv2の仕様です。v1では残っているリソースの数が返るので、CMSIS RTOS v1を期待してプログラムを作るとうまく動作しないので注意してください。
プログラムの作成は以上です。実際に動かしてボタン押下の度にLEDが点灯・消灯することを確認してみてください。
まとめ
STM32のFreeRTOSを使ったバイナリセマフォの使い方は以上です。
使い方自体は非常に簡単だと思いますが、osSemaphoreWait()の返り値がCMSIS RTOS v1の仕様と異なる点だけ注意が必要ですね。記憶の片隅に入れておきましょう。
関連:STM32のFreeRTOSのカウンティングセマフォの使い方