タスク間の排他制御

 

マルチタスク実行環境における複数タスク間で、共通のリソース(例, グローバル変数、周辺レジスタ)に同時アクセスする際に生じるグローバル変数の意図しない上書きや周辺レジスタの占有等の問題に対して、nxtOSEKではOSEK Resourceを使用した共有リソースの排他制御機能を提供しています。
samples\resourcetestディレクトリに格納されたresourcetestサンプルプログラムでは、OSEKのGetResource/ReleaseResource APIを使用して、2つのタスク間での液晶表示に対する排他制御およびイベント同期処理が実装されています。優先度が低いタスクにおいて下図のように液晶表示処理前にGet Resource APIをコールすることで、優先度の高いタスクの実行を遅延させています。OSEKのResource APIでは排他制御を実現するために、Priority Ceiling Protocolと呼ばれる一時的な優先度変更処理を施しています。

samples\resourcetest\resourcetest.c

/* resourcetest.c */
#include "kernel.h"
#include "kernel_id.h"
#include "ecrobot_interface.h"

/* OSEK declarations */
DeclareCounter( SysTimerCnt );
DeclareResource(resource1);
DeclareEvent(event1);
DeclareTask(LowTask);
DeclareTask(HighTask);

/* nxtOSEK hook to be invoked from an ISR in category 2 */
void user_1ms_isr_type2(void)
{
  StatusType ercd;

  ercd = SignalCounter(SysTimerCnt); /* Increment OSEK Alarm Counter */
  if (ercd != E_OK)
  {
    ShutdownOS(ercd);
  }
}

/* Definitions */
#define COUNT 5000000
int digits;
int lowtaskcount;
int hightaskcount;

TASK(LowTask)
{
  int rcount;

  ecrobot_debug1(digits, 1111, 0);
  for(rcount = 0; rcount < COUNT; rcount++);
  ecrobot_debug1(digits, 1119, 0);

  GetResource(resource1); /* Get resource1 */

  for(rcount = 0; rcount < COUNT; rcount++) digits++;
  SetEvent(HighTask, event1); /* Set event1 to execute HighTask */

  ecrobot_debug1(digits, 1199, 0);
  for(rcount=0; rcount < COUNT; rcount++) digits--;

  ReleaseResource(resource1); /* Release resource1 */

  ecrobot_debug1(digits, 1999, 0);

  TerminateTask();
}

TASK(HighTask)
{
  int rcount;

  ecrobot_debug2(digits, 2222, 1);
  for(rcount=0; rcount < COUNT; rcount++) digits++;
  ecrobot_debug2(digits, 2228, 1);
  for(rcount=0; rcount < COUNT; rcount++) digits++;

  WaitEvent(event1); /* Waiting for event1 */
  ClearEvent(event1);
  ecrobot_debug2(digits, 2288, 1);
  for(rcount=0; rcount < COUNT; rcount++) digits++;

  GetResource(resource1); /* Get resource1 */

  ecrobot_debug2(digits, 2888, 1);
  for(rcount = 0; rcount < COUNT; rcount++);

  ReleaseResource(resource1); /* Release resource1 */

  ecrobot_debug2(digits,8888 , 1);

  TerminateTask();
}

samples\resourcetest\resourcetest.oil

#include "implementation.oil"

CPU ATMEL_AT91SAM7S256
{
  OS LEJOS_OSEK
  {
    STATUS = EXTENDED;
    STARTUPHOOK = TRUE;
    ERRORHOOK = FALSE;
    SHUTDOWNHOOK = FALSE;
    PRETASKHOOK = FALSE;
    POSTTASKHOOK = FALSE;
    USEGETSERVICEID = FALSE;
    USEPARAMETERACCESS = FALSE;
    USERESSCHEDULER = FALSE;
  };

  /* Definition of application mode */
  APPMODE appmode1{};

  /* Definition of resource */
  RESOURCE resource1
  {
    RESOURCEPROPERTY = STANDARD;
  };

  /* Definition of event */
  EVENT event1
  {
    MASK = AUTO;
  };

  /* Definition of HighTask */
  TASK HighTask
  {
    AUTOSTART = FALSE;
    SCHEDULE = FULL;
    PRIORITY = 3;
    ACTIVATION = 1;
    SCHEDULE = FULL;
    RESOURCE = resource1;
    EVENT = event1;
    STACKSIZE = 512;
  };

  /* Definition of LowTask */
  TASK LowTask
  {
    AUTOSTART = FALSE;
    PRIORITY = 2;
    ACTIVATION = 1;
    SCHEDULE = FULL;
    RESOURCE = resource1;
    STACKSIZE = 512;
  };

  /* Definition of OSEK Alarm Counter */
  COUNTER SysTimerCnt
  {
    MINCYCLE = 1;
    MAXALLOWEDVALUE = 100000;
    TICKSPERBASE = 1;
  };

  ALARM cyclic_alarm1
  {
    COUNTER = SysTimerCnt;
    ACTION = ACTIVATETASK
    {
      TASK = HighTask;
    };
    AUTOSTART = TRUE
    {
      ALARMTIME = 3000;
      CYCLETIME = 10000;
      APPMODE = appmode1;
    };
  };

  ALARM cyclic_alarm2
  {
    COUNTER = SysTimerCnt;
    ACTION = ACTIVATETASK
    {
      TASK = LowTask;
    };
    AUTOSTART = TRUE
    {
      ALARMTIME = 3000;
      CYCLETIME = 10000;
      APPMODE = appmode1;
    };
  };
};

 

 

 

Back to Samples