ITRON入門 静的APIとコンフィギュレーションファイル

ITRON入門カリキュラム
この記事は約24分で読めます。

こんにちは、ナナです。

ITRONではサービスコール以外に静的APIと呼ばれる特殊なサービスコールが用意されています。ITRONのシステムを構築する際には静的APIを使いこなせる必要があります。

本記事では次の疑問点を解消する内容となっています。

本記事で学習できること
  • 静的APIとは何なのか?
  • コンフィギュレーションファイルの役割とは?
  • 「kernel_cfg.c」と「kernel_id.h」には何が書かれているのか?
  • HOS独自の静的APIとはどのようなものがあるのか?

では、順に解説していきます。

スポンサー

ITRONで定義される静的APIとコンフィギュレーションファイル

ITRON仕様において次のように定義されています。

ITRON仕様による静的APIの定義

2.1.2 APIの構成要素

(C)静的API

システムコンフィギュレーションファイル中に記述し、カーネルやソフトウェア部品の構成を決定したり、オブジェクトの初期状態を定義するためのインターフェースを静的APIと呼ぶ。

システムコンフィギュレーションファイルという用語が出てきました。静的APIと関連性の強い用語です。次のように定義されています。

ITRON仕様によるコンフィギュレーションファイルの定義

2.1.10 システムコンフィギュレーションファイル

カーネルやソフトウェア部品の構成やオブジェクトの初期状態を定義するためのファイルをシステムコンフィギュレーションファイルと呼ぶ。

システムコンフィギュレーションファイルにはカーネルやソフトウェア部品の静的APIとITRON仕様共通静的APIに加え、C言語処理系のプリプロセッサディレクティブを記述することができる。

システムコンフィギュレーションファイル中の静的APIを解釈してカーネルやソフトウェア部品を構成するためのツールをコンフィギュレータと呼ぶ。

様々な専門用語が出てきて戸惑うかもしれません。順に解説していきましょう。本記事を見終わった後に再度読めば理解できるはずです。

スポンサー

ITRONにおける静的APIの役割

ITRONを搭載したシステムではオブジェクトというものを利用してプログラミングをしていきます。オブジェクトには「タスク」「イベントフラグ」といったものが存在します。

これらオブジェクトをプログラム実行時に作り出すことは可能なのですが、ITRONではプログラム実行前の段階にて生成定義を行うことが可能です。その仕組みこそが静的APIです。

静的APIの種類

ITRONで定義されている静的APIには次のものがあります。静的APIは全て大文字で定義されているのが特徴です。

タスク管理機能

CRE_TSKタスクの生成

タスク例外処理機能

DEF_TEXタスク例外処理ルーチンの定義

同期・通信機能

CRE_SEMセマフォの生成
CRE_FLGイベントフラグの生成
CRE_DTQデータキューの生成
CRE_MBXメールボックスの生成

拡張同期・通信機能

CRE_MTXミューテックスの生成
CRE_MBFメッセージバッファの生成
CRE_PORランデブの生成

メモリプール管理機能

CRE_MPF固定長メモリプールの生成
CRE_MPL可変長メモリプールの生成

時間管理機能

CRE_CYC周期ハンドラの生成
CRE_ALMアラームハンドラの生成
DEF_OVRオーバーランハンドラの生成

割込み管理機能

DEF_INH割込みハンドラの定義
ATT_ISR割込みサービスルーチンの追加

サービスコール管理機能

DEF_SVC拡張サービスコールの定義

システム構成管理機能

DEF_EXCCPU例外ハンドラの定義
ATT_INI初期化ルーチンの追加

よく見ると多くの静的APIはCREという文字で始まるものがほとんどですね。CREはCreateの略ですが、オブジェクトの生成に関するものが静的APIとして定義されています。

このように静的APIはオブジェクトを事前生成するためのサービスコールなのです。

スポンサー

コンフィギュレーションファイルの役割

静的APIを使うことで事前に「タスク」や「イベントフラグ」といったオブジェクトを生成できるといっても一体どのように使えばよいのかわかりませんね。

静的APIの記述は皆さんがプログラムを書くソースファイルやヘッダファイルに記述するわけではありません。

静的APIの記述はコンフィギュレーションファイルと呼ばれるsystem.cfgファイルに記述するのがITRONのルールです。

コンフィギュレーションファイルの書き方

