2020年度の第10回TOOPERS活用アイデア・アプリケーション開発コンテストのアプリケーション開発部門で金賞を受賞した「TOPPERS/ASPのタスク遷移表示システム」で使用したタイマー割込みを部分を抜き出して実装方法などを紹介します。
STM32FボードでのTOPPERS/ASPと割り込み処理作成の参考になると思い記事にしてみました。
・TOPPERS活用アイデア・アプリケーション開発コンテスト
https://www.toppers.jp/contest.html
##TOPPERS/ASPとは
TOPPERS/ASPは、TOPPERSプロジェクト(TOPPERS:Toyohashi OPen Platform for Embedded Real-time Systems)が管理、公開しているITRON仕様のRTOSの1つです。
TOPPERS新世代カーネルとしてワンチップマイコンで動かすことができるRTOSです。
TOPPERSやTOPPERSプロジェクト、TOPPERS/ASPの詳細は以下のページを参照してください。
・TOPPERSのページ
https://www.toppers.jp/
・TOPPERSプロジェクトのページ
https://www.toppers.jp/project.html
・TOPPERS/ASPカーネルのページ
https://www.toppers.jp/asp-kernel.html
##タイマー処理の作成
###デバイスの初期化
STM32F446-Nucleoでタイマーを使うには、以下の処理が必要になります。
・タイマーのクロックを有効化
・タイマー機能の設定
・タイマー割り込み発生時間の設定
・タイマー割り込みクリア処理
###タイマーのクロックを有効化
今回、タイマーとして STM32F446の General-purpose timers TIM2を使い周期的に割り込みを発生させます。
このため STM32F446の RCC_APB1ENRレジスタの ビット0:TIM2ENへ「1」をセットするとこで、タイマー TIM2へクロックを供給し、利用できるようにします。
/* set clock enable */
RCC->APB1ENR |= ( RCC_APB1ENR_TIM2EN
) ;
###タイマー機能の設定
タイマーのコントロールレジスタなどを設定し、周期的にタイマー割り込みが発生するにします。
手順としては以下になります。
・タイマーカウント停止
・タイマーコントロールレジスタ設定
・クロック分周設定 TIM_CR1_CKD_1 : 4分周
・オートリロード設定有効
・タイマーカウンタディレクション Counter used as downcounter
・割り込み発生条件 アンダーフロー
・割り込みイネーブルレジスタ設定
・タイマープリスケーラー設定
・タイマー割り込み発生時間の設定
・タイマー割り込みのクリア
・タイマー割り込みフラグのクリア
・タイマーカウントの開始
/* counter disable */
TIM2->CR1 &= ~TIM_CR1_CEN;
/* clk/4, Auto-reload preload enable, downcounter, Update request source */
TIM2->CR1 = TIM_CR1_CKD_1 | TIM_CR1_ARPE | TIM_CR1_DIR | TIM_CR1_URS;
TIM2->DIER = TIM_DIER_UIE;
TIM2->EGR = TIM_EGR_UG;
「タイマー割り込み発生時間(間隔)の設定”」
TIM2->SR &= ~TIM_SR_UIF;
TIM2->SR &= ~(TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF | TIM_SR_CC4IF);
TIM2->CR1 |= TIM_CR1_CEN; /* counter enable */
###タイマー割り込み発生時間の設定
タイマー割り込みの発生時間を設定するため、プリスケーラーやカウンタレジスタにの設定を行います。
・プリスケーラーレジスタの設定
インターナルクロックを分周します。
カウンタレジスタによる遅延が1~65536に収まるようクロックを分周します。
・オートリロードレジスタの設定
タイマートリガ発生後にタイマーカウンタへリロードする値を設定します。
・カウンターレジスタの設定
1発目のタイマー割り込みを発生させるまでのカウンタ値を設定します。
オートロードの場合、2回目以降はオートリロードレジスタの値が用いられます。
TIM2->PSC = 10-1;
/* 45000/9000000 = 1/200 -> 5msec */
/* 9000/9000000 = 1/1000 -> 1msec */
/* 900/9000000 = 1/10000 -> 100usec */
TIM2->ARR = 900;
TIM2->CNT = 900;
###タイマー割り込みクリア処理
タイマー割り込み発生後、割り込みフラグをクリアする処理を実行します。
割り込みのクリアはステータスレジスタのUIFビットを「0」にすることで行えます。
TIM2->SR &= ~TIM_SR_UIF;
##TOPPERS/ASPへの割り込みの登録
RTOSだけでなく Linuxなどの一般的な OS においても割り込みは OSの管理下にあります。
TOPPERS/ASPも当然ですが、割り込みの管理を行っています。
このため、割り込みを用いる場合には前述のハードウェアの設定だけでなく、OS側にもどの割り込みを使い、割り込み発生時のハンドラの登録などを行う必要があります。
TOPPERS/ASPでタイマー割り込みを使えるようにするため、以下の設定や処理の追加を行います。
・タイマー初期化処理の追加
・タイマー割り込みハンドラの追加
・アプリケーションコンフィグレーションの設定
###タイマー初期化処理の追加
前述の「タイマー処理の作成」のうち、「デバイスの初期化」「タイマー機能の設定」「タイマー割り込み発生時間の設定」の呼び出し処理です。
また、タイマー初期化後、TOPPERS/ASPに対してタイマー割り込みの許可を指示します。
STM32F446-Nucleoの TIM2の場合、ベクタ番号が「28」ですが、TOPPERS/ASP内では Cortex-M4 内部割込みの「16」ベクタを加えた「44 (28+16)」割り込み番号として指定します。
er = ena_int( 44 );
###タイマー割り込みハンドラの追加
タイマー割り込み発生時に呼び出される処理です。
タイマー割り込み発生ごとに毎回呼び出される関数で、ユーザが任意の処理を作成することが可能です。
ただし、割り込み中の処理なので、短時間で処理を終える必要があります。
また、割り込み処理中にはイベント待ちになるようなTOPPERS/ASPのAPIの実行は禁止されていています。
最後に割り込み処理終了後にタスクへ処理が戻った後に再び割り込みを認識しないよう、処理の最後にタイマー割り込みのクリア処理を実行します。
###アプリケーションコンフィグレーションの設定
TOPPERS/ASPに対してタイマー割り込み関連処理の登録や設定を行うため、アプリケーションコンフィグレーションの設定を行います。
TOPPERS/ASPのサンプルプログラムの場合、sample1.cfg への設定の追加になります。
初期化ルーチンの追加(ATT_INI)
第3引数にタイマー初期化処理の先頭アドレス(関数名)を指定します。
・割込みサービスルーチンの追加(ATT_ISR)
第2引数に割り込み番号、第3引数にタイマー割り込みハンドラの先頭アドレス(関数名)を指定します。
・CFG_INT 割込み要求ラインの属性の設定(CFG_INT)
第1引数に割り込み番号を指定します。
ATT_INI({ TA_NULL, 0, main_timer_init });
ATT_ISR({ TA_NULL, 0, 44, main_timer_handler, 1 });
CFG_INT(44, { TA_EDGE, -4 });
##最後に
TOPPERS/ASPを使えばミリ秒単位の繰り返しや待ちを行うことができますが、μ秒単位の時間が必要な場合などタイマーを使った処理や割り込みが必要になります。
また、今回はタイマー割り込みの登録方法を記しましたが、割り込み番号を変更することで他のデバイスの割り込みをアプリケーションで受け取り、処理することができるようになり、プログラムや製作物の幅が広がると思います。
今回使用したプログラムやSTM32F446の定義ファイルなどは以下に含まれています。実際にプログラムを試す場合に利用できると思います。
- 以上 -