タイマー割込みで制御(タイマーW割り込みハンドラ)

OS機能の1つである、割り込みハンドラの利用。

 

割り込みハンドラは、OSを使わない割り込み処理と感覚的に似ているのでわかりやすい。

割り込みによるタスク処理の例

タイマー割込み

OSなしの タイマー割込みで効率的な制御(タイマーA割り込み) に当たる処理をしてみます。

タイマーの正確な時間で処理をする方法で 周期ハンドラを使いましたが、続いて割り込みハンドラを使った方法です。


タイマーWを使ってみた例。
タイマーAは、OSのシステム時間用に使用されているので使えません。

 

●μITRONでの割り込み処理

 

割り込みハンドラを使った処理

初期設定等 OSなしの場合の通常の割り込み処理と同様な感覚の扱いです。

 

割り込み処理についてはμITRONでも、通常のOSなしのタイマのレジスタ設定と同様な設定が必要。多重割り込みについてもOSなしと同様のようです。

実行の様子は周期ハンドラと同様ですが、割り込みハンドラではいったん実行されると、途中で他へのタスク切り替えはされず、最後まで処理され切り替えは終了後(遅延ディスパッチ) OSなしの割り込み処理同様、多重割り込みは可。

 

通常のタスクと違う(非タスクコンテキスト)途中切り替えしないので、スリープで眠らせる等のこれまでslp_tsk等のサービスコールはできない。非タスクコンテキスト用のiact_tskなどを使う。 先頭に”iが付いたサービスコールがこれようのようです。

実験回路

 

IOポートでLEDを光らせる と同じ

 

プログラム

 

.c



/* ------------------------------------------------------------------------
 IOポートでLEDを光らせる

	P1-4 と P1-5 が0.5秒間隔で交互に点灯
		起動ごとに点灯LEDが変わるtask1を
		周期ハンドラで1秒間隔に起動する

	割り込みハンドラ func()	0.5秒間隔
 ------------------------------------------------------------------------ */

#include "itron.h"
#include "kernel.h"
#include "kernel_id.h"
#include "h83664f.h"


/* メイン関数 */
int main()
{

  sta_hos();
  
  return 0;
}

/* 初期化ハンドラ */
void Initialize(VP_INT exinf)
{

	/* ポート初期化設定 */
	IO.PMR1.BYTE=0x00;	/* 全て0にセットし、ポート使用に設定 0000 0000*/
	IO.PCR1=0xFF;		/* 全て1にセットし、出力に設定 1111 1111 */
	IO.PUCR1.BYTE=0x00;	/* 全て0にセットし、プルアップなし*/ 

  /* Timer W (システムタイマ)初期化 */
  TW.TMRW.BIT.CTS = 0;     /* カウンタ停止 */
  TW.TCRW.BIT.CCLR = 1;    /* コンペアマッチAでTCNTをクリア */
  TW.TCRW.BIT.CKS = 3;     /* 内部クロックを8分周 */
  TW.GRA = exinf;          /* コンペアマッチAの値を代入 */

  TW.TIERW.BIT.IMIEA = 1;  /* コンペアマッチAで割込み */
  TW.TMRW.BIT.CTS = 1;     /* カウンタ動作開始 */

  act_tsk(TSKID_SAMPLE1);
}

unsigned char f=0;

/* サンプルタスク */
void Task1(VP_INT exinf)
{

		if( f==1 ){

 			IO.PDR1.BIT.B4 = 1;	//  P14--pin20
		 	IO.PDR1.BIT.B5 = 0;
			 f=0;
		}else{

			IO.PDR1.BIT.B4 = 0;
			IO.PDR1.BIT.B5 = 1;	// P15--pin21
			 f=1;
		}

}

/* タイマ用割り込みハンドラ */
void TW_TimerHandler(VP_INT exinf)
{
  static int  count;

  /* 割り込み要因クリア */
  TW.TSRW.BIT.IMFA = 0;         /* 割込み条件のクリア */

  if( ++count >= 20 )		//0.5秒間隔
  {
    count = 0;

	act_tsk( TSKID_SAMPLE1 );	/* タスクを機動 */
  }
}



       

 

 

