source: ssp_qb_r5f100le_cs/trunk/doc/configurator.txt@ 95

Last change on this file since 95 was 95, checked in by nmir-saito, 9 years ago

ファイルの mime-type 変更

  • Property svn:mime-type set to text/plain; charset=shift_jis
File size: 50.6 KB
Line 
1
2 TOPPERS/SSPカーネル
3 コンフィギュレータ仕様
4
5 対応バージョン: Release 1.3.0
6 最終更新: 2014年 5月 19日
7
8このドキュメントは,TOPPERS/SSPカーネルのコンフィギュレータが標準的に生
9成すべきファイルの内容について解説したものである.ターゲット依存に生成
10する内容については,このドキュメントの範囲外である.
11
12----------------------------------------------------------------------
13 TOPPERS/SSP Kernel
14 Toyohashi Open Platform for Embedded Real-Time Systems/
15 Smallet Set Profile Kernel
16
17 Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
18 Graduate School of Information Science, Nagoya Univ., JAPAN
19 Copyright (C) 2012-2015 by Naoki Saito
20 Nagoya Municipal Industrial Research Institute, JAPAN
21
22 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
23 ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
24 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
25 (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
26 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
27 スコード中に含まれていること.
28 (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
29 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
30 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
31 の無保証規定を掲載すること.
32 (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
33 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
34 と.
35 (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
36 作権表示,この利用条件および下記の無保証規定を掲載すること.
37 (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
38 報告すること.
39 (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
40 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
41 また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
42 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
43 免責すること.
44
45 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
46 よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
47 に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
48 アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
49 の責任を負わない.
50
51 $Id: configurator.txt 659 2015-05-19 09:45:26Z nmir-saito $
52----------------------------------------------------------------------
53
54○目次
55
56・生成するファイルの種類
57・静的API一覧
58・カーネル構成・初期化ヘッダファイル(kernel_cfg.h)
59 (1) 固定生成部分
60 (2) オブジェクト数の定義
61 (3) オブジェクトのID番号の定義
62・カーネル構成・初期化ファイル(kernel_cfg.c)
63 (1) 固定生成部分
64 (2) インクルードディレクティブ(#include)の処理
65 (3) オブジェクトのID番号を保持する変数の定義
66 (4) トレースログマクロのデフォルト定義
67 (5) 各カーネルオブジェクトに関する定義
68 (5-1) タスクに関する定義
69 (5-2) イベントフラグに関する定義
70 (5-3) データキューに関する定義
71 (5-4) 周期ハンドラに関する定義
72 (5-5) アラームハンドラに関する定義
73 (6) 割込みに関する定義
74 (6-1) 割込み要求ラインに関する定義
75 (6-2) 割込みサービスルーチンに関する定義
76 (6-3) 割込みハンドラに関する定義
77 (7) CPU例外に関する定義
78 (8) 共有スタック領域に関する定義
79 (9) タイムイベント管理に関する定義
80 (10)各モジュールの初期化関数の定義
81 (11)初期化ルーチンの実行関数の定義
82 (12)終了処理ルーチンの実行関数の定義
83
84○生成するファイルの種類
85
86SSPカーネルのコンフィギュレータは,システムコンフィギュレーションファイ
87ルを処理して,カーネル構成・初期化ファイル(kernel_cfg.c)と構成・初期
88化ヘッダファイル(kernel_cfg.h)を生成する.また,コンフィギュレータの
89処理の途中に,必要な中間ファイルを生成する.
90
91
92○静的API一覧
93
94SSPカーネルのコンフィギュレータが処理する静的APIは次の通り.
95
96(1) タスク管理機能
97 CRE_TSK(ID tskid, { ATR tskatr, intptr_t exinf, TASK task,
98 PRI itskpri, SIZE stksz, STK_T *stk })
99 DEF_EPR (ID tskid, { PRI exepri })
100
101(2) 同期・通信機能
102 CRE_FLG(ID flgid, { ATR flgatr, FLGPTN iflgptn })
103 CRE_DTQ(ID dtqid, { ATR dtqatr, uint_t dtqcnt, void *dtqmb })
104
105※ dtqmb が NULL でない場合はサポートしない.
106
107(3) 時間管理機能
108 CRE_CYC(ID cycid, { ATR cycatr, intptr_t exinf, CYCHDR cychdr,
109 RELTIM cyctim, RELTIM cycphs })
110 CRE_ALM(ID almid, { ATR almatr, intptr_t exinf, ALMHDR almhdr })
111
112(4) 割込み管理機能
113 CFG_INT(INTNO intno, { ATR intatr, PRI intpri })
114 ATT_ISR({ ATR isratr, intptr_t exinf, INTNO intno, ISR isr, PRI isrpri })
115 DEF_INH(INHNO inhno, { ATR inhatr, INTHDR inthdr })
116
117(5) CPU例外管理機能
118 DEF_EXC(EXCNO excno, { ATR excatr, EXCHDR exchdr })
119
120(6) システム構成管理機能
121 DEF_ICS({ SIZE istksz, STK_T *istk })
122 DEF_STK({ SIZE stksz, STK_T *stk })
123 ATT_INI({ ATR iniatr, intptr_t exinf, INIRTN inirtn })
124 ATT_TER({ ATR teratr, intptr_t exinf, TERRTN terrtn })
125
126これらの静的APIのパラメータの内,ID型のパラメータはオブジェクト識別名,
127ポインタ型(TASK,CYCHDR,ALMHDR,ISR,INTHDR,EXCHDR,INIRTN,TERRTN,
128STK_T *)および intptr_t 型のパラメータは一般定数式パラメータとする.
129その他のパラメータは,整数定数式パラメータとする.
130
131
132○カーネル構成・初期化ヘッダファイル(kernel_cfg.h)
133
134カーネル構成・初期化ヘッダファイル(kernel_cfg.h)には,次の定義を生成する.
135
136(1) 固定生成部分
137
138kernel_cfg.hが複数回インクルードされるのを防ぐための記述を生成する.具
139体的には,ファイルの先頭に次の行を生成する.
140
141#ifndef TOPPERS_KERNEL_CFG_H
142#define TOPPERS_KERNEL_CFG_H
143
144また,ファイルの末尾に次の行を生成する.
145
146#endif /* TOPPERS_KERNEL_CFG_H */
147
148(2) オブジェクト数の定義
149
150カーネルがサポートするオブジェクトの数をマクロ定義するプリプロセッサディ
151レクティブ(#define)を生成する.具体的には,次のような記述を生成する.
152
153#define TNUM_TSKID <タスクの数>
154#define TNUM_FLGID <イベントフラグの数>
155#define TNUM_DTQID <データキューの数>
156#define TNUM_CYCID <周期ハンドラの数>
157#define TNUM_ALMID <アラームハンドラの数>
158
159(3) オブジェクトのID番号の定義
160
161コンフィギュレータがID番号を割り付けたオブジェクトの名前を,割り付けた
162ID番号にマクロ定義するプリプロセッサディレクティブ(#define)を生成する.
163例えば,次のような記述を生成する.
164
165#define TASK1 1
166#define TASK2 2
167#define ALM1 1
168
169**************************************************************************
170SSPカーネルの場合,CRE_TSK における起動時優先度の高い(値としては小さい)
171順番に,1から連続した値がID番号としてそれぞれのタスクに割り当てられる.
172**************************************************************************
173
174
175○カーネル構成・初期化ファイル(kernel_cfg.c)
176
177(1) 固定生成部分
178
179kernel_cfg.c用のヘッダファイルとID自動割付け結果ファイルをインクルード
180するプリプロセッサディレクティブ(#include)を生成する.具体的には,次
181の行を生成する.
182
183#include "kernel/kernel_int.h"
184#include "kernel_cfg.h"
185
186(2) インクルードディレクティブ(#include)の処理
187
188システムコンフィギュレーションファイルに含まれるC言語プリプロセッサのイ
189ンクルードディレクティブ(#include)と同一のディレクティブ(#include)
190を生成する.例えば,
191
192#include "sample1.h"
193
194というインクルードディレクティブに対して,
195
196#include "sample1.h"
197
198というディレクティブを生成する.生成するディレクティブの順序は,システ
199ムコンフィギュレーションファイル中でのインクルードディレクティブの順序
200に一致させる.
201
202(3) オブジェクトのID番号を保持する変数の定義
203
204コンフィギュレータに対するオプション指定(--external-id)により,コンフィ
205ギュレータは変数を生成する.変数名は ID 番号を割り付けたオブジェクト名
206の末尾に "_id" を付加した名称とする.変数の型は,const属性を付加したID型
207とし,変数の値は割り付けたID番号とする.例えば,次のような記述を生成する.
208
209const ID TASK1_id = 1;
210const ID TASK2_id = 2;
211const ID ALM1_id = 1;
212
213(4) トレースログマクロのデフォルト定義
214
215kernel_cfg.cの中で使用するトレースログマクロのデフォルト定義を生成する.
216具体的には,次の行を生成する.
217
218#ifndef LOG_ISR_ENTER
219#define LOG_ISR_ENTER(intno)
220#endif /* LOG_ISR_ENTER */
221
222#ifndef LOG_ISR_LEAVE
223#define LOG_ISR_LEAVE(intno)
224#endif /* LOG_ISR_LEAVE */
225
226
227(5) 各カーネルオブジェクトに関する定義
228
229システムコンフィギュレーションファイル中に,オブジェクトを生成する静的
230API「CRE_XXX」が含まれる各カーネルオブジェクトに関して,オブジェクト生
231成のための定義を生成する.
232
233コンフィギュレータは,同じ種類のオブジェクトを生成する静的APIを集め,各
234オブジェクトにID番号を割り付ける.ID番号は,他のオブジェクトのID番号と
235重複がなく,ID番号が連続するように割り付ける.
236
237コンフィギュレータは,オブジェクトに割り付けるID番号を指定するための
238オプション(--id-input-file)並びに ID番号を割り付けたオブジェクトの名前
239および割り付けたID番号の組をファイルに出力するためのオプション
240(--id-output-file)を持つ.しかし,SSPカーネルではこれらのオプションの
241使用を原則として ***禁止*** する(理由は後述).
242
243**************************************************************************
244【理由】
245SSPカーネルの場合,「タスクIDの場合に限り」コンフィギュレータは
246--id-input-file の指定内容を無視する.それは,CRE_TSKで指定した起動時優先
247度の設定値が優先されるためである.また,--id-output-file で指定したファイ
248ルへの出力内容も --id-input-file で指定したタスクIDの値がそのまま出力され
249る.その出力内容は kernel_cfg.h へ出力されるタスクIDの値とは無関係である.
250従って,混乱が生じる恐れがあることから,SSPカーネルでは --id-input-file
251および --id-output-file オプションを指定してはならない.
252
253本来ならば,--kernel=ssp および --id-input-file を同時に指定した場合に
254コンフィギュレーションエラーとすべきところである.しかし,これらのオプショ
255ンに対する処理は全てコンフィギュレータ内部で実施され,テンプレートファイル
256(kernel.tf)では処理することができない.現時点ではコンフィギュレータの対応
257について未定であるため暫定的にこのような扱いとしている.
258**************************************************************************
259
260各カーネルオブジェクトに関する定義の標準的な構成は,次の通りである.オ
261ブジェクトによって例外がある場合には,オブジェクト毎の項で説明する.
262
263(a) 最大のオブジェクトIDの変数の定義
264
265最大のオブジェクトIDを持つ変数の定義を生成する.具体的には,オブジェク
266トの省略記号を「XXX/xxx」とすると,次のような行を生成する.
267
268const ID _kernel_tmax_xxxid = (TMIN_XXXID + TNUM_XXXID - 1);
269
270(b) オブジェクトに必要なメモリ領域の定義
271
272オブジェクトによっては,オブジェクトに必要なメモリ領域の定義を生成する.
273具体的には,オブジェクト毎の項で説明する.
274
275(c) オブジェクトの初期化ブロックの定義
276
277オブジェクトの初期化ブロックの定義を生成する.具体的には,
278 ・オブジェクトの省略記号を「XXX/xxx」
279 ・属性項目のデータ型を「YYY」
280 ・属性項目の名称を「zzz」
281とすると,オブジェクトの属性項目毎に次のような行を生成する.
282
283const YYY _kernel_xxxinib_zzz[TNUM_XXXID] = {
284 <オブジェクトIDが1のオブジェクトに対する zzz の初期化情報>,
285 <オブジェクトIDが2のオブジェクトに対する zzz の初期化情報>,
286 ……
287 <オブジェクトIDがTNUM_XXXIDのオブジェクトに対する zzz の初期化情報>,
288};
289
290オブジェクトの初期化情報の形式は,オブジェクトおよび属性項目毎に異なる.
291具体的にはオブジェクト毎の項で説明する.
292
293(d) オブジェクトのコントロールブロックの定義
294
295オブジェクトのコントロールブロックの定義を生成する.具体的には,
296 ・オブジェクトの省略記号を「XXX/xxx」
297 ・属性項目のデータ型を「YYY」
298 ・属性項目の名称を「zzz」
299とすると,オブジェクトの属性項目毎に次のような行を生成する.
300
301YYY _kernel_xxxcb_zzz[TNUM_XXXID];
302
303オブジェクトのコントロールブロックの形式は,オブジェクトおよび属性項目毎に異なる.
304具体的にはオブジェクト毎の項で説明する.
305
306
307(5-1) タスクに関する定義
308
309SSPカーネルは,タスクが一つもないケースに対応していないため,タスクに関する
310定義は必ず生成しなければならない.
311
312タスクの省略記号は「TSK」「tsk」である.
313ただし,タスク初期化ブロックの変数名は _kernel_tinib_<属性項目名> である.
314(「TSK/tsk」に代えて「T/t」を用いている).
315タスクコントロールブロックは存在しない.
316
317タスク初期化ブロックには,「CRE_TSK」静的APIで指定される情報に加えて,
318「DEF_EPR」静的APIで指定される情報を含める.
319
320以下では,システムコンフィギュレーションファイルに次の静的APIが含まれて
321いる時に生成すべき情報について述べる.
322
323CRE_TSK(tskid, { tskatr, exinf, task, itskpri, stksz, stk });
324DEF_EPR(tskid, { exepri });
325
326※ 以降の初期化情報の配列に格納される順序は,起動時優先度の高い順となる.
327※ なぜなら,タスクID が起動時優先度の高い順番で割り当てられるからである.
328
329(5-1-1) タスクの初期化情報(タスク属性)
330
331タスク属性の初期化情報は,次の形式とする.
332
333const ATR _kernel_tinib_tskatr[TNUM_TSKID] = {(tskatr)};
334
335(5-1-2) タスクの初期化情報(拡張情報)
336
337タスクの拡張情報の初期化情報は,次の形式とする.
338
339const intptr_t _kernel_tinib_exinf[TNUM_TSKID] = {(intptr_t)(exinf)};
340
341(5-1-3) タスクの初期化情報(起動番地)
342
343タスクの起動番地の初期化情報は,次の形式とする.
344
345const TASK _kernel_tinib_task[TNUM_TSKID] = {(task)};
346
347(5-1-4) タスクの初期化情報(実行時優先度)
348
349タスクの実行時優先度の初期化情報は,次の形式とする.
350(実際には改行されず,1行で出力される)
351
352const TASK _kernel_tinib_epriority[TNUM_TSKID] = {
353 INT_PRIORITY(実行時優先度)};
354
355実行時優先度の値は CRE_TSK の起動時優先度(itskpri) および
356DEF_EPR の実行時優先度(exepri) の設定値を元に算出される.
357算出方法については(5-1-6)に後述する.
358
359(5-1-5) ready_primap の初期値の定義
360
361タスクに対しては,ビットマップ ready_primap の初期値情報を生成する.
362タスク属性の設定値から一意に定めることができるからである.
363
364具体的には以下のような定義を生成する.
365
366const uint_t _kernel_init_rdypri = <ready_primapの初期値>;
367
368ここで ready_primap の初期値は,タスク属性(tskatr)の値から算出される.
369
370変数 _kernel_init_rdypri の各ビットはそれぞれのタスクに対応する.
371タスクIDが1のタスクは最下位ビット(LSB)に対応づけられており,
372タスクIDの値が1つ増える毎に1つ高位のビットがそれぞれ対応づけられる.
373例えば,タスクIDが4のタスクは最下位から数えて4番目のビットが対応する.
374
375タスク属性として TA_ACT を持つタスクは,そのタスクに対応するビットが
3761になる.TA_ACT を持たない場合は対応するビットが0になる.
377
378(5-1-6) 優先度の表現
379
380優先度の値は,コンフィギュレーションファイルの CRE_TSK 及び DEF_EPR にて
381指定した値を元に,コンフィギュレータが自動的に割り当てる.
382値の範囲は TMIN_TPRI(=1) から TMAX_TPRI の範囲の値をとる.
383
384また,コンフィギュレータにより割り当てられる優先度の値とは別に,処理効率の
385観点からプログラム中で使用される優先度の内部表現がある.
386内部表現の値は 0 から (TMAX_TPRI-TMIN_TPRI) の範囲の値をとる.
387優先度とその内部表現との間には (内部表現 = 優先度 - TMIN_TPRI)の関係がある.
388
389タスクの起動時優先度は,CRE_TSK で指定した起動時優先度の高い順に(値としては
390小さい順に),TMIN_TPRI(=1) からはじまる連続した値が割り当てられる.
391つまり,タスクの起動時優先度の値はタスクID に等しい.
392
393タスクの実行時優先度の値は,以下の方法で算出される.
394
395(1)当該タスクに対し DEF_EPR で実行時優先度を定義しない場合
396
397当該タスクに対し DEF_EPR で実行時優先度を定義しない場合,
398起動時優先度の値と同じ値を実行時優先度の値とする.
399
400(2)当該タスクに対し DEF_EPR で実行時優先度を定義する場合
401
402当該タスクに対し DEF_EPR で実行時優先度を定義した場合,
403DEF_EPR で指定した実行時優先度の設定値,並びに,全てのタスクに対する
404起動時優先度の設定値およびコンフィギュレーション結果として得られる起動時優先度
405の値をもとに,実行時優先度の値を算出する.
406
407実行時優先度の値を算出する方法は,「実行中のタスクがプリエンプトされる/されない」
408という関係が保存される範囲で適切な値が算出されることを意図したもので,
409具体的な手順は次のようになる.
410
411【実行時優先度の算出手順 ※これを全てのタスクに対して行う】
412
413(1) あるタスクを選ぶ(T1とする)
414(2) T1 の実行時優先度の設定値と同じ,または,それよりも低い(値としては
415大きい)起動時優先度の設定値を持つタスクの集合の中で,起動時優先度の
416設定値が最も高い(値としては最も小さい)タスクを探す(T2)
417(3) T2 の起動時優先度の値を T1 の実行時優先度の値とする.
418
419例)
420CRE_TSK(TASK1, { TA_NULL, 1, task1, 2, 10, NULL });
421CRE_TSK(TASK2, { TA_NULL, 3, task2, 6, 30, NULL });
422CRE_TSK(TASK3, { TA_NULL, 5, task3, 4, 50, NULL });
423CRE_TSK(TASK4, { TA_ACT, 7, task4, 8, 100, NULL });
424
425DEF_IPR(TASK1, { 1 } );
426DEF_IPR(TASK2, { 5 } );
427DEF_IPR(TASK3, { 3 } );
428DEF_IPR(TASK4, { 4 } );
429
430結果は次のようになる:
431
432【起動時優先度】
433 TASK1:設定値=2 → (割り当てられる)起動時優先度=1
434 TASK2:設定値=6 → (割り当てられる)起動時優先度=3
435 TASK3:設定値=4 → (割り当てられる)起動時優先度=2
436 TASK4:設定値=8 → (割り当てられる)起動時優先度=4
437
438 起動時優先度の高い順に並び替えると
439 TASK1:設定値=2 → 起動時優先度=1
440 TASK3:設定値=4 → 起動時優先度=2
441 TASK2:設定値=6 → 起動時優先度=3
442 TASK4:設定値=8 → 起動時優先度=4
443
444【実行時優先度】
445 TASK1:設定値=1
446 TASK3:設定値=3
447 TASK2:設定値=5
448 TASK4:設定値=4
449
450・ためしに TASK4 の場合の実行時優先度の値を算出してみる.
451 ・TASK4 の実行時優先度の設定値(4)と同じまたはそれよりも低い起動時
452  優先度の設定値をもつタスクの集合 = {TASK2,TASK3,TASK4}
453 ・上記タスクの集合の中で最も起動時優先度の設定値が高いもの = TASK3
454 ・上記タスクの起動時優先度の値 = 2
455 ・従ってTASK4 の実行時優先度の値は 2
456
457・同様に,TASK3 の場合は.
458 ・TASK3 の実行時優先度の設定値(3)と同じまたはそれよりも低い起動時
459  優先度の設定値をもつタスクの集合 = {TASK2,TASK3,TASK4}
460 ・上記タスクの集合の中で最も起動時優先度の設定値が高いもの = TASK3
461 ・上記タスクの起動時優先度の値 = 2
462 ・従ってTASK3 の実行時優先度の値は 2
463
464実行時優先度に対する初期化情報の kernel_cfg.c への結果は次のようになる.
465実際は1行で表現される.また,配列への格納順序は TASK1, TASK3, TASK2,
466TASK4 の順序で格納されることに注意する.
467ちなみに,INT_PRIORITY マクロは優先度の値をその内部表現に変換するマクロで
468あり,task.h で定義されている.
469
470const uint_t _kernel_tinib_epriority[TNUM_TSKID] =
471 {INT_PRIORITY(1),INT_PRIORITY(2),INT_PRIORITY(3),INT_PRIORITY(2)};
472
473(5-1-7) スタック領域設定
474
475SSPカーネルでは,タスクを含む全ての処理単位が同じスタック領域を共用する
476ように設計されている.
477共用されるスタック領域のことを「共有スタック領域」と呼ぶ.
478共有スタック領域の定義は DEF_STK を用いて行う.詳しくは(9)を参照のこと.
479
480コンフィギュレータは共有スタック領域のみ確保し,タスクコンテキスト専用の
481スタック領域は確保しない.
482このため,CRE_TSK では先頭番地 stk として NULL のみ受け付ける.
483NULL 以外の値を指定した場合,エラーとなる.
484
485また,CRE_TSK で指定するタスクのスタックサイズ stksz の値は,
486DEF_STK を用いない場合には共有スタック領域のサイズを決定するために用いられ,
487DEF_STK を用いる場合には DEF_STK で指定した共有スタック領域のサイズを
488チェックするために用いられる.※ (9-4) も参照のこと.
489
490全タスクによるスタック使用量(の推定値)は,CRE_TSK で指定する
491スタックサイズ stksz, および起動時優先度 itskpri,ならびに DEF_EPR で
492指定する実行時優先度 exepri から算出される.算出手順については次節で説明する.
493
494(5-1-8) 全タスクによるスタック使用量の算出方法
495
496全タスクのスタック使用量に対する計算の基本的な考え方は,それぞれの優先度ごとに,
497同じ優先度をもつタスクの中で最もスタック使用量が大きいものを選び,それらの
498スタック使用量をすべて加算したものと考えることである.実際にはプログラムにより
499それより少なくなるケースも存在し得るが,現在の実装では考え方を単純化している.
500
501SSPカーネルの仕様では,ひとつの起動時優先度につき登録可能なタスクは
502高々一つである.そのため,DEF_EPR により実行時優先度を設定しない場合,
503すなわち,全てのタスクの実行時優先度がそれぞれの起動時優先度に等しい
504場合,各タスクのスタック使用量を単純に加算したものが,全タスクによる
505スタック使用量となる.
506
507それに対し,DEF_EPR を用いて特定のタスクに対する実行時優先度を指定し,
508当該タスク実行中の優先度を引き上げるように設定した場合,本来ならばプリ
509エンプトされるはずのものがされなくなるケースが生じ,結果として全タスクの
510スタック使用量を少なくできる場合がある.
511
512実行時優先度を考慮した「全タスクによるスタック使用量」の算出手順は
513次のようになる(※)
514(a) あるタスクから実行開始し,他のどのようなタスクにプリエンプトされるか,
515 そして結果的にどういうプログラムの実行経路が存在し得るかを全て列挙する.
516(b) それぞれの場合の「全タスクによるスタック使用量」を求める.
517(c) 求めた値の中の最大値を選ぶ.
518
519※ 実装では,不要な処理の省略等も行っているが,ここでは基本的な考え方
520 のみを示す.
521
522算出手順を具体的な例を用いて説明する.
523例として先の (5-1-6) の例を用いる.
524下の手順 (a), (b), (c) は上に挙げた各項目に対応している.
525
526CRE_TSK(TASK1, { TA_NULL, 1, task1, 2, 10, NULL });
527CRE_TSK(TASK2, { TA_NULL, 3, task2, 6, 30, NULL });
528CRE_TSK(TASK3, { TA_NULL, 5, task3, 4, 50, NULL });
529CRE_TSK(TASK4, { TA_ACT, 7, task4, 8, 100, NULL });
530
531DEF_IPR(TASK1, { 1 } );
532DEF_IPR(TASK2, { 5 } );
533DEF_IPR(TASK3, { 3 } );
534DEF_IPR(TASK4, { 4 } );
535
536(a) あるタスク(TASKn, n = 1,2,3,4)を選択する.
537 TASKn の実行時優先度よりも高い起動時優先度(値としては小さい)をもつ
538 タスクの集合を探す.
539 そして「プリエンプトされるタスク→プリエンプトするタスク」の組を列挙する.
540
541・TASK1 に着目すると,これをプリエンプト可能なタスクは存在しない.
542・TASK2 に着目すると,実行中は優先度 5 になり,これをプリエンプト可能な
543 タスクは TASK1 および TASK3.
544・TASK3 に着目すると,実行中は優先度 3 になり,これをプリエンプト可能な
545 タスクは TASK1 だけ.
546・TASK4 に着目すると,実行中は優先度 4 になり,これをプリエンプト可能な
547 タスクは TASK1 だけ.
548
549したがってここでは,次の組が得られる.
550 TASK2 → TASK1
551 TASK2 → TASK3
552 TASK3 → TASK1
553 TASK4 → TASK1
554
555全くプリエンプトされないケース,および,プリエンプトしたタスクがさらに
556別のタスクにプリエンプトされるケースまで考慮すると,結果的にプログラムの
557実行経路は次のようになると考えられる.
558
559・TASK1 から始まるケース:
560 TASK1 (プリエンプトされずに終了)
561
562・TASK2 から始まるケース:
563 TASK2
564 TASK2 → TASK1 (TASK2から実行開始して,TASK1にプリエンプトされた)
565 TASK2 → TASK3
566 TASK2 → TASK3 → TASK1
567
568・TASK3 から始まるケース:
569 TASK3
570 TASK3 → TASK1
571
572・TASK4 から始まるケース:
573 TASK4
574 TASK4 → TASK1
575
576(b) それぞれのケースでスタック使用量を計算する.
577
578・TASK1 から始まるケース:
579 TASK1:10
580
581・TASK2 から始まるケース:
582 TASK2:30
583 TASK2 → TASK1:30+10
584 TASK2 → TASK3:30+50
585 TASK2 → TASK3 → TASK1:30+50+10
586
587・TASK3 から始まるケース:
588 TASK3:50
589 TASK3 → TASK1:50+10
590
591・TASK4 から始まるケース:
592 TASK4:100
593 TASK4 → TASK1:100+10
594
595(c) 最も値が大きくなる経路を選ぶ.
596
597ここでは TASK4 → TASK1 の場合が最大で,見積もり値は 110
598
599
600(5-1-9) 全タスクによるスタック使用量の定義
601
602コンフィギュレータは,全タスクによるスタック使用量の見積もり過程を
603kernel_cfg.c にコメントとして出力する.
604
605/*
606 * Task Stack Size Estimation:
607 *
608 (ここに算出の過程が出力される)
609 */
610
611そして,次のような行を生成する.
612
613#define TOPPERS_TSTKSZ <全タスクによるスタック使用量の計算値>
614
615
616(5-1-10) エラー条件
617
618タスクに関するエラー条件は次の通りである.
619
620*コンフィギュレータ本体が検出するもの
621・タスクが一つも存在しない場合.
622・同じtskidに対するCRE_TSKが複数ある場合(E_OBJ)
623・DEF_EPRに対応するCRE_TSKがない場合(E_NOEXS)
624・同じtskidに対するDEF_EPRが複数ある場合(E_OBJ)
625
626*パス2で検出するもの
627・tskatrが([[TA_ACT]|[TA_RSTR])でない場合(E_RSATR)
628 ※ ターゲット依存部でタスク属性を追加可(TARGET_TSKATR)
629・(TMIN_TPRI <= itskpri && itskpri <= TMAX_TPRI)でない場合(E_PAR)
630・同じ itskpri に対する CRE_TSK が複数ある場合 (E_PAR)
631・stkszが0か,ターゲット定義の最小値(TARGET_MIN_STKSZ)よりも小さい場
632 合(E_PAR)
633・stk が NULL でない場合(E_PAR)
634・(TMIN_TPRI <= exepri && exepri <= TMAX_TPRI) でない場合:E_PAR エラー
635・(itskpri < exepri && exepri <= TMAX_TPRI) である場合:E_ILUSEエラー
636
637*パス3で検出するもの
638・task がプログラムの開始番地として正しくない場合(E_PAR)
639 - ターゲット依存の値(CHECK_FUNC_ALIGN)の倍数でない場合
640 - NULLの場合(ターゲット依存,CHECK_FUNC_NONNULL)
641
642
643(5-2) イベントフラグに関する定義
644
645イベントフラグの省略記号は「FLG/flg」である.以下では,システムコンフィ
646ギュレーションファイルに次の静的APIが含まれている時に生成すべき情報につ
647いて述べる.
648
649CRE_FLG(flgid, { flgatr, iflgptn });
650
651(5-2-1) イベントフラグの初期化情報(イベントフラグ属性)
652
653イベントフラグの属性情報の初期化情報は,次の形式とする.
654
655const ATR _kernel_flginib_atr[TNUM_FLGID] = {(flgatr)};
656
657(5-2-2) イベントフラグの初期化情報(フラグパターン初期値)
658
659イベントフラグのフラグパターンの初期化情報は,次の形式とする.
660
661const FLGPTN _kernel_flginib_iflgptn[TNUM_FLGID] = {(iflgptn)};
662
663(5-2-3) イベントフラグのフラグパターン
664
665イベントフラグのフラグパターンを格納する配列は,以下の形式とする.
666
667FLGPTN _kernel_flgcb_flgptn[TNUM_FLGID];
668
669(5-2-4) エラー条件
670
671イベントフラグに関するエラー条件は次の通りである.
672
673*コンフィギュレータ本体が検出するもの
674・同じflgidに対するCRE_FLGが複数ある場合(E_OBJ)
675
676*パス2で検出するもの
677・tskatrが([[TA_CLR]|[TA_NULL])でない場合(E_RSATR)
678 ※ TA_CLR と TA_NULL を同時に指定した場合,TA_CLR のみを指定した場合と同様に振る舞う
679・iflgptn がFLGPTN に格納できない(iflgptnの値がFLGPTN型の最大値よりも大きい)場合(E_PAR)
680
681
682(5-3) データキューに関する定義
683
684データキューの省略記号は「DTQ/dtq」である.以下では,システムコンフィギュ
685レーションファイルに次の静的APIが含まれている時に生成すべき情報について
686述べる.
687
688CRE_DTQ(dtqid, { dtqatr, dtqcnt, dtqmb });
689
690(5-3-1) データキューに必要なメモリ領域の定義
691
692データキューに必要なメモリ領域として,データキュー管理領域がある.生成
693するデータキュー毎に,必要なサイズのデータキュー管理領域を定義する.具
694体的には,上記の静的APIに対して,次の定義を生成する.
695
696*dtqcntが0でない場合のみ生成
697static intptr_t _kernel_dtqmb_<データキュー名>[dtqcnt];
698
699(5-3-2) データキューの初期化情報(データキュー属性)
700
701データキューの属性情報の初期化情報は,次の形式とする.
702
703const ATR _kernel_dtqinib_atr[TNUM_DTQID] = {(dtqatr)};
704
705(5-3-3) データキューの初期化情報(データキュー管理領域)
706
707データキューのデータキュー管理領域の初期化情報は,次の形式とする.
708
709intptr_t * const _kernel_dtqinib_data[TNUM_DTQID] = {(_kernel_dtqmb_<データキュー名>)};
710
711※ SSPカーネルでは待ち状態をサポートしないため,同期呼出しが実現できない.
712 そのため dtqcnt が 0 の場合,コンフィギュレーションエラー(E_PAR)となる.
713
714(5-3-4) データキューの初期化情報(データキューのサイズ)
715
716データキューのサイズの初期化情報は,次の形式とする.
717
718const uint8_t _kernel_dtqinib_size[TNUM_DTQID] = {(dtqcnt)};
719
720(5-3-5) データキューに格納されている要素数
721
722データキューに格納されている要素数の配列は,次の形式とする.
723
724uint8_t _kernel_dtqcb_count[TNUM_DTQID];
725
726(5-3-6) データキューの先頭・末尾要素
727
728データキューに格納されている先頭要素・末尾要素を格納する配列は,次の形式とする.
729
730uint8_t _kernel_dtqcb_head[TNUM_DTQID];
731uint8_t _kernel_dtqcb_tail[TNUM_DTQID];
732
733(5-3-7) エラー条件
734
735データキューに関するエラー条件は次の通りである.
736
737*コンフィギュレータ本体が検出するもの
738・同じdtqidに対するCRE_DTQが複数ある場合(E_OBJ)
739
740*パス2で検出するもの
741・dtqatrが([TA_NULL])でない場合(E_RSATR)
742・dtqcntが 0 の場合 (E_PAR)
743・dtqmb が NULL でない場合(E_NOSPT)
744
745
746(5-4) 周期ハンドラに関する定義
747
748周期ハンドラの省略記号は「CYC/cyc」である.以下では,システムコンフィ
749ギュレーションファイルに次の静的APIが含まれている時に生成すべき情報につ
750いて述べる.
751
752CRE_CYC(cycid, { cycatr, exinf, cychdr, cyctim, cycphs });
753
754(5-4-1) 周期ハンドラの初期化情報(拡張情報)
755
756周期ハンドラの拡張情報の初期化情報は,次の形式とする.
757
758const intptr_t _kernel_cycinib_exinf[TNUM_CYCID] = {(intptr_t)(exinf)};
759
760(5-4-2) 周期ハンドラの初期化情報(起動番地)
761
762周期ハンドラのアドレスの初期化情報は,次の形式とする.
763
764const CYCHDR _kernel_cycinib_cychdr[TNUM_CYCID] = {(cycdhr)};
765
766(5-4-3) 周期ハンドラの初期化情報(起動周期)
767
768周期ハンドラの起動周期の初期化情報は,次の形式とする.
769
770const RELTIM _kernel_cycinib_cyctim[TNUM_CYCID] = {(cyctim)};
771
772(5-4-4) 周期ハンドラの初期化情報(位相)
773
774周期ハンドラの位相の初期化情報は,次の形式とする.
775
776const RELTIM _kernel_cycinib_cycphs[TNUM_CYCID] = {(cycphs)};
777
778(5-4-5) 周期ハンドラの動作状態
779
780周期ハンドラの動作状態を格納する変数は,次の形式とする.
781
782uint_t _kernel_cyccb_cycact;
783
784変数 _kernel_cyccb_cycact の各ビットはそれぞれの周期ハンドラに対応する.
785周期ハンドラIDが1のタスクは最下位ビット(LSB)に対応づけられており,
786IDの値が1つ増える毎に1つ高位のビットがそれぞれ対応づけられる.
787例えば,ハンドラIDが4の周期ハンドラは最下位から数えて4番目のビットが
788対応する.
789
790動作している状態の周期ハンドラは,その周期ハンドラに対応するビットが
7911となる.動作していない状態の周期ハンドラは対応するビットが0になる.
792
793(5-4-6) 周期ハンドラの次回起動時刻の定義
794
795周期ハンドラの次回起動時刻を格納する変数は,次の形式とする.
796
797EVTTIM _kernel_cyccb_evttim[TNUM_CYCID];
798
799(5-4-7) タイムイベントキューの中のオフセット情報の定義
800
801タイムイベントキューの中で周期ハンドラ用に割り当てられた領域の先頭位置を
802示す情報を変数に保持する.タイムイベントキューは配列で表現されており,
803先頭位置は配列の先頭からのオフセット(つまり配列のインデックス)として
804表現される.周期ハンドラに対してはタイムイベントキュー配列の先頭から割り
805当てられるため,この値は常に 0 となる.従って変数定義は,次の形式となる.
806
807const uint_t _kernel_cycevtid_offset = 0;
808
809タイムイベントキューについては(9-3)を参照のこと.
810
811(5-4-8) エラー条件
812
813周期ハンドラに関するエラー条件は次の通りである.
814
815*コンフィギュレータ本体が検出するもの
816・同じcycidに対するCRE_CYCが複数ある場合(E_OBJ)
817
818*パス2で検出するもの
819・cycatrが([TA_STA])でない場合(E_RSATR)
820・(0 < cyctim && cyctim <= TMAX_RELTIM)でない場合(E_PAR)
821・(0 <= cycphs && cycphs <= TMAX_RELTIM)でない場合(E_PAR)
822・警告:cycatrにTA_STAが設定されていて,(cycphs == 0)の場合
823・CRE_CYC のエントリが16個より多い ※SSP実装定義事項
824
825*パス3で検出するもの
826・cychdrがプログラムの開始番地として正しくない場合(E_PAR)
827 - ターゲット依存の値(CHECK_FUNC_ALIGN)の倍数でない場合
828 - NULLの場合(ターゲット依存,CHECK_FUNC_NONNULL)
829
830(5-5) アラームハンドラに関する定義
831
832アラームハンドラの省略記号は「ALM/alm」である.以下では,システムコン
833フィギュレーションファイルに次の静的APIが含まれている時に生成すべき情報
834について述べる.
835
836CRE_ALM(ID almid, { almatr, (intptr_t)(exinf), almhdr });
837
838(5-5-1) アラームハンドラの初期化情報(拡張情報)
839
840アラームハンドラの拡張情報の初期化情報は,次の形式とする.
841
842const intptr_t _kernel_alminib_exinf[TNUM_ALMID] = {(intptr_t)(exinf)};
843
844(5-5-2) アラームハンドラの初期化情報(起動番地)
845
846アラームハンドラの起動番地の初期化情報は,次の形式とする.
847
848const ALMHDR _kernel_alminib_almhdr[TNUM_ALMID] = {(almhdr)};
849
850(5-5-3) アラームハンドラの動作状態
851
852アラームハンドラの動作状態を格納する変数は,次の形式とする.
853
854uint_t _kernel_almcb_almact;
855
856変数 _kernel_almcb_almact の各ビットは個々のアラームハンドラに対応する.
857アラームハンドラIDが1のタスクは最下位ビット(LSB)に対応づけられており,
858IDの値が1つ増える毎に1つ高位のビットがそれぞれ対応づけられる.
859例えば,ハンドラIDが4のアラームハンドラは最下位から数えて4番目のビットが
860対応する.
861
862動作している状態のアラームハンドラは,その周期ハンドラに対応するビットが
8631となる.動作していない状態の周期ハンドラは対応するビットが0になる.
864
865(5-5-4) タイムイベントキューの中のオフセット情報の定義
866
867タイムイベントキューの中でアラームハンドラ用に割り当てられた領域の先頭
868位置を示す情報を変数に保持する.タイムイベントキューは配列で表現されており,
869先頭位置は配列の先頭からのオフセット(つまり配列のインデックス)として
870表現される.アラームハンドラに対しては周期ハンドラ用領域の次の要素から
871割り当てられるため,この値は常に周期ハンドラの個数に等しい.
872変数定義は,次の形式となる.
873
874const uint_t _kernel_almevtid_offset = <周期ハンドラの個数>;
875
876タイムイベントキューについては(9-3)を参照のこと.
877
878(5-5-5) エラー条件
879
880アラームハンドラに関するエラー条件は次の通りである.
881
882*コンフィギュレータ本体が検出するもの
883・同じalmidに対するCRE_ALMが複数ある場合(E_OBJ)
884
885*パス2で検出するもの
886・almatrが(TA_NULL)でない場合(E_RSATR)
887・CRE_ALM のエントリが16個より多い ※SSP実装定義事項
888
889*パス3で検出するもの
890・almhdrがプログラムの開始番地として正しくない場合(E_PAR)
891 - ターゲット依存の値(CHECK_FUNC_ALIGN)の倍数でない場合
892 - NULLの場合(ターゲット依存,CHECK_FUNC_NONNULL)
893
894(6) 割込みに関する定義
895
896割込みに関して生成する情報は,ターゲット毎に定めることができる.
897ターゲット毎に定めない場合には,以下で述べるターゲットに依存しない標準的な
898情報を生成する.ターゲット毎に定める場合には,(6-1)と(6-3)に述べる情報は生
899成しない((6-2)に述べる情報は生成する).
900
901(6-1) 割込み要求ラインに関する定義
902
903割込み要求ラインの属性を設定する静的API「CFG_INT」で設定した割込み要求
904ラインに関する定義を生成する.具体的には次の通り.
905
906以下では,システムコンフィギュレーションファイルに次の静的APIが含まれ
907ている時に生成すべき情報について述べる.
908
909CFG_INT(INTNO intno, { intatr, intpri });
910
911(6-1-1) 設定する割込み要求ラインの数
912
913設定する割込み要求ラインの数をマクロ定義するプリプロセッサディレクティ
914ブ(#define)を生成する.また,その値を持つ変数の定義を生成する.具体的
915には,次のような行を生成する.
916
917#define TNUM_INTNO <設定する割込み要求ラインの数>
918const uint_t _kernel_tnum_intno = TNUM_INTNO;
919
920(6-1-2) 割込み要求ラインの初期化情報(割込み番号)
921
922割込み番号の初期化情報は,次の形式とする.
923
924const INTNO _kernel_intinib_intno[TNUM_INTNO] = {(intno)};
925
926(6-1-3) 割込み要求ラインの初期化情報(割込み要求ライン属性)
927
928割込み要求ライン属性の初期化情報は,次の形式とする.
929
930const ATR _kernel_intinib_intatr[TNUM_INTNO] = {(intatr)};
931
932(6-1-4) 割込み要求ラインの初期化情報(割込み要求ライン属性)
933
934割込み優先度の初期化情報は,次の形式とする.
935
936const PRI _kernel_intinib_intpri[TNUM_INTNO] = {(intpri)};
937
938(6-1-5) エラー条件
939
940割込み要求ラインに関するエラー条件は次の通りである.
941
942*パス2で検出するもの
943・intno が CFG_INTに対する割込み番号として正しくない場合(E_PAR)
944・intno が CFG_INTによって設定済みの場合(E_OBJ)
945・intatrが([TA_ENAINT]|[TA_EDGE])でない場合(E_RSATR)
946 ※ ターゲット依存部で割込み属性を追加可(TARGET_INTATR)
947・カーネル管理に固定されている intno に対して,intpriにTMIN_INTPRI
948 よりも小さい値(つまり,優先度としては高い値)が指定された場合(E_OBJ)
949・カーネル管理外に固定されている intno に対して,intpri に TMIN_INTPRI
950 と同じかまたはそれよりも大きい値(つまり,優先度としては同じかまたは
951 それより低い値)が指定された場合(E_OBJ)
952・intpri が CFG_INT に対する割込み優先度として正しくない場合(E_PAR)
953
954*必要に応じてターゲット依存部で検出するもの
955・intatr が割込み属性として設定できない値の場合(E_RSATR)
956・intpri が割込み優先度として設定できない値の場合(E_PAR)
957・同一の割込み優先度しか設定できない割込み要求ラインに対して,異なる割
958 込み優先度を設定した場合(E_PAR)
959
960(6-2) 割込みサービスルーチンに関する定義
961
962(6-2-1) 割込みハンドラの生成
963
964システムコンフィギュレーションファイル中に含まれる割込みサービスルーチ
965ンを追加する静的API「ATT_ISR」に基づき,同一の割込み番号に対して追加さ
966れた割込みサービスルーチンを順に呼び出す関数を生成する.
967
968具体的には,同一の割込み番号に対して割込みサービスルーチンを追加する
969
970ATT_ISR({ isratr_1, exinf_1, intno, isr_1, isrpri_1 });
971ATT_ISR({ isratr_2, exinf_2, intno, isr_2, isrpri_2 });
972 ……
973ATT_ISR({ isratr_n, exinf_n, intno, isr_n, isrpri_n });
974
975という静的APIに対して,次のような関数を生成する.ここで,isrpri_1,
976isrpri_2,……,isrpri_nは,値の小さい順に並べ替えられているものとする.
977値が同じものの間では,システムコンフィギュレーションファイル中での静的
978APIの順序の通りに並んでいるものとする.
979
980static void
981_kernel_inthdr_<intno>(void)
982{
983 PRI saved_ipm;
984
985 i_begin_int(intno);
986 saved_ipm = i_get_ipm();
987
988 LOG_ISR_ENTER(<intno>); /* ISR1の呼出し */
989 isr_1((intptr_t)(exinf_1));
990 LOG_ISR_LEAVE(intno);
991
992 if (i_sense_lock()) { /* ISRの呼出し前の状態に戻す */
993 i_unlock_cpu();
994 }
995 i_set_ipm(saved_ipm);
996
997 LOG_ISR_ENTER(<intno>); /* ISR2の呼出し */
998 isr_2((intptr_t)(exinf_2));
999 LOG_ISR_LEAVE(intno);
1000
1001 if (i_sense_lock()) { /* ISRの呼出し前の状態に戻す */
1002 i_unlock_cpu();
1003 }
1004 i_set_ipm(saved_ipm);
1005
1006 ……
1007
1008 LOG_ISR_ENTER(<intno>); /* ISRnの呼出し */
1009 isr_n((intptr_t)(exinf_n));
1010 LOG_ISR_LEAVE(intno);
1011
1012 i_end_int(intno);
1013}
1014
1015ここで,ISRnの呼出しの後に呼出し前の状態に戻さないのは,割込みハンドラ
1016からのリターンにより,カーネルが元の状態に戻すためである.
1017
1018同一の割込み番号に対して追加された割込みサービスルーチンが1つのみの場合
1019には,次のような関数を生成する.
1020
1021static void
1022_kernel_inthdr_<intno>(void)
1023{
1024 i_begin_int(intno);
1025 LOG_ISR_ENTER(intno);
1026 isr_1((intptr_t)(exinf_1));
1027 LOG_ISR_LEAVE(intno);
1028 i_end_int(intno);
1029}
1030
1031【課題】ここで,LOG_ISR_ENTER,LOG_ISR_LEAVEの引数をどうするかが課題と
1032して残っている.ATT_ISRで登録されたISRに対してはISR IDが付与されないた
1033め,IDでISRを区別することができない.やむなく割込み番号を渡しているが,
1034拡張情報(exinf)も渡すべきかもしれない.
1035
1036(6-2-2) 割込みハンドラの定義に相当する処理
1037
1038上のように割込みハンドラを生成した場合には,次に説明する割込みハンドラ
1039に関する定義において,システムコンフィギュレーションファイル中に次の静
1040的APIが含まれているのと同様に処理する.
1041
1042DEF_INH(inhno, { TA_NULL, _kernel_inthdr_<intno> });
1043
1044ここでinhnoは,intnoに対応する割込みハンドラ番号である.
1045
1046(6-2-3) エラー条件
1047
1048割込みサービスルーチンに関するエラー条件は次の通りである.
1049
1050*パス2で検出するもの
1051・isratr が(TA_NULL)でない場合(E_RSATR)
1052 ※ ターゲット依存部で割込みサービスルーチン属性を追加可(TARGET_ISRATR)
1053・intno が ATT_ISR に対する割込み番号として正しくない場合(E_PAR)
1054 ※ intno に対応する inhno がない場合を含む
1055・(TMIN_ISRPRI <= isrpri && isrpri <= TMAX_ISRPRI)でない場合(E_PAR)
1056・intno に対応する inhno に対して DEF_INH がある場合(E_OBJ)
1057・intno に対する CFG_INT がない場合(E_OBJ)
1058・intno に対して CFG_INT が存在し,かつ,CFG_INT で設定された割込み優先度が
1059 TMIN_INTPRI よりも小さい(つまり,優先度としては高い)場合(E_OBJ)
1060 ※ カーネル管理外のISRはサポートしないため
1061
1062*必要に応じてターゲット依存部で検出するもの
1063・isrがプログラムの開始番地として正しくない場合(E_PAR)
1064
1065(6-3) 割込みハンドラに関する定義
1066
1067割込みハンドラを定義する静的API「DEF_INH」で定義した割込みハンドラ
1068(上述の割込みサービスルーチンの追加によりコンフィギュレータが生成した
1069割込みハンドラを含む)に関する定義を生成する.具体的には次の通り.
1070
1071以下では,システムコンフィギュレーションファイルに次の静的APIが含まれ
1072ている時に生成すべき情報について述べる.
1073
1074DEF_INH(inhno, { inhatr, inthdr });
1075
1076(6-3-1) 定義する割込みハンドラの数
1077
1078定義する割込みハンドラの数をマクロ定義するプリプロセッサディレクティブ
1079(#define)を生成する.また,その値を持つ変数の定義を生成する.具体的
1080には,次のような行を生成する.
1081
1082#define TNUM_INHNO <定義する割込みハンドラの数>
1083const uint_t _kernel_tnum_inhno = TNUM_INHNO;
1084
1085(6-3-2) 割込みハンドラの出入口処理
1086
1087定義する割込みハンドラ毎に,割込みハンドラの出入口処理ルーチンを生成す
1088る.具体的には,次のような行を生成する.
1089
1090INTHDR_ENTRY(inhno, inhno_num, inthdr)
1091
1092ここでinhno_numは,inhno(割込みハンドラ番号)を数値で表現したもので,
1093アセンブリ言語記述に使用するためのものである.
1094
1095(6-3-3) 割込みハンドラの初期化情報(割込みハンドラ番号)
1096
1097割込みハンドラ番号の初期化情報は,次の形式とする.
1098
1099const INHNO _kernel_inhinib_inhno[TNUM_INHNO] = {(inhno)};
1100
1101(6-3-4) 割込みハンドラの初期化情報(割込みハンドラ属性)
1102
1103割込みハンドラ属性の初期化情報は,次の形式とする.
1104
1105const ATR _kernel_inhinib_inhatr[TNUM_INHNO] = {(inhatr)};
1106
1107(6-3-5) 割込みハンドラの初期化情報(割込みハンドラアドレス)
1108
1109割込みハンドラのアドレスの初期化情報は,次の形式とする.
1110
1111const FP _kernel_inhinib_entry[TNUM_INHNO] = {(inthdr)};
1112
1113(6-3-6) エラー条件
1114
1115割込みハンドラに関するエラー条件は次の通りである.
1116
1117*パス2で検出するもの
1118・inhno が DEF_INH に対する割込みハンドラ番号として正しくない場合(E_PAR)
1119・inhno が DEF_INH によって設定済みの場合(E_OBJ)
1120#・inhno に対応する intno に対して ATT_ISR がある場合(E_OBJ)
1121# ※ inhno に対応する intno がない場合には,このチェックを行わない
1122# → このチェックは,割込みサービスルーチン側で行う
1123・inhatr が(TA_NULL)でない場合(E_RSATR)
1124 ※ ターゲット依存部で割込みハンドラ属性を追加可(TARGET_INHATR)
1125 ※ TA_NONKERNEL を使う場合には,TARGET_INHATR に設定する
1126・カーネル管理に固定されている inhno に対して,inhatr に TA_NONKERNEL が
1127 指定されている場合(E_RSATR)
1128・カーネル管理外に固定されている inhno に対して,inhatr に TA_NONKERNEL が
1129 指定されていない場合(E_RSATR)
1130・inhno に対応する intno に対する CFG_INT がない場合(E_OBJ)
1131 ※ inhno に対応する intno がない場合には,このチェックを行わない
1132・inhatr に TA_NONKERNEL が指定されておらず,inhno に対応する intno に対して
1133 CFG_INT で設定された割込み優先度が TMIN_INTPRI よりも小さい場合(E_OBJ)
1134 ※ inhno に対応する intno がない場合には,このチェックを行わない
1135・inhatr に TA_NONKERNEL が指定されており,inhno に対応する intno に対して
1136 CFG_INT で設定された割込み優先度が TMIN_INTPRI 以上である場合(E_OBJ)
1137 ※ inhno に対応する intno がない場合には,このチェックを行わない
1138
1139*必要に応じてターゲット依存部で検出するもの
1140・inthdrがプログラムの開始番地として正しくない場合(E_PAR)
1141
1142(7) CPU例外に関する定義
1143
1144CPU例外に関して生成する情報は,ターゲット毎に定めることができる.
1145ターゲット毎に定めない場合には,以下で述べるターゲットに依存しない標準的な
1146情報を生成する.ターゲット毎に定める場合には,これらの情報は生成されない.
1147
1148システムコンフィギュレーションファイル中に,CPU例外ハンドラを定義する
1149静的API「DEF_EXC」が含まれている場合に,CPU例外ハンドラに関する定義を
1150生成する.
1151
1152以下では,システムコンフィギュレーションファイルに次の静的APIが含まれ
1153ている時に生成すべき情報について述べる.
1154
1155DEF_EXC(excno, { excatr, exchdr });
1156
1157(7-1) 定義するCPU例外ハンドラの数
1158
1159定義するCPU例外ハンドラの数をマクロ定義するプリプロセッサディレクティ
1160ブ(#define)を生成する.また,その値を持つ変数の定義を生成する.具体
1161的には,次のような行を生成する.
1162
1163#define TNUM_EXCNO <定義するCPU例外ハンドラの数>
1164const uint_t _kernel_tnum_excno = TNUM_EXCNO;
1165
1166(7-2) CPU例外ハンドラの出入口処理
1167
1168定義するCPU例外ハンドラ毎に,CPU例外ハンドラの出入口処理ルーチンを生成
1169する.具体的には,次のような行を生成する.
1170
1171EXCHDR_ENTRY(excno, excno_num, exchdr)
1172
1173ここでexcno_numは,excno(CPU例外ハンドラ番号)を数値で表現したもので,
1174アセンブリ言語記述に使用するためのものである.
1175
1176(7-3) CPU例外ハンドラ番号の初期化情報(CPU例外番号)
1177
1178CPU例外ハンドラ番号の初期化情報は,次の形式とする.
1179
1180const EXCNO _kernel_excinib_excno[TNUM_EXCNO] = {(excno)};
1181
1182(7-4) CPU例外ハンドラ番号の初期化情報(CPU例外ハンドラ属性)
1183
1184CPU例外ハンドラ属性の初期化情報は,次の形式とする.
1185
1186const ATR _kernel_excinib_excatr[TNUM_EXCNO] = {(excatr)};
1187
1188(7-5) CPU例外ハンドラ番号の初期化情報(CPU例外ハンドラの先頭番地)
1189
1190CPU例外ハンドラの先頭番地の初期化情報は,次の形式とする.
1191
1192const FP _kernel_excinib_entry[TNUM_EXCNO] = {(FP)(EXC_ENTRY(excno, exchdr))};
1193
1194ここで EXC_ENTRY はCPU例外ハンドラ番号とCPU例外ハンドラの先頭番地を元に
1195CPU例外ハンドラの入り口処理の名称を生成するマクロで,ターゲット依存部で
1196定義されている.
1197
1198(7-6) エラー条件
1199
1200CPU例外ハンドラに関するエラー条件は次の通りである.
1201
1202*パス2で検出するもの
1203・excno が DEF_EXC に対する CPU 例外ハンドラ番号として正しくない場合(E_PAR)
1204・excno が DEF_EXC によって設定済みの場合(E_OBJ)
1205・excatr が(TA_NULL)でない場合(E_RSATR)
1206 ※ ターゲット依存部でCPU例外ハンドラ属性を追加可(TARGET_EXCATR)
1207
1208*必要に応じてターゲット依存部で検出するもの
1209・exchdrがプログラムの開始番地として正しくない場合(E_PAR)
1210
1211(8) 非タスクコンテキスト用のスタック領域に関する定義
1212
1213先の (5-1-7) でも説明したように,SSPカーネルでは,コンフィギュレータは
1214共有スタック領域のみ確保する.したがって,非タスクコンテキスト専用のスタック領域は
1215確保しない.このため,DEF_ICS の役割は,非タスクコンテキストが用いるスタック領域の
1216サイズを指定することのみとなる.また,DEF_ICS では先頭番地 istk として NULL のみ
1217受け付ける.NULL 以外の値を指定した場合はエラーとなる.
1218
1219※ 共有スタック領域に関する定義は (9) を参照すること.
1220
1221なお,非タスクコンテキスト用のスタックサイズに関する定義は,以下のように
1222DEF_ICS の有無にかかわらず常に生成される.
1223
1224(8-1) DEF_ICS がない場合
1225
1226システムコンフィギュレーションファイルに,静的API「DEF_ICS」が含まれて
1227いない場合には,次の行を生成する.
1228
1229#define TOPPERS_ISTKSZ DEFAULT_ISTKSZ
1230
1231(8-2) DEF_ICS がある場合
1232
1233以下では,システムコンフィギュレーションファイルに次の静的APIが含まれて
1234いる時に生成すべき情報について述べる.
1235
1236DEF_ICS({ istksz, istk });
1237
1238DEF_ICS では istk としてNULLのみ指定可能であり,出力には影響しない.
1239非タスクコンテキスト用スタック領域のサイズ istksz により次の行を生成する.
1240
1241#define TOPPERS_ISTKSZ (istksz)
1242
1243※共有スタック領域の定義については (9) を参照のこと.
1244
1245(8-3) エラー条件
1246
1247非タスクコンテキスト用のスタック領域に関するエラー条件は次の通りである.
1248
1249*パス2で検出するもの
1250・静的API「DEF_ICS」が複数ある(E_OBJ)
1251・istkszがスタック領域のサイズとして正しくない場合(E_PAR)
1252 - istksz が 0 の場合
1253・istkがスタック領域の先頭番地として正しくない場合(E_PAR)
1254 - NULL以外の値の場合
1255
1256*必要に応じてターゲット依存部で検出するもの
1257・istkszが小さすぎる場合(E_PAR)
1258
1259
1260(9) 共有スタック領域に関する定義
1261
1262先の (5-1-7) にて説明したように,SSPカーネルではタスクを含む全ての処理単位が
1263同じスタック領域を共用するように設計されている.そして共用されるスタック領域の
1264ことを「共有スタック領域」と呼ぶ.
1265
1266共有スタック領域の定義は DEF_STK を用いて行う.そして,コンフィギュレーションでは
1267共有スタック領域に関する定義は,DEF_STK の有無に関わらず常に生成される.
1268
1269以下では,DEF_STK の有無および与えられる引数の内容により,
1270どのように共有スタック領域の定義が生成されるかについて説明する.
1271
1272(9-1) DEF_STK がない場合に生成される定義
1273
1274システムコンフィギュレーションファイルに,静的API「DEF_STK」が含まれて
1275いない場合には,次の行を生成する.
1276
1277static STK_T _kernel_stack[COUNT_STK_T(TOPPERS_TSTKSZ+TOPPERS_ISTKSZ)];
1278#define TOPPERS_STK _kernel_stack
1279#define TOPPERS_STKSZ ROUND_STK_T(TOPPERS_TSTKSZ+TOPPERS_ISTKSZ)
1280
1281(9-2) DEF_STKがある場合にのみ生成される定義
1282
1283以下では,システムコンフィギュレーションファイルに次の静的APIが含まれて
1284いる時に生成すべき情報について述べる.
1285
1286DEF_STK({ stksz, stk });
1287
1288(9-2-1) stk が NULL の場合
1289
1290stk が NULL の場合には,指定されたサイズの共有スタック領域を確保し,
1291共有スタック領域の初期化情報を生成する.
1292具体的には,上記の静的APIに対して,次の行を生成する.
1293
1294static STK_T _kernel_stack[COUNT_STK_T(stksz)];
1295#define TOPPERS_STK _kernel_stack
1296#define TOPPERS_STKSZ ROUND_STK_T(stksz)
1297
1298(9-2-2) stk が NULL 以外の場合
1299
1300stk が NULL でない場合には,共有スタック領域の初期化情報を,次の形式で生成する.
1301
1302#define TOPPERS_STK (stk)
1303#define TOPPERS_STKSZ (stksz)
1304
1305(9-3) DEF_STK の有無に関係なく,常に生成される定義
1306
1307DEF_STKの有無によらず,次の定義を生成する.
1308
1309const SIZE _kernel_stksz = TOPPERS_STKSZ;
1310STK_T *const _kernel_stk = TOPPERS_STK;
1311
1312#ifdef TOPPERS_ISTKPT
1313STK_T *const _kernel_istkpt = TOPPERS_ISTKPT(TOPPERS_STK, TOPPERS_STKSZ);
1314#endif /* TOPPERS_ISTKPT */
1315
1316(9-4) エラー条件
1317
1318共有スタック領域に関するエラー条件は次の通りである.
1319
1320*パス2で検出するもの
1321・静的API「DEF_STK」が複数ある(E_OBJ)
1322・stkszがスタック領域のサイズとして正しくない場合(E_PAR)
1323 - stksz として 0 を指定した場合
1324 - ターゲット依存の値(CHECK_STKSZ_ALIGN)の倍数でない場合
1325 ※ このエラーチェックは,stk が NULL でない場合にのみ行う
1326・警告:stksz が,(TOPPERS_TSTKSZ+TOPPERS_ISTKSZ) よりも小さい場合
1327 ※ DEF_STK が存在し,stk が非NULLの場合.
1328 ※ マクロの値については (5-1-9), (8-1), (8-2) を参照のこと
1329
1330*パス3で検出するもの
1331・stkがスタック領域の先頭番地として正しくない場合(E_PAR)
1332 - ターゲット依存の値(CHECK_STACK_ALIGN)の倍数でない場合
1333 - NULLの場合(ターゲット依存,CHECK_STACK_NONNULL)
1334
1335(10) タイムイベント管理に関する定義
1336
1337タイムイベント管理に関連して,次の定義を生成する.
1338
1339(10-1) タイムイベントハンドラの数
1340
1341生成されたタイムイベントハンドラの数をマクロ定義するプリプロセッサ
1342ディレクテイブ(#define) を生成する.
1343
1344SSPカーネルではタイムイベントハンドラとして周期ハンドラおよびアラーム
1345ハンドラのみをサポートする.そのため,CRE_CYC および CRE_ALM の合計が
1346タイムイベントハンドラ数となる.
1347
1348具体的には,次のような記述を生成する.
1349
1350#define TNUM_TMEVT <タイムイベントハンドラの個数>
1351
1352(10-2) タイムイベントブロックのサイズの定義
1353
1354タイムイベントブロックの要素数を定義する変数を生成する.
1355タイムイベントブロックの要素数はタイムイベントハンドラの数に等しい.
1356
1357具体的には,次のような記述を生成する.
1358
1359const uint_t _kernel_tmevt_queue = <タイムイベントハンドラの個数>;
1360
1361(10-3) タイムイベントキューの定義
1362
1363タイムイベント管理のためのキューを生成する.キューは配列として実装されて
1364いる.キューの先頭を表現するための配列要素を確保するため,配列の要素数は
1365「タイムイベントハンドラの個数+1」となる.
1366
1367具体的には,次のような記述を生成する.
1368
1369extern QUEUE tmevt_queue[TNUM_TMEVT+1];
1370
1371(10-4) タイムイベント時間の定義
1372
1373タイムイベントハンドラの起動時刻を格納する変数は,次の形式とする.
1374
1375extern EVTTIM tmevt_time[TNUM_TMEVT];
1376
1377(10-5) タイムイベントのコールバックの定義
1378
1379タイムイベントハンドラのコールバック関数を格納する変数は,
1380次の形式とする.
1381
1382extern CBACK tmevt_callback[TNUM_TMEVT];
1383
1384(10-6) タイムイベントコールバックの引数の定義
1385
1386タイムイベントハンドラのコールバック関数の引数を格納する変数は,
1387次の形式とする.
1388
1389extern uintptr_t tmevt_arg[TNUM_TMEVT];
1390
1391(11) 各モジュールの初期化関数の定義
1392
1393各カーネルオブジェクトの管理,割込み管理,CPU例外ハンドラ管理の各機能を
1394初期化関数を順に呼び出す関数(_kernel_initialize_object)を生成する.次
1395の3つの初期化関数を除いては,使用しない機能の初期化関数は呼び出さない.
1396
1397_kernel_initialize_task();
1398_kernel_initialize_interrupt
1399_kernel_initialize_exception
1400
1401また次の初期化関数については,周期ハンドラまたはアラームハンドラを使用する
1402場合にのみ呼び出される.
1403_kernel_initialize_time_event();
1404
1405すべての機能を使った場合に生成される関数は次の通りである.
1406
1407void
1408_kernel_initialize_object(void)
1409{
1410 _kernel_initialize_time_event();
1411 _kernel_initialize_task();
1412 _kernel_initialize_interrupt();
1413 _kernel_initialize_exception();
1414 _kernel_initialize_cyclic();
1415 _kernel_initialize_alarm();
1416 _kernel_initialize_eventflag();
1417}
1418
1419
1420(12) 初期化ルーチンの実行関数の定義
1421
1422システムコンフィギュレーションファイル中に含まれる初期化ルーチンを追加
1423する静的API「ATT_INI」に対して,追加した初期化ルーチンを順に呼び出す関
1424数を生成する.具体的には,
1425
1426ATT_INI({ iniatr, exinf, inirtn });
1427
1428という静的APIに対して,
1429
1430(inirtn)((intptr_t)(exinf));
1431
1432を呼び出す関数を,_kernel_call_inirtnという名前で生成する.初期化ルーチ
1433ンを呼び出す順序は,システムコンフィギュレーションファイル中での静的
1434APIの順序に一致させる.
1435
1436例えば,
1437
1438ATT_INI({ TA_NULL, 0, timer_initialize });
1439ATT_INI({ TA_NULL, CONSOLE_PORTID, serial_initialize });
1440
1441という2つの静的APIがこの順序で記述された時に生成する関数は次の通りであ
1442る.
1443
1444void
1445_kernel_call_inirtn(void)
1446{
1447 ((INIRTN)(timer_initialize))((intptr_t)(0));
1448 ((INIRTN)(serial_initialize))((intptr_t)(CONSOLE_PORTID));
1449}
1450
1451(12-1) エラー条件
1452
1453初期化ルーチンに関するエラー条件は次の通りである.
1454
1455*パス2で検出するもの
1456・iniatrが(TA_NULL)でない場合(E_RSATR)
1457
1458*必要に応じてターゲット依存部で検出するもの
1459・inirtnがプログラムの開始番地として正しくない場合(E_PAR)
1460
1461(13) 終了処理ルーチンの実行関数の定義
1462
1463システムコンフィギュレーションファイル中に含まれる終了処理ルーチンを追
1464加する静的API「ATT_TER」に対して,追加した終了処理ルーチンを順に呼び出
1465す関数を生成する.具体的には,
1466
1467ATT_TER({ teratr, exinf, terrtn });
1468
1469という静的APIに対して,
1470
1471(terrtn)((intptr_t)(exinf));
1472
1473を呼び出す関数を,_kernel_call_terrtnという名前で生成する.終了処理ルー
1474チンを呼び出す順序は,システムコンフィギュレーションファイル中での静的
1475APIの逆順に一致させる.
1476
1477例えば,
1478
1479ATT_TER({ TA_NULL, 0, timer_terminate });
1480ATT_TER({ TA_NULL, CONSOLE_PORTID, serial_terminate });
1481
1482という2つの静的APIがこの順序で記述された時に生成する関数は次の通りであ
1483る.
1484
1485void
1486_kernel_call_terrtn(void)
1487{
1488 ((TERRTN)(serial_terminate))((intptr_t)(CONSOLE_PORTID));
1489 ((TERRTN)(timer_terminate))((intptr_t)(0));
1490}
1491
1492(13-1) エラー条件
1493
1494終了処理ルーチンに関するエラー条件は次の通りである.
1495
1496*パス2で検出するもの
1497・teratrが(TA_NULL)でない場合(E_RSATR)
1498
1499*必要に応じてターゲット依存部で検出するもの
1500・terrtnがプログラムの開始番地として正しくない場合(E_PAR)
1501
1502以上
Note: See TracBrowser for help on using the repository browser.