最終更新: llysfactoryll 2020年08月29日(土) 19:24:01履歴
μITRONをSTM32に移植しようとしているが、多重割り込みに対応できないところで止まっている。
それならば苦労せず、freeRTOSを使ってみようか、という企画。
題して〔STM32F4DISCOVERY/STM32CubeIDEで、freeRTOSを使う〕。
結論的には、特に苦労もなく実行できるようになった。
最後にμITRONとの実装の比較も載せる。
まずはOS以前に、プロジェクトの生成手順です。
※Start new STM32 projectを選ぶ。
※Board SelectionからSTM32407G-DISC1を選ぶ。
※なんとなくC++も使えるようにしておきました。
スクリーンショットはPDF版を見てください。
1-start.pdf
※MX画面、ModdlewareのFREERTOSにチェックを入れる。
※タイムベースを設定する。SysTickを使わない方が良いらしい。
TIM5を使用する。
ここで言うタイムベースは、OSが使用するものではなさそう?
※ビルドしようとするとダイアログが出て、コードが自動生成される。
これで無事、アイドルタスクが走り出した。デフォルトタスクも動いていた。
スクリーンショットはPDFを見てください。
2-add-freeRTOS.pdf
freeRTOSに、CMSISのラップがかかっている(freeRTOSとは、APIが違う)。
APIはCMSIS-RTOSだが、仕様はCMSIS-RTOSとは違う部分もあるらしい。
■タスク
DefaultTaskが最初から用意されているので、それを使ってみる。
タスクの実態は、Core\Src\main.cに生成されている。
●ふたつ目のタスクを追加すっる(タスク2)※優先度を高く(osPriorityHight)している。
■時間待ち
osDelay(1); ms単位。
■シグナル(イベントフラグの代わり?)
int32_t osSignalClear( osThreadId thread_id, int32_t signals )
int32_t osSignalSet( osThreadId thread_id, int32_t signals)
osEvent osSignalWait(int32_t signals, uint32_t millisec)
(TRON系フラグとの違い)
・指定したタスクにしか発生できない(タスク付属型)。
このPDF版はスクリーンショットはありません。
4-use-freeRTOS.pdf
(骨子)
TIM1を使う。
プリスケーラ × カウンタピリオド × 1/f = タイマー周期
400 × 42000 × 1/168M = 100ms
クロック周波数 f = 168MHz(後述参照)
(手順)
●タイマーの設定
※Clock Source = Internal Clock。Prescaler、Counter Periodには1小さい値を設定する。
●クロック周波数の確認
※APB2=168MHz --> TIM1
●割り込みを発生させる
■実装(100ms周期のタイマー割り込みの中からシグナルイベントを発生させ、タスクで受けてLEDをトグルする)
●初期化(要コーディング)
■割り込みハンドラが本当に割り込みの中で呼ばれているか確認する。
●割り込みハンドラにブレークをかけて、xpsrの値を調べる。
※xpsrの下位8ビットが0以外なので、割り込みハンドラであることが分かる。
※割り込みハンドラの中から、シグナルイベントを発生させている。
●シグナルイベントを受けるタスク側にブレークをかけて、xpsrの値を調べる。
※xpsrの下位8ビットが0なので、タスク(割り込みハンドラではない)ことが分かる。
※シグナルイベントを受けてLEDの点灯をトグルしている。
スクリーンショットはPDF版を見てください。
5-timer.pdf
同じことを、freeRTOSと、μITRONで行った場合の実装の違いを比較してみた。
4つのLEDを点滅させるだけのプログラムである。
基本的にはメインのタスクで、100msごとに順にトグルを繰り返しているが・・
LD6はメインのタスクから、ふたつ目のタスクへイベント(シグナル)を飛ばしてトグルさせている。
LD4は割り込みハンドラからイベント(シグナル)を飛ばして、LD6と同じふたつ目のタスクで受ける。
実装(ソースコード)はPDF版を見てください。
6-vs-tron.pdf
それならば苦労せず、freeRTOSを使ってみようか、という企画。
題して〔STM32F4DISCOVERY/STM32CubeIDEで、freeRTOSを使う〕。
結論的には、特に苦労もなく実行できるようになった。
最後にμITRONとの実装の比較も載せる。
開発環境 STM32CubeIDE 1.4.2
基板 STM32FDISCOVERY
CPU STM32F407VGT6
ARM Cortex-M4
まずはOS以前に、プロジェクトの生成手順です。
※Start new STM32 projectを選ぶ。
※Board SelectionからSTM32407G-DISC1を選ぶ。
※なんとなくC++も使えるようにしておきました。
スクリーンショットはPDF版を見てください。
1-start.pdf
※MX画面、ModdlewareのFREERTOSにチェックを入れる。
※タイムベースを設定する。SysTickを使わない方が良いらしい。
TIM5を使用する。
ここで言うタイムベースは、OSが使用するものではなさそう?
※ビルドしようとするとダイアログが出て、コードが自動生成される。
これで無事、アイドルタスクが走り出した。デフォルトタスクも動いていた。
スクリーンショットはPDFを見てください。
2-add-freeRTOS.pdf
freeRTOSに、CMSISのラップがかかっている(freeRTOSとは、APIが違う)。
APIはCMSIS-RTOSだが、仕様はCMSIS-RTOSとは違う部分もあるらしい。
■タスク
DefaultTaskが最初から用意されているので、それを使ってみる。
タスクの実態は、Core\Src\main.cに生成されている。
●ふたつ目のタスクを追加すっる(タスク2)※優先度を高く(osPriorityHight)している。
■時間待ち
osDelay(1); ms単位。
■シグナル(イベントフラグの代わり?)
int32_t osSignalClear( osThreadId thread_id, int32_t signals )
int32_t osSignalSet( osThreadId thread_id, int32_t signals)
osEvent osSignalWait(int32_t signals, uint32_t millisec)
(TRON系フラグとの違い)
・指定したタスクにしか発生できない(タスク付属型)。
このPDF版はスクリーンショットはありません。
4-use-freeRTOS.pdf
(骨子)
TIM1を使う。
プリスケーラ × カウンタピリオド × 1/f = タイマー周期
400 × 42000 × 1/168M = 100ms
クロック周波数 f = 168MHz(後述参照)
(手順)
●タイマーの設定
※Clock Source = Internal Clock。Prescaler、Counter Periodには1小さい値を設定する。
●クロック周波数の確認
※APB2=168MHz --> TIM1
●割り込みを発生させる
■実装(100ms周期のタイマー割り込みの中からシグナルイベントを発生させ、タスクで受けてLEDをトグルする)
●初期化(要コーディング)
HAL_TIM_Base_Start_IT(&htim1);●割り込みハンドラ(TIM共通)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { /* USER CODE BEGIN Callback 0 */ /* USER CODE END Callback 0 */ /* USER CODE BEGIN Callback 1 */ if (htim == &htim1) { osSignalSet(defaultTaskHandle, (1<<1)); } /* USER CODE END Callback 1 */ }
■割り込みハンドラが本当に割り込みの中で呼ばれているか確認する。
●割り込みハンドラにブレークをかけて、xpsrの値を調べる。
※xpsrの下位8ビットが0以外なので、割り込みハンドラであることが分かる。
※割り込みハンドラの中から、シグナルイベントを発生させている。
●シグナルイベントを受けるタスク側にブレークをかけて、xpsrの値を調べる。
※xpsrの下位8ビットが0なので、タスク(割り込みハンドラではない)ことが分かる。
※シグナルイベントを受けてLEDの点灯をトグルしている。
スクリーンショットはPDF版を見てください。
5-timer.pdf
同じことを、freeRTOSと、μITRONで行った場合の実装の違いを比較してみた。
4つのLEDを点滅させるだけのプログラムである。
基本的にはメインのタスクで、100msごとに順にトグルを繰り返しているが・・
LD6はメインのタスクから、ふたつ目のタスクへイベント(シグナル)を飛ばしてトグルさせている。
LD4は割り込みハンドラからイベント(シグナル)を飛ばして、LD6と同じふたつ目のタスクで受ける。
実装(ソースコード)はPDF版を見てください。
6-vs-tron.pdf
コメントをかく