2018年2月25日日曜日

STM32 Nucleo FreeRTOS Lチカまで on Mac memo

[目標]
・FreeRTOSを使ってLチカ
  ・作成するタスクは1つ
  ・周期タイマで0.5秒周期で点滅させる

[前提]
・NucleoL152RE を使用
・NucleoにデフォルトでのってるLED(LD2) をLチカ
・開発環境 SW4STM32(AC6)
・コード生成ツールSTM32CubeMX を使用
・開発環境の構築,プロジェクトの作成は,
http://chuchulabo.blogspot.jp/2018/02/stm32-on-mac-memo.html
を参照。

[手順]

== タスクの追加 ==

http://chuchulabo.blogspot.jp/2018/02/stm32-on-mac-memo.html
で作成したプロジェクトをそのまま変更する(めんどいから)。
CubeMXのプロジェクトファイルを開く。
左サイドバーの FREERTOS->Enabled にチェックを入れる。
これだけで,FREERTOSをプロジェクトに入れてくれる。すごい!
タスクの設定をする。
まずは,LEDタスクを作成する。
これも,CubeMXで行う。
「Configuration」タブ -> 「FREERTOS」 をダブルクリック。
FREERTOS Configuration のダイアログが開くので,設定を変更する。
「Tasks and Queues」タブ -> Tasksの方の「Add」ボタンをクリック。


New Task ダイアログが開くので,LEDタスクを設定する。
以下のように設定して,「OK」を押す。
すると,LEDタスクが追加される。
追加されたのを確認したら,「Apply」をクリック -> 「OK」をクリック。

Project->generate Code で,コード生成を開始する。
すると,次のようなダイアログが出る。
よくわからんが,「Yes」を押す。
すると,CubeMXがよしなにコードを生成してくれる。
素晴らしい!

main.cでは,
MX_FREERTOS_Init();
が呼び出されているだけ。
中身は,freertos.c に書いてある。
ちゃんとvoid StartLedTask(void const * argument) ってのが生成されている。



== ちょっとFreeRTOSとCMSISについてメモ ==
使うとチェックを入れたのはFree RTOS。
だが,実際には,Free RTOSのAPIをラッパーしたCMSISのAPIを使用して,
タスクの生成は行われている。

osThreadDef とか,osThreadCreate というのは,CMSISのAPI。

FreeRTOSについて
https://www.freertos.org/index.html

CMSISについて
http://www.keil.com/pack/doc/CMSIS/RTOS/html/index.html

CMSISは,FreeRTOSや,その他のRTOSであっても,共通して使用できるように
策定されたもの。
CMSISのAPIを使っていれば,FreeRTOSから他のRTOS(ThreadXとか?)に変えても,
CMSISの部分が吸収してくれて,移行が簡単になる。

だから,今回は,CMSISのAPIをなるべく使うようにする。
(CubeMXが勝手にやってくれるんだろうけど)

== 周期ハンドラの追加 ==
タイマー機能を使用して,周期ハンドラを作る。
まず,CubeMXで設定を行う。
タイマー機能を使用するため,ソフトウェアタイマを有効にする。
「Configuration」タブ -> 「FREERTOS」 をダブルクリック。
FREERTOS Configuration ダイアログが開く。
「Config parameters」タブ->「Software timer definitions」->「USE_TIMERS」を「Enabled」に変更。
次に,タイマーを作成する設定を行う。
「Timers and Semaphores」タブ->「Timers」の「Add」ボタンをクリック。
NewTimerダイアログが開くので,以下のように設定して,「OK」をクリック。
LEDの点滅用のタイマーなので,名前をLedTimerにした。
Callbackは,タイマーで一定時間たった時に呼ばれるコールバック関数の事。

「Apply」->「OK」をクリックして,FREERTOSの設定終了。
と思ったけど,なんか,「Free RTOS Heap Usage」タブで,「×」が表示されててだめっぽいところがある。読むと,Heapサイズが足りてないっぽい。
タイマーをEnableにしたせいで,使用するHeapサイズが足りなくなったらしい。
とりあえず,Heapサイズを多くとるようにする。
「Config parameters」タブ->「Memory management settings」->「TOTAL_HEAP_SIZE」を3072→4096に変更。
すると,「Free RTOS Heap Usage」タブの「×」が「✔︎」に変わる。

これでOK!多分。
「Apply」->「OK」を押して,FREE RTOSの設定を完了する。

コード生成をしてみる。
「Project」->「Generate Code」で,コードを生成する。

freertos.cをみると,タイマが追加されていることがわかる。




== コーディング ==
MX_FREERTOS_Init(void) でタスクもタイマも作成されている。
タスクに関しては,osThreadCreate() したら,始まるみたい。
ただ,タイマは,osTimerStart()しないと,始まらないっぽい。
というわけで,
LEDタスクからLEDタイマを開始して,
LEDタイマのコールバック関数内でLEDを点滅させる。
まず,タイマをスタートさせる。

以下,コード。
-------------------------------------------------
/* StartLedTask function */
void StartLedTask(void const * argument)
{
  /* USER CODE BEGIN StartLedTask */
  osTimerStart(LedTimerHandle, 500);
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END StartLedTask */
}

/* LedTimerCallback function */
void LedTimerCallback(void const * argument)
{
  /* USER CODE BEGIN LedTimerCallback */
  HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
  
  /* USER CODE END LedTimerCallback */

}
-------------------------------------------------


さらに,freertos.cは,HALライブラリをincludeしてないので,
HAL_GPIO_TogglePin()でエラーになる。
ので,HALをincludeする。
以下,コード。
-------------------------------------------------
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "cmsis_os.h"

/* USER CODE BEGIN Includes */     
#include "stm32l1xx_hal.h"


/* USER CODE END Includes */
-------------------------------------------------

以上,コーディング終わり!
500ms周期でLEDが点滅するはず!

Build -> Debug -> Resumeで,実行すると,
LEDが500ms周期で点滅した!
成功!

0 件のコメント:

コメントを投稿