前回記事では、ひとまずFreeRTOSを動かしてみる、までやってみました。
今回(から)は、FreeRTOSの主要機能を体験してみたいと思います。
はじめに
CMSIS-RTOS
当初、動作確認においては、FreeRTOSのI/Fをまんま使おうかと思っていました。
がしかし、STM32CubeIDEの生成コードを見るに、CMSIS I/Fでラップしている模様です。
郷に入りては、、、で、そいつに従うこととします。仕様は以下。
Function Overview
http://www.keil.com/pack/doc/CMSIS/RTOS/html/functionOverview.html
機能を選ぶ
RTOSといえばタスク間通信、タスク間通信で最も簡単なものといえば、イベントフラグでしょう。
前述CMSISによれば、こいつを**「シグナルイベント」**と呼ぶらしいです。今回はそれを紹介します。
本編
1. 環境
前回記事と同じです。
なお、FreeRTOSの有効化やタスク追加等はこの記事に倣っていますので、いったんは試してみることをお勧めします。
- IDE: STM32CubeIDE
- 評価用ボード: STM32L4 Discovery kit IoT node - 型番はB-L475E-IOT01A
2. やってみよう!
実現仕様は以下。地味に高機能です。
2-1. U(S)ART割り込み有効化
「Device Configuration Tool」(iocファイルが開いた状態)の左側、「Categories」から「Connectivity」-「USART1」を選びます。
その後、「NVIC Settings」タブで、割り込みを有効化します。
設定変更したので、コード生成も忘れずに!
2-2. 割り込み実装
main.cの上部、「/* USER CODE BEGIN 0 */」の箇所を以下とします。
/* USER CODE BEGIN 0 */
uint8_t g_RxData;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* Re-Initialize Rx */
HAL_UART_Receive_IT(&huart1, &g_RxData, 1);
/* Set Signal */
osSignalSet(myTask02Handle, 1);
}
/* USER CODE END 0 */
2-3. タスク実装
ユーザータスクを以下とします。
/* USER CODE BEGIN StartTask02 */
/* Initlize Rx */
HAL_UART_Receive_IT(&huart1, &g_RxData, 1);
/* Infinite loop */
for(;;)
{
/* Wait Signal */
osSignalWait(1, osWaitForever);
/* Echo Back */
HAL_UART_Transmit_IT(&huart1, &g_RxData, 1);
osDelay(1);
}
/* USER CODE END StartTask02 */
2-4. 動かしてみる
Tera Termで動作確認しましたが、無事入力した文字がエコーバックされています(雑)!
3. かんたんな解説
実現仕様とコメント、実動作の通りです、、、というのはさすがに雑過ぎますね。笑
3-1. シグナルイベント(イベントフラグ)とは
シグナルイベント(イベントフラグ)は、名前通りイベント(=何かあったよ!)を通知する仕組みです。
本例でのイベントとは、**「受信したことをタスクに伝える」**です。
/* Set Signal */
osSignalSet(myTask02Handle, 1);
でイベントを設定しています。第一パラメータはタスクハンドル(タスクを指し示す番号)。
/* Wait Signal */
osSignalWait(1, osWaitForever);
でイベントを待ち合わせています。第二パラメータは「無限に待つよ」という意味です。
ともに存在するパラメータ「1」は、イベントを指し示すビットです。
参考までに、CMSIS仕様は以下です。
Signal Events
http://www.keil.com/pack/doc/CMSIS/RTOS/html/group__CMSIS__RTOS__SignalMgmt.html
3-2. U(S)ART受信割り込み
最初に以下呼び出しをしないと、受信割り込みが上がりません。
また、割り込みハンドラで再度呼び出さないと、以降の割り込みが上がりません。よって複数個所に記載しています。
HAL_UART_Receive_IT(&huart1, &g_RxData, 1);
パラメータは「1byte受信したら割り込みを上げなさいよ」としています。
3-3. 問題点
タスク(イベント受信側)で受信データを吸い上げていますが、タイミング的に遅い可能性があります。
本来は、割り込みで速やかに受信データを退避してから、何らかの手段でタスクに通知すべきでしょう(と次回記事への伏線を書いてみました)。
おわりに
uITRONなどと比べると、断然シンプルでわかりやすく、使いやすいと思います!
次回もタスク間通信、メッセージあたりの記事を書く予定。