"OIL"とは、"OSEK Implementation Language"の略です。
この章では、OILファイルの記述ついて学習し、プログラムの動かし方を変えてみましょう。
1.OILファイルとオブジェクト
下に示したのは、0章で用いたサンプルプログラムのOILファイルです。
これを元に、OILファイルの解説をします。
OIL記述は、OILオブジェクト(OS,APPMODE,TASKなど)の集合で構成されています。
OILオブジェクトは、種類、名前の順で定義します。例えば、"CPU"がオブジェクトの種類、"ATMEL_AT91SAM7S256"がCPUオブジェクトの名前です。
上の例で用いているOILオブジェクトを解説します。
OILファイルのコードは実装部とアプリケーション部の大きく二つに分けられます。
OSオブジェクトは、標準的な実装仕様を示す定義を記述した実装部、APPMODE,TASKオブジェクトは、アプリケーションの構造を定義したアプリケーション部です。
実装部は、ハードウェアによって決まるので、NXTを扱う以上、コードは変わりません。
アプリケーション部のTASKオブジェクトの記述を変えることによって、プログラムの実行の仕方を変えることができます。
TASKオブジェクト内の記述を次のように変えてみてください。
NXTにプログラムを転送し、実行してみると、画面にはなにも表示されません。
これは、NXTOSEKが起動したものの、タスクが何も実行されていないからです。
"AUTOSTART"とは、プログラムを実行したときに、自動的にタスクを実行させる機能です。
これを"FALSE"すなわち偽にしたことで、タスクが実行されず、なにも動作しなかった訳です。
TASKオブジェクト内の記述について、下に詳しく記します。
TASKオブジェクトの記述は、タスクが複数あるプログラムの場合、大変重要になります。
これは、実践編:マルチタスクにて解説します。
これを元に、OILファイルの解説をします。
test.oil
#include "implementation.oil" CPU ATMEL_AT91SAM7S256 { OS LEJOS_OSEK { STATUS = EXTENDED; STARTUPHOOK = FALSE; SHUTDOWNHOOK = FALSE; PRETASKHOOK = FALSE; POSTTASKHOOK = FALSE; USEGETSERVICEID = FALSE; USEPARAMETERACCESS = FALSE; USERESSCHEDULER = FALSE; }; /* Definition of application mode */ APPMODE appmode1{}; TASK Task1 /* Task1 を定義する */ { AUTOSTART = TRUE { APPMODE = appmode1; }; PRIORITY = 1; ACTIVATION = 1; SCHEDULE = FULL; STACKSIZE = 512; }; }; |
OIL記述は、OILオブジェクト(OS,APPMODE,TASKなど)の集合で構成されています。
OILオブジェクトは、種類、名前の順で定義します。例えば、"CPU"がオブジェクトの種類、"ATMEL_AT91SAM7S256"がCPUオブジェクトの名前です。
上の例で用いているOILオブジェクトを解説します。
オブジェクト名 | 説明 |
CPU | CPUはすべてのオブジェクトのコンテナとして使われます。 |
OS | OSプロパティを定義するのに使用されるオブジェクトです。 |
APPMODE | アプリケーションモードを定義します。一つ以上のアプリケーションモードが必要です。 |
TASK | タスクの実行の仕方を指定するオブジェクトです。 |
OILファイルのコードは実装部とアプリケーション部の大きく二つに分けられます。
OSオブジェクトは、標準的な実装仕様を示す定義を記述した実装部、APPMODE,TASKオブジェクトは、アプリケーションの構造を定義したアプリケーション部です。
実装部は、ハードウェアによって決まるので、NXTを扱う以上、コードは変わりません。
アプリケーション部のTASKオブジェクトの記述を変えることによって、プログラムの実行の仕方を変えることができます。
TASKオブジェクト内の記述を次のように変えてみてください。
TASK Task1
{
AUTOSTART = FALSE;
PRIORITY = 1;
ACTIVATION = 1;
SCHEDULE = FULL;
STACKSIZE = 512;
};
};
|
NXTにプログラムを転送し、実行してみると、画面にはなにも表示されません。
これは、NXTOSEKが起動したものの、タスクが何も実行されていないからです。
"AUTOSTART"とは、プログラムを実行したときに、自動的にタスクを実行させる機能です。
これを"FALSE"すなわち偽にしたことで、タスクが実行されず、なにも動作しなかった訳です。
TASKオブジェクト内の記述について、下に詳しく記します。
TASK Task1{}
"Task1"という名前のタスクを定義します。
AUTOSTART = FALSE
プログラム実行時に、タスクを自動起動するかを指定します。
TRUEとする場合、続けて{}内にアプリケーションモードを指定します。
例:AUTOSTART = TRUE { APPMODE = appmode1; };
TRUEとする場合、続けて{}内にアプリケーションモードを指定します。
例:AUTOSTART = TRUE { APPMODE = appmode1; };
PRIORITY = 1
タスク優先度を指定します。
タスクが複数あるプログラムの場合、優先度が高いプログラムが優先して実行されます。
数字が大きいほど優先度が高く、範囲は1〜16までです。
タスクが複数あるプログラムの場合、優先度が高いプログラムが優先して実行されます。
数字が大きいほど優先度が高く、範囲は1〜16までです。
ACTIVATION = 1
多重起動の最大数を指定します。
"1"は多重起動なしの設定です。また、拡張タスクは多重起動できません。
"1"は多重起動なしの設定です。また、拡張タスクは多重起動できません。
SCHEDULE = FULL;
ノンプリエンプティブ"NON"もしくはフルプリエンプティブ"FULL"を設定します。
ノンプリエンプティブは、現在実行しているタスクが優先される方式です。
フルプリエンプティブは、優先度の高いタスクが優先される方式です。。
ノンプリエンプティブは、現在実行しているタスクが優先される方式です。
フルプリエンプティブは、優先度の高いタスクが優先される方式です。。
STACKSIZE = 512;
スタックのサイズを指定します。
TASKオブジェクトの記述は、タスクが複数あるプログラムの場合、大変重要になります。
これは、実践編:マルチタスクにて解説します。
2.カウンタとアラーム
アプリケーション部には、APPMODEやTASKのほかにも、オブジェクトを記述することが出来ます。
今回は、COUNTERオブジェクトと、ALARMオブジェクトを紹介します。
次のプログラムを実行してください。
プログラムでは、変数iを繰り返しインクリメントし、表示させています。
しかし、ソースコードにはwhile文やfor文などのループ処理は記述されていません。
また、systick_waitを記述していないにもかかわらず、iの値はゆっくりと増えていきます。
この動作は、カウンタとアラームを用いることにより、実現されています。
OILファイルを見ると、COUNTERオブジェクトと、ALARMオブジェクトが追加されています。
COUNTERオブジェクトは、プログラム実行時間をカウントするオブジェクトです。
ALARMオブジェクトは、カウンタに貼り付けて用い、様々な動作をさせることが出来るオブジェクトです。
COUNTERオブジェクトと、ALARMオブジェクト内の記述について詳しく説明します。
・ COUNTER
・ ALARM
今回は、COUNTERオブジェクトと、ALARMオブジェクトを紹介します。
次のプログラムを実行してください。
alarm_test.c
#include "kernel.h" #include "kernel_id.h" #include "ecrobot_interface.h" DeclareCounter(SysTimerCnt); /* SysTimerCntを宣言 */ DeclareTask(Task1); /* Task1を宣言 */ void ecrobot_device_initialize(){} /* OSEK起動時の処理(何もしない)*/ void ecrobot_device_terminate(){} /* OSEK終了時の処理(何もしない)*/ void user_1ms_isr_type2(void) /* タイマ割り込み用フック関数 */ { SignalCounter(SysTimerCnt); /* カウンタをIncrementする */ } TASK(Task1) { static int i=0; /* 変数iを定義と初期化 */ display_clear(0); display_goto_xy(0,1); display_string("I="); /* 変数の内容を表示 */ display_int(i, 5); display_update(); i++; /* iをインクリメントする */ TerminateTask(); /* 処理終了 */ } |
alarm_test.oil
#include "implementation.oil" CPU ATMEL_AT91SAM7S256 { OS LEJOS_OSEK { STATUS = EXTENDED; STARTUPHOOK = FALSE; SHUTDOWNHOOK = FALSE; PRETASKHOOK = FALSE; POSTTASKHOOK = FALSE; USEGETSERVICEID = FALSE; USEPARAMETERACCESS = FALSE; USERESSCHEDULER = FALSE; }; APPMODE appmode1{}; /* アプリケーションモードを定義 */ TASK Task1 /* Task1 を定義 */ { AUTOSTART = FALSE; PRIORITY = 1; ACTIVATION = 1; SCHEDULE = FULL; STACKSIZE = 512; }; COUNTER SysTimerCnt /* SysTimerCntを定義 */ { MAXALLOWEDVALUE = 10000; TICKSPERBASE = 1; /* 1ティックは 1msec */ MINCYCLE = 1; }; ALARM cyclic_alarm1 /* 周期起動アラームを定義 */ { COUNTER = SysTimerCnt; ACTION = ACTIVATETASK { TASK = Task1; }; AUTOSTART = TRUE { ALARMTIME = 1; CYCLETIME = 1000; /* Task1は1秒ごとに起動 */ APPMODE = appmode1; }; }; }; |
プログラムでは、変数iを繰り返しインクリメントし、表示させています。
しかし、ソースコードにはwhile文やfor文などのループ処理は記述されていません。
また、systick_waitを記述していないにもかかわらず、iの値はゆっくりと増えていきます。
この動作は、カウンタとアラームを用いることにより、実現されています。
OILファイルを見ると、COUNTERオブジェクトと、ALARMオブジェクトが追加されています。
COUNTERオブジェクトは、プログラム実行時間をカウントするオブジェクトです。
ALARMオブジェクトは、カウンタに貼り付けて用い、様々な動作をさせることが出来るオブジェクトです。
COUNTERオブジェクトと、ALARMオブジェクト内の記述について詳しく説明します。
・ COUNTER
MAXALLOWEDVALUE = 10000;
カウンタの最大値を指定します。"0"を指定することは出来ません。
TICKSPERBASE = 1;
カウンタが1単位に達するまでのティックを指定します。
"1"を指定した場合、1ティック毎に一つカウントアップします。
※ティックとは、NXTOSEKの場合、1ms毎に1づつ増えていく数値です。
"1"を指定した場合、1ティック毎に一つカウントアップします。
※ティックとは、NXTOSEKの場合、1ms毎に1づつ増えていく数値です。
MINCYCLE = 1;
周期としての最小単位を指定します。
TICKSPERBASEより大きく、MAXALLOWEDVALUE以下の値を指定します。
TICKSPERBASEより大きく、MAXALLOWEDVALUE以下の値を指定します。
・ ALARM
COUNTER = SysTimerCnt;
貼り付けるカウンタを指定します。
ACTION = ACTIVATETASK{ … }
カウンタがexpire、すなわち満期になった際の動作を指定します。
今回は、ACTIVATETASK、すなわちタスクを起動する動作を指定しています。
{}内に、起動したいタスク名を指定します。
動作の種類には他に、SETEVENT、ALARMCALLBACKなどがあります。
詳しくは、「TOPPERS_OSEKカーネルSG取扱説書」の「6.7.4. ALARMオブジェクト」を参照してください。
「TOPPERS_OSEKカーネルSG取扱説書」は、nxtOSEK\toppers_osek\docにあります。
今回は、ACTIVATETASK、すなわちタスクを起動する動作を指定しています。
{}内に、起動したいタスク名を指定します。
動作の種類には他に、SETEVENT、ALARMCALLBACKなどがあります。
詳しくは、「TOPPERS_OSEKカーネルSG取扱説書」の「6.7.4. ALARMオブジェクト」を参照してください。
「TOPPERS_OSEKカーネルSG取扱説書」は、nxtOSEK\toppers_osek\docにあります。
TASK = Task1;
上のACTIVATETASKの{}内において、タスクを指定するときに使う記述です。
今回は、アラームによってTASK1を起動します。
今回は、アラームによってTASK1を起動します。
AUTOSTART = TRUE{ … }
プログラム起動時にアラームを自動的に起動させるかを指定します。
させる場合は"TRUE"とします。{}内にサブ属性を記載します。
させる場合は"TRUE"とします。{}内にサブ属性を記載します。
ALARMTIME = 1;
最初にアラームをexpireさせる値です。
0以上、MAXALLOWEDVALUE以下の値を指定します。
"1"とした場合、プログラム開始直後にカウンタがexpireします。
0以上、MAXALLOWEDVALUE以下の値を指定します。
"1"とした場合、プログラム開始直後にカウンタがexpireします。
CYCLETIME = 1000;
アラームをexpireさせる周期を指定します。
MAXALLOWEDVALUE以下の値を指定します。
上のプログラムの場合、1秒毎にTASK1が起動されます。
MAXALLOWEDVALUE以下の値を指定します。
上のプログラムの場合、1秒毎にTASK1が起動されます。
APPMODE = appmode1;
タスクを起動させる際のアプリケーションモードを指定します。
APPMODEオブジェクトで定義したアプリケーションモードを指定します。
APPMODEオブジェクトで定義したアプリケーションモードを指定します。
3.課題
1.サンプルプログラムをNXTにダウンロードし、動作を確認せよ。
2.サンプルプログラムを応用し、タッチセンサでスタート・ストップするストップウォッチを作成せよ。ストップウォッチの時間分解能は10msecとする。
2.サンプルプログラムを応用し、タッチセンサでスタート・ストップするストップウォッチを作成せよ。ストップウォッチの時間分解能は10msecとする。