実はすでにビュートローバーのプロジェクトにはコンフィギュレーションファイルが用意されています。次のファイルを開いてみてください。

C:\WorkSpace\BeautoRoverRTOS\BeautoRover\system.cfg

system.cfg

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

INCLUDE("\"main.h\"");
INCLUDE("\"ostimer.h\"");

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


//------------------------------------------------
//  初期化
//------------------------------------------------
ATT_INI({TA_HLNG, 0, Main_init});
ATT_INI({TA_HLNG, 0, Ostimer_init});

//------------------------------------------------
//  割り込み
//------------------------------------------------
ATT_ISR({TA_HLNG, 0, 29, Ostimer_interruptHandler});

//------------------------------------------------
//  タスク定義
//------------------------------------------------
CRE_TSK(TSKID_MAIN, {TA_HLNG|TA_ACT, 0, MAIN, 1, 128, NULL});

/* ------------------------------------------------------------------------ */
/*  Copyright (C) 1998-2006 by Project HOS                                  */
/* ------------------------------------------------------------------------ */

本来このファイルはシステムを作る皆さんが適切に記述して用意する必要があります。

自分が作りたいシステムにおいて「タスク」や「イベントフラグ」といったオブジェクトをいくつ利用するかという設計をした上でこのファイルにその意思を表明するのです。

system.cfgの検討

その記述方法こそが静的APIで決められており、そのルールに従って記述するのです。

コンフィギュレーションファイルから生み出されるもの

コンフィギュレーションファイルは最終的に「kernel_cfg.c」「kernel_id.h」という2つのファイルを生成することが目的です。

ITRON仕様書にも生成手順が明記されています。「2.1.10 システムコンフィギュレーションファイル」の図2.1を参照してみてください。

複雑な図に見えますが、今回のシステムにおいて簡略表記すると次の工程にて作成しています。

コンフィギュレーション手順

実はすでに皆さんのビュートローバー環境ではこの工程を実施するように設定が行われています。ポーティング作業の中で登場した「ビルドフェーズの登録」の設定がそれです。

忘れてしまった人はもう一度見てみるとよいでしょう。このビルドフェーズで設定したものは「ビルド」コマンドを実行した時に行われるようになっています。

ビルドフェーズ:preconfigの実際のコマンド内容

ch38.exe system.cfg -cpu=300HN -prep=system.pre

ch38.exeはHEW環境のH8マイコン用コンパイラです。-prepはプリプロセス処理のみを実施するオプション指定になっています。sysytem.cfgが入力ファイルでsystem.preが出力ファイルです。

ビルドフェーズ:configの実際のコマンド内容

hos4cfg.exe system.pre

hos4cfg.exeがHOS環境におけるコンフィギュレータツールの実行ファイルです。入力すべきファイルであるsystem.preファイルを指定しています。

このツールの実行により「kernel_cfg.c」「kernel_id.h」が自動生成されることになります。

HOSのコンフィギュレータツールはHOSを解凍した先の下記に元から含まれている!

コンフィギュレータ: C:\WorkSpace\BeautoRoverRTOS\hos\config\hos4cfg.exe

コンフィギュレータツールは各製品により個別のものが提供される。それはコンフィギュレーションファイルが一部製品依存の記述が含まれるためである!

スポンサー

コンフィギュレータが作るkernel_cfg.cとkernel_id.hの役割

システムコンフィギュレーションファイルからコンフィギュレータが出力したこの2つのファイルが何なのかを知っておきましょう。

ITRONカーネルの不足情報

ITRONカーネルのプログラム(hosライブラリ)にはサービスコールの実体となる関数やカーネルが管理する外部変数などが含まれています。

しかし、システムを作りたい皆さんが決めるべきITRONに関するパラメータ要素はこの中に含めることなどできるわけがありません。

例えば次のようなオブジェクトに対する要求はシステムを作る側次第で変化します。

  • タスクを3個
  • イベントフラグを2個

このようなシステム構築者側のITRON要素を「kernel_cfg.c」「kernel_id.h」という形でITRONカーネルは取り込みます。

kernelファイルの位置づけ

kernel_cfg.cとkernel_id.hの中身の確認

具体的にどのような情報が入っているのかを見てみましょう。もちろん、入力されるコンフィギュレーションファイル次第で中身は変化しますよ。

kernel_id.h

