STM32 FreeRTOS シグナルイベントの動作を確認する

STM32 FreeRTOS シグナルイベントの動作を確認する

今回はFreeRTOSのシグナルイベントを使ってみます。

投稿時の開発環境を記しておきます。

PC:Windows10 OS
IDE: STM32CubeIDE Version1.3.0
Configurator: STM32CubeMX Version5.6.0
Board: STM32Nucleo-F401RE

FreeRTOSにおいて、タスク通知のひとつであるイベントフラグをFreeRTOSではシグナルイベントと呼びます。

今回はスイッチが押されたら、それを他のスレッドに伝えるというタスク間通信を行ってみます。
受け取った側ではLEDを点滅させてみます。

IDEのプロジェクトを作成する

File – New -STM32 Project を選択し、Boart SelectorタブからNUCLEO-F401REを選択しNextボタンを押します。

Project Nameは RtosSignal としておきます。
言語はCで良いので、そのままFinishを押します。

Initialize all peripherals with their default Mode? と聞いてくるので、Yesを押します。
This kinod of project is associated with the STM32CubeMx perspectiove.
Do you want to open this perspective now?と聞いてくるので、Yesを押します。

FreeRTOSを追加する

Pinout & Configuration – Categories の Middleware – FREERTOSをチェックします。
右側の FREERTOS Mode and Configuration の Mode , Interface から CMSIS_V1 を選択します。
これはOSのバージョンです。
どちらでも良いと思うのですが、安定しているV1の方を使ってみます。

SysTickを変更する

次に Pinout & Configuration – Categories の System Coreの SYS – Timebase Source から TIM5 を選択します。

FreeRTOSでは Timebase Sourceは SysTick 以外を使うことが推奨されているからです。

タスクを追加する

FreeRTOS Modeの下のConfigurationでTasks & Queuesを選択します。

Tasks用の上にある方の Addボタンを押します。

リストの以下の3項目だけ以下の通りに変更してOKボタンを押します。

Task Name : Receiver
Priority : osPriorityNormal
Entry Function : ReceiveFunc

ここで言うタスクはスレッドと同じ意味と考えて構いません。
この先はスレッドという言葉で統一します。

GPIOを設定する

Pinout & Configuration – Categories – System Core から GPIO を選択します。

GPIOタブが選択された状態で Pin Name の PA5 を選択します。

GPIO mode が Output Push Pull になっていることを確認します。

次に Pin Name の PC13-ANTI_TAMP を選択します。

GPIO mode が External Interruput Mode with Falling edge trigger detection になっていることを確認します。

続いて Pinout & Configuration – Categories – System Core から NVIC を選択します。

そして EXTI line[15:10] interrupts の Enabled にチェックを入れて割り込みを許可します。

シグナルイベントの実装

シグナルイベントについては こちら を参考にしてください。

コーディングする

main()の前に以下のコードを書きます。

/* USER CODE BEGIN 0 */

#define FLGPTN 0x00000001

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if (GPIO_Pin == GPIO_PIN_13)
  {
    osSignalSet(ReceiverHandle, FLGPTN);
  }
}
/* USER CODE END 0 */

ReceiveFunc()には以下のコードを書きます。

void ReceiveFunc(void const * argument)
{
  /* USER CODE BEGIN ReceiveFunc */
  /* Infinite loop */
  for(;;)
  {
	  for(;;)
	  {
	    osEvent event = osSignalWait(FLGPTN, osWaitForever);
	    if (event.status == osEventSignal && event.value.signals == FLGPTN)
	    {
	    	HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
	    }
	  }
      osDelay(1);
  }
  /* USER CODE END ReceiveFunc */
}

コードの概要

osSignalSet()

第1引数:osThreadCreate()で取得した osThreadId型の値
第2引数:信号フラグ

osSignalWait()

第1引数:信号フラグ
第2引数:タイムアウト値(ミリ秒)、または無限待ち(osWaitForever)

osSignalSet()でシグナルイベントをセットし、
osSignalWait()で待ちます。
osSignalWait()からぬけた後、if()でフラグの確認を行ってから処理します。

スイッチを押すたびにLD2(緑)が点滅すれば成功です。

スイッチ押下の検出に割り込みを使いました。
GPIOの割り込みに関して詳しく知りたい方は HALのGPIOで割り込みを使ってみる の記事をご覧ください。

皆さん、いかがでしたか?うまくLチカできましたか。

FreeRTOSカテゴリの最新記事