ここでは、マルチタスクについて学習します。
まず、タスクとはOSから見た処理の実行単位のことです。これまでのプログラムではタスクを意識することがなかったと思います。
なぜなら、これまでは一つのタスク内の処理を順に実行するだけのシングルタスクのプログラムしか組んでいなかったからです。
しかしシングルタスクでは、複数の処理を同時に(並行して)実行させることはできません。 そのためには複数のタスクを切り替えながら処理するマルチタスクを用いる必要があります。
ここでは、マルチタスクの概念とマルチタスクを扱うプログラミングについて学習します。
1.複数タスクのプログラム
まずは、タスクが2つあるプログラムを組んでみましょう。
次のプログラムを作成してください。ここでは tasks.c , tasks.oilとします。
次のプログラムを作成してください。ここでは tasks.c , tasks.oilとします。
tasks.c
#include "kernel.h" #include "kernel_id.h" #include "ecrobot_interface.h" #define COUNT 500 /* カウント数を500に定義 */ DeclareTask(Task1); /* Task1を宣言 */ DeclareTask(Task2); /* Task2を宣言 */ void ecrobot_device_initialize(){} void ecrobot_device_terminate(){} void user_1ms_isr_type2(void){} TASK(Task1) { int i; for(i=0 ; i<=COUNT ; i++){ display_goto_xy(0,1); display_string("TASK1 = "); display_goto_xy(8,1); display_int(i, 5); display_update(); systick_wait_ms(10); } TerminateTask(); /* 処理終了 */ } TASK(Task2) { int j; for(j=0 ; j<=COUNT ; j++){ display_goto_xy(0,2); display_string("TASK2 = "); display_goto_xy(8,2); display_int(j, 5); display_update(); systick_wait_ms(20); } TerminateTask(); /* 処理終了 */ } |
tasks.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 = TRUE { APPMODE = appmode1; }; PRIORITY = 1; ACTIVATION = 1; SCHEDULE = FULL; STACKSIZE = 512; }; TASK Task2 /* Task2 を定義 */ { AUTOSTART = TRUE { APPMODE = appmode1; }; PRIORITY = 2; ACTIVATION = 1; SCHEDULE = FULL; STACKSIZE = 512; }; }; |
このプログラムを動かすとLCDを見れば分かるように、まずTask2が500までインクリメントします。 次に、Task1が500までインクリメントして処理が終了します。
タスクの起動される順番は、タスクの優先度によって決まります。このプログラムでは、Task1の優先度は1、Task2の優先度は2になっています。
優先度は値が大きいほど高いので、Task2の方が優先度が高く、Task2が先に起動されたのです。
※2つのタスクの優先度が同じだった場合、先に起動されたタスクが処理されます。
しかし、これでは、同時に処理をしているとはいえません。優先度を同じにしても、先に宣言されていたタスクが先に処理されるので、同時には処理されません。
普通の処理系では、同じ優先度のタスクはラウンドロビンという方式により、ほぼ同時に処理されますが、nxtOSEKにはその仕組みがありません。
つぎは、どうしたらタスクが同時に処理されるかを考えて見ましょう。
※ラウンドロビン…タスクをを一定時間ずつ順番に実行する方式。持ち時間を使い果たしたタスクは一旦中断され、待ち行列の最後に回される。