/* ------------------------------------------------------------------------ */
/*  HOS-V4  kernel configuration                                            */
/*    kernel object ID definition                                           */
/*                                                                          */
/* ------------------------------------------------------------------------ */


#ifndef __HOS_V4__kernel_cfg_h__
#define __HOS_V4__kernel_cfg_h__



/* time tic */
#define TIC_NUME        1
#define TIC_DENO        1


/* task ID definetion */
#define TSKID_MAIN      1

#define TMAX_TSKID      8



#endif  /* __HOS_V4__kernel_cfg_h__ */


/* ------------------------------------------------------------------------ */
/*  End of file                                                             */
/* ------------------------------------------------------------------------ */

ヘッダファイルにはいくつかのマクロ定義が含まれていますね。system.cfgと照らし合わせるとこれらの情報の元が何の静的APIによるものなのかがわかります。

kernel_cfg.c

/* ------------------------------------------------------------------------ */
/*  HOS-V4  kernel configuration                                            */
/*    kernel object create and initialize                                   */
/*                                                                          */
/* ------------------------------------------------------------------------ */


#include "kernel.h"
#include "kernel_id.h"

#include "main.h"
#include "ostimer.h"



/* ------------------------------------------ */
/*                 idle stack                 */
/* ------------------------------------------ */

VP         mknl_idl_stkblk[((128) + sizeof(VP) - 1) / sizeof(VP)];  /* idle stack block*/
const VP   mknl_idl_stk   = (VP)(mknl_idl_stkblk);  /* idle stack */
const SIZE mknl_idl_stksz = (SIZE)sizeof(mknl_idl_stkblk);  /* idle stack size */



/* ------------------------------------------ */
/*           create ready queue               */
/* ------------------------------------------ */

T_MKNL_QUE mknl_rdq_tbl[8];
const INT  mknl_rdq_cnt = 8;



/* ------------------------------------------ */
/*               set time tic                 */
/* ------------------------------------------ */

const UW kernel_tic_deno = TIC_DENO;
const UW kernel_tic_div  = TIC_NUME / TIC_DENO;
const UW kernel_tic_mod  = TIC_NUME % TIC_DENO;



/* ------------------------------------------ */
/*          create task objects               */
/* ------------------------------------------ */

/* stack area */
static VP kernel_tsk1_stk[((128) + sizeof(VP) - 1) / sizeof(VP)];

/* task control block for rom area */
const T_KERNEL_TCB_ROM kernel_tcb_rom[1] =
    {
        {(ATR)(TA_HLNG|TA_ACT), (VP_INT)(0), (FP)(MAIN), (PRI)(1), (SIZE)(128), (VP)kernel_tsk1_stk},
    };

/* task control block for ram area */
T_KERNEL_TCB_RAM kernel_tcb_ram[1];

/* task control block table */
T_KERNEL_TCB_RAM *kernel_tcb_ram_tbl[8] =
    {
        &kernel_tcb_ram[0],
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
    };

/* task control block count */
const INT kernel_tcb_cnt = 8;



/* ------------------------------------------ */
/*         create semaphore objects           */
/* ------------------------------------------ */

/* semaphore control block count */
const INT kernel_semcb_cnt = 0;



/* ------------------------------------------ */
/*        create event flag objects           */
/* ------------------------------------------ */

/* event flag control block count */
const INT kernel_flgcb_cnt = 0;



/* ------------------------------------------ */
/*        create data queue objects           */
/* ------------------------------------------ */

/* data queue control block count */
const INT kernel_dtqcb_cnt = 0;



/* ------------------------------------------ */
/*         create mail box objects            */
/* ------------------------------------------ */

/* mail box control block count */
const INT kernel_mbxcb_cnt = 0;



/* ------------------------------------------ */
/*      create message buffer objects         */
/* ------------------------------------------ */

/* mail box control block count */
const INT kernel_mbfcb_cnt = 0;



/* ------------------------------------------ */
/*   create fixed size memory-pool objects    */
/* ------------------------------------------ */

/* fixed size memory-pool control block count */
const INT kernel_mpfcb_cnt = 0;



/* ------------------------------------------ */
/*  create variable size memory-pool objects  */
/* ------------------------------------------ */

/* variable size memory-pool control block count */
const INT kernel_mplcb_cnt = 0;



/* ------------------------------------------ */
/*       create cyclic handler objects        */
/* ------------------------------------------ */

