周期ハンドラでLED点滅

uItronの機能の1つ 周期ハンドラの利用

 

定期的に実行される処理を、OS側に周期ハンドラに設定して定期実行してもらう、OS上での処理方法。

タスクの実行と休止を使い切り替える処理は、OSを使わないプログラムとはひと味違ってくる、マルチタスクらしい処理です。


正確な時間稼ぎをする(周期ハンドラ)

OSなしの タイマーAを使った
タイマーで正確な時間稼ぎをする に当たる処理をしてみます。

 

正確な時間で処理を実行する方法は μITronではいく通りもありますが、周期ハンドラを使った方法です。
ただ、3664ではタイマーAは、RTOSのシステム時間用に使用されている。

周期ハンドラは 設定した周期で、周期的に実行されるハンドラ そのままです。
ハンドラに登録したfunc関数が 設定の周期で実行される。

この関数内で LEDの点滅処理の切り替え起動させる。

 

プログラム

 

 

.c



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

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

	周期ハンドラ func()	1秒間隔

/* ------------------------------------------------------------------------ */


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

#define	SLP_TEST	1

/* メイン関数 */
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にセットし、プルアップなし*/ 

	act_tsk(TSKID_SAMPLE1);
}

unsigned char f=0;

void Task1(VP_INT exinf)
{
	for ( ; ; )
	{
   
		slp_tsk();	 // 自ら起床待ち状態に遷移する

		if( f==1 ){

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

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


void func( VP_INT exinf){

	iwup_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\"");


/* 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, 0, Initialize});
CRE_TSK(TSKID_SAMPLE1, {TA_HLNG, 1, Task1, 1, 256, NULL});

/* 周期ハンドラ */
CRE_CYC( CYC_ID, {TA_HLNG | TA_STA, 0 ,func, 1000,0} );



       

 

 

.h


        #ifndef __PROJECT_HOS__sample_h__

        #define __PROJECT_HOS__sample_h__

        void Initialize(VP_INT exinf);

        void Task1(VP_INT exinf);

        void func(VP_INT exinf);


      #endif	/* __PROJECT_HOS__sample_h__ */

 

設定時間1000が来るごとにfuncが実行されるような設定にする。

 

周期ハンドラ設定

/* 周期ハンドラ */ CRE_CYC( CYC_ID, {TA_HLNG | TA_STA, 0 ,func, 1000,0} );

 

必要なところの設定だけについて 
左から CYC_ID がIDとなる名前 、TA_HLNG | TA_STA は必要な設定、 funcが登録関数名、 1000は周期時間、0はTA_STA設定のときは周期ハンドラ生成から最初の起動までの時間 ( 詳細は P256 ITRON仕様書 周期ハンドラなど参照 )

 

周期ハンドラからよばれるfunc内で、LEDの点滅処理のタスクを起動させる。1秒ごとの周期に設定。

 

slp_tskでてきます。このサービスコールで、タスクは自分がスリープし、待ち状態(WAITTING)になる。

 

この処理では slp_tsk を使って実行中のLED点滅タスクを眠らせiwup_tskで起床し再び実行、これを繰り返すことで点滅動作をしています。

 

slp_tskで眠り wup_tsk 起床 
・slp_tsk(スリープ)  ←→   wup_tsk (起床)
・待ち状態(WAITTING)         実行状態


wup_tsk はハンドラからの場合はiwup_tskを使うようです。
仕様書にwup、iwup_tskの違いについての説明が見あたらなかったのですが、iwup_tskは非タスクコンテキスト用とのことらしい。

 

最初に イニシャライズで自動実行されると slp_tsk で眠る。
周期ハンドラで周期的にiwup_tsk が実行されると 起床してLED処理実行後、またスリープ の流れで、無限ループになっています。

実行結果

LEDのタスクは頭から実行されるたびにLEDを切り替えるので、  実行 → スリープ 起床 →実行  と起床して実行するごとにLEDが切り替わる。

 

これまで同様、1秒ごとの周期で LEDが切り替わります。

 

slp_tsk で眠らせ  wup_tsk    での実行は、

 

スリープ
↓  ↑
起床 実行

 

 この流れを繰り返すループです。

 

タスクが実行されると、ループに入りそこで、目的処理の 最初か、または最後に 必ずslp_tskが実行される。wup_tsk が実行されるとまたそこから起きて実行、目的処理を

 

実行したあとはスリープという流れは無限ループでやるのが良いようです。

slp_tskを使っていますが act_tskとext_tskでも同様のことができます


act_tskを使うと 休止→実行    ext_tsk 実行→休止 
slp_tskを使ったときと較べても 実行、待ち、休止などの状態の違いが関わってOSの難しさがでてきます。

 

実際、複数のタスクの休止、実行などにはタスクの優先順位、スケジューリングなどの処理の中身が関わってきますが、複数のタスク処理でないのでここでは簡潔です。

 

定期的に実行する処理は他にも同様のLEDの動作を割り込みハンドラを使ってもできます。

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