.cfg



/* ------------------------------------------------------------------------ */
/*  Hyper Operating System V4  サンプルプログラム                           */
/*   コンフィギュレーションファイル                                         */
/*                                                                          */
/*                                  Copyright (C) 1998-2003 by Project HOS  */
/*                                  http://sourceforge.jp/projects/hos/     */
/* ------------------------------------------------------------------------ */

INCLUDE("\"sample.h\"");
INCLUDE("\"ostimer.h\"");
INCLUDE("\"h8t_sci.h\"");



/* HOS 独自の設定 */
HOS_KERNEL_HEAP(0);			/* カーネルヒープの設定(省略時 0) */
HOS_TIM_TIC(1024, 125);			/* タイムティックの設定(省略時 1/1 ) */
HOS_MAX_TPRI(8);			/* 最大優先度(省略時 16) */
HOS_MIN_INTNO(19);			/* 使用する割り込み番号の最小値(省略時 0) */
HOS_MAX_INTNO(23);			/* 使用する割り込み番号の最大値(省略時 0) */
HOS_MAX_TSKID(8);			/* 最大タスクID番号(省略時静的生成に必要なだけ) */


/* OS タイマ */
ATT_INI({TA_HLNG, 0, OsTimer_Initialize});
ATT_ISR({TA_HLNG, 0, 19, OsTimer_TimerHandler});

/* サンプルプログラム */
ATT_INI({TA_HLNG, 49999, Initialize});
CRE_TSK(TSKID_SAMPLE1, {TA_HLNG, 1, Task1, 1, 256, NULL});

/* TIMER W割り込みハンドラ */
ATT_ISR({TA_HLNG, 0, 21, TW_TimerHandler});
	//	     ↑コンペアマッチ割り込み番号
/* ------------------------------------------------------------------------ */
/*  Copyright (C) 1998-2003 by Project HOS                                  */
/* ------------------------------------------------------------------------ */


       
 

 

.h



/* ------------------------------------------------------------------------ */
/*  Hyper Operating System V4  サンプルプログラム                           */
/*                                                                          */
/*                                  Copyright (C) 1998-2002 by Project HOS  */
/*                                  http://sourceforge.jp/projects/hos/     */
/* ------------------------------------------------------------------------ */

#ifndef __PROJECT_HOS__sample_h__
#define __PROJECT_HOS__sample_h__


void Initialize(VP_INT exinf);
void Task1(VP_INT exinf);
void TW_TimerHandler(VP_INT exinf);


#endif	/* __PROJECT_HOS__sample_h__ */



       

 

プログラム内容

割り込みハンドラの方法も 先の周期ハンドラに変わり、割り込みハンドラになる程度です。

定期的に実行された周期ハンドラが割り込みハンドラに変わった程度で実際の動作は同様。

 

割り込みハンドラと周期ハンドラの違いはこの処理では実行結果は同様ですが、
OS処理では、割り込みハンドラではいったん実行されると、途中で他へのタスク切り替えはされず、最後まで処理され切り替えは終了後(遅延ディスパッチ) OSなしの割り込み処理同様、多重割り込みは可。

 

登録したfunc関数が 設定の間隔で実行される。定期的に割り込みハンドラが実行される。
この関数内で LEDの点滅処理を起動させる。

 

割り込み周期設定

設定時間が来るごとにハンドラが実行されるような設定にする。

 

func内で、LEDの点滅処理のタスクを機動させる。

 

この処理では act_tskで強制的に LEDのタスクを機動しています。
slp_tsk で眠らせ、起こして起動させる処理もできますが、前述のようにslp_tskタスクは不可

 

cfgファイル

/* TIMER W割り込みハンドラ */
ATT_ISR({TA_HLNG, 0, 21, TW_TimerHandler});
21の部分は割り込み番号 チップにより割り込みベクタの番号をここに。

 

実行結果

 

LEDが交互に点灯する 周期ハンドラでLED点滅 と同様です。

 

 

スポンサーリンク
  • facebook
  • twtter
  • google+
  • hatena