/* cyclic handler control block count */
const INT kernel_cyccb_cnt = 0;



/* ------------------------------------------ */
/*       create alarm handler objects         */
/* ------------------------------------------ */

/* alarm handler control block count */
const INT kernel_almcb_cnt = 0;



/* ------------------------------------------ */
/*        interrupt control objects           */
/* ------------------------------------------ */

/* interrupt control */
T_KERNEL_INTCB kernel_intcb_tbl[33];        /* interrupt control block table */
const INT      kernel_intcb_cnt = 33;       /* interrupt control block count */
const INTNO    kernel_min_intno = 0;        /* minimum intrrupt number */

/* interrupt service routine control */
const INT      kernel_isrcb_cnt = 0;        /* ISR control block count */



/* ------------------------------------------ */
/*    CPU exception handler control objects   */
/* ------------------------------------------ */

/* interrupt control */
T_KERNEL_EXCCB kernel_exccb_tbl[1];     /* CPU exception handler control block table */
const INT      kernel_exccb_cnt = 1;        /* CPU exception handler control block count */
const EXCNO    kernel_min_excno = 0;        /* minimum CPU exception handler number */



/* ------------------------------------------ */
/*          initialize functions              */
/* ------------------------------------------ */

/* object initialize */
void kernel_cfg_init(void)
{
    int i;
    
    
    /* initialize task control block */
    for ( i = 0; i < 1; i++ )
    {
        kernel_tcb_ram[i].tcb_rom = &kernel_tcb_rom[i];
    }

    /* initialize interrupt table */
    kernel_intcb_tbl[29].exinf = (VP_INT)(0);
    kernel_intcb_tbl[29].isr   = (FP)(Ostimer_interruptHandler);
}

/* start up */
void kernel_cfg_start(void)
{
    kernel_ini_tsk();       /* initialize task */

    /* call initialize routine*/
    ((FP)(Main_init))((VP_INT)(0));
    ((FP)(Ostimer_init))((VP_INT)(0));
}


/* ------------------------------------------------------------------------ */
/*  End of file                                                             */
/* ------------------------------------------------------------------------ */

非常にたくさんのグローバル変数や関数定義が記述されているのがわかります。今回使用しているsystem.cfgは大した定義はしていませんが、これだけの情報が自動生成されているのです。

kernel_cfg.cとkernel_id.hは自動生成されるファイルのため、皆さんが直接編集することは許されない。必ずsystem.cfgファイルを利用して変更すること!

スポンサー

HOS独自の静的API

HOSには独自の静的APIが定義されています。この定義はITRON仕様書には記載されていない部分になります。HOSによるITRONカーネルで必要となる特殊な情報が静的APIとして定義されているのです。

独自の静的APIに関する説明はHOS環境に含まれているため下記をのぞいてみるとよいでしょう。

独自静的API説明書: C:\WorkSpace\BeautoRoverRTOS\hos\document\hos4cfg.txt

HOS独自の静的APIの種類

次のものが定義されています。必要に応じて別途解説を行います。

HOS_IDL_STKアイドルタスクのスタック指定
HOS_INT_STK割り込みコンテキストのスタック指定
HOS_INT_SP割り込み時のスタックポインタの指定
HOS_MAX_TPRI最大タスク優先度の指定
HOS_KERNEL_HEAPカーネルヒープサイズの指定
HOS_TIM_TICタイムティックの周期の指定
HOS_MIN_INTNO割り込み番号の範囲の指定(最小値)
HOS_MAX_INTNO割り込み番号の範囲の指定(最大値)
HOS_MAX_TSKIDオブジェクトの最大IDの指定(タスク)
HOS_MAX_SEMIDオブジェクトの最大IDの指定(セマフォ)
HOS_MAX_FLGIDオブジェクトの最大IDの指定(イベントフラグ)
HOS_MAX_DTQIDオブジェクトの最大IDの指定(データキュー)
HOS_MAX_MBFIDオブジェクトの最大IDの指定(メッセージバッファ)
HOS_MAX_MBXIDオブジェクトの最大IDの指定(メールボックス)
HOS_MAX_MPFIDオブジェクトの最大IDの指定(固定長メモリプール)
HOS_MAX_CYCIDオブジェクトの最大IDの指定(周期ハンドラ)
HOS_MAX_ISRIDオブジェクトの最大IDの指定(割り込みサービスルーチン)