こんにちは、ナナです。
ITRONではサービスコール以外に静的APIと呼ばれる特殊なサービスコールが用意されています。ITRONのシステムを構築する際には静的APIを使いこなせる必要があります。
本記事では次の疑問点を解消する内容となっています。
では、順に解説していきます。
ITRONで定義される静的APIとコンフィギュレーションファイル
ITRON仕様において次のように定義されています。
ITRON仕様による静的APIの定義
(C)静的API
システムコンフィギュレーションファイル中に記述し、カーネルやソフトウェア部品の構成を決定したり、オブジェクトの初期状態を定義するためのインターフェースを静的APIと呼ぶ。
システムコンフィギュレーションファイルという用語が出てきました。静的APIと関連性の強い用語です。次のように定義されています。
ITRON仕様によるコンフィギュレーションファイルの定義
カーネルやソフトウェア部品の構成やオブジェクトの初期状態を定義するためのファイルをシステムコンフィギュレーションファイルと呼ぶ。
システムコンフィギュレーションファイルにはカーネルやソフトウェア部品の静的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_EXC | CPU例外ハンドラの定義 |
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 */
/* ------------------------------------------------------------------------ */
本来このファイルはシステムを作る皆さんが適切に記述して用意する必要があります。
自分が作りたいシステムにおいて「タスク」や「イベントフラグ」といったオブジェクトをいくつ利用するかという設計をした上でこのファイルにその意思を表明するのです。
その記述方法こそが静的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_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の指定(割り込みサービスルーチン) |
ITRONを基礎から体系的に学びたい方はこちらからどうぞ~