source: ssp_qb_r5f100le_cs/trunk/kernel/kernel.tf@ 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: 48.1 KB
Line 
1$ ======================================================================
2$
3$ TOPPERS/SSP Kernel
4$ Smallest Set Profile Kernel
5$
6$ Copyright (C) 2007 by TAKAGI Nobuhisa
7$ Copyright (C) 2007-2009 by Embedded and Real-Time Systems Laboratory
8$ Graduate School of Information Science, Nagoya Univ., JAPAN
9$ Copyright (C) 2010-2015 by Naoki Saito
10$ Nagoya Municipal Industrial Research Institute, JAPAN
11$
12$ 上記著作権者は,以下の (1)〜(4) の条件を満たす場合に限り,本ソフトウェ
13$ ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改変・
14$ 再配布(以下,利用と呼ぶ)することを無償で許諾する.
15$ (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作権
16$ 表示,この利用条件および下記の無保証規定が,そのままの形でソース
17$ コード中に含まれていること.
18$ (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使用
19$ できる形で再配布する場合には,再配布に伴うドキュメント(利用者マ
20$ ニュアルなど)に,上記の著作権表示,この利用条件および下記の無保
21$ 証規定を掲載すること.
22$ (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使用
23$ できない形で再配布する場合には,次のいずれかの条件を満たすこと.
24$ (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著作
25$ 権表示,この利用条件および下記の無保証規定を掲載すること.
26$ (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに報
27$ 告すること.
28$ (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損害
29$ からも,上記著作権者およびTOPPERSプロジェクトを免責すること.また,
30$ 本ソフトウェアのユーザまたはエンドユーザからのいかなる理由に基づ
31$ く請求からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
32$
33$ 本ソフトウェアは,無保証で提供されているものである.上記著作権者およ
34$ びTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的に対す
35$ る適合性も含めて,いかなる保証も行わない.また,本ソフトウェアの利用
36$ により直接的または間接的に生じたいかなる損害に関しても,その責任を負
37$ わない.
38$
39$ ======================================================================
40
41$ ログ出力
42$ 指定した数だけ行頭にタブをつけて表示する.
43$ コード及び出力の可読性を挙げるために使う.
44$ 引数 : ARGV[1] : 行頭に挿入するタブの数
45$ 返値 : 空文字列
46$ 注意 : RESULTを操作しているため,他の関数の出力を保存する前に呼び出すと上書きされる.
47$
48$FUNCTION LOG$
49 $FOREACH i RANGE(1,ARGV[1])$$TAB$$END$
50 $RESULT = {}$
51$END$
52
53$ =====================================================================
54$ 処理前のチェック
55$ =====================================================================
56
57$ タスクが1個以上存在することのチェック
58$IF !LENGTH(TSK.ID_LIST)$
59 $ERROR$$FORMAT("no task is registered")$$END$
60$END$
61
62$ =====================================================================
63$ kernel_cfg.h の生成
64$ =====================================================================
65
66$FILE "kernel_cfg.h"$
67
68/* kernel_cfg.h */$NL$
69#ifndef TOPPERS_KERNEL_CFG_H$NL$
70#define TOPPERS_KERNEL_CFG_H$NL$
71$NL$
72#define TNUM_TSKID $LENGTH(TSK.ID_LIST)$$NL$
73#define TNUM_FLGID $LENGTH(FLG.ID_LIST)$$NL$
74#define TNUM_DTQID $LENGTH(DTQ.ID_LIST)$$NL$
75#define TNUM_CYCID $LENGTH(CYC.ORDER_LIST)$$NL$
76#define TNUM_ALMID $LENGTH(ALM.ORDER_LIST)$$NL$
77$NL$
78
79$ // タスクIDを起動優先度(tskapri)の高い順に reallocate_tskapri へ割り当て,
80$ // 定義を kernel_cfg.h へ出力する.
81$tsk_apriorder_list={}$
82$tsk_epri_list={}$
83$tsk_index = 1$
84$FOREACH id SORT(TSK.ORDER_LIST, "TSK.ATSKPRI")$
85 $tsk_apriorder_list = APPEND(tsk_apriorder_list, TSK.TSKID[id])$
86 $reallocate_tskapri[TSK.TSKID[id]] = tsk_index$
87 #define $TSK.TSKID[id]$ $tsk_index$$NL$
88
89$ DEF_EPR で定義されていないタスクの実行時優先度が,起動優先度と同じになるようにする.
90 $tsk_epri_list = APPEND(tsk_epri_list, ALT(TSK.EXEPRI[TSK.TSKID[id]], TSK.ATSKPRI[TSK.TSKID[id]]))$
91 $tsk_index = tsk_index + 1$
92$END$
93$FOREACH id FLG.ID_LIST$
94 #define $id$ $+id$$NL$
95$END$
96$FOREACH id DTQ.ID_LIST$
97 #define $id$ $+id$$NL$
98$END$
99$FOREACH id CYC.ID_LIST$
100 #define $id$ $+id$$NL$
101$END$
102$FOREACH id ALM.ID_LIST$
103 #define $id$ $+id$$NL$
104$END$
105
106#endif /* TOPPERS_KERNEL_CFG_H */$NL$
107
108$ =====================================================================
109$ kernel_cfg.cの生成
110$ =====================================================================
111
112$FILE "kernel_cfg.c"$
113
114/* kernel_cfg.c */$NL$
115#include "kernel/kernel_int.h"$NL$
116#include "kernel_cfg.h"$NL$
117$NL$
118#ifndef TOPPERS_EMPTY_LABEL$NL$
119#define TOPPERS_EMPTY_LABEL(x,y) x y[0]$NL$
120#endif$NL$
121$NL$
122
123$ ---------------------------------------------------------------------
124$ インクルードディレクティブ(#include)
125$ ---------------------------------------------------------------------
126/*$NL$
127$SPC$* Include Directives (#include)$NL$
128$SPC$*/$NL$
129$NL$
130$INCLUDES$
131$NL$
132
133$ ---------------------------------------------------------------------
134$ オブジェクトのID番号を保持する変数
135$ ---------------------------------------------------------------------
136$IF USE_EXTERNAL_ID$
137 /*$NL$
138 $SPC$* Variables for Object ID$NL$
139 $SPC$*/$NL$
140 $NL$
141 $FOREACH id TSK.ID_LIST$
142 const ID $id$_id$SPC$=$SPC$$+id$;$NL$
143 $END$
144 $FOREACH id FLG.ID_LIST$
145 const ID $id$_id$SPC$=$SPC$$+id$;$NL$
146 $END$
147 $FOREACH id DTQ.ID_LIST$
148 const ID $id$_id$SPC$=$SPC$$+id$;$NL$
149 $END$
150 $FOREACH id CYC.ID_LIST$
151 const ID $id$_id$SPC$=$SPC$$+id$;$NL$
152 $END$
153 $FOREACH id ALM.ID_LIST$
154 const ID $id$_id$SPC$=$SPC$$+id$;$NL$
155 $END$
156$END$
157
158$ ---------------------------------------------------------------------
159$ トレースログマクロのデフォルト定義
160$ ---------------------------------------------------------------------
161/*$NL$
162$SPC$* Default Definitions of Trace Log Macros$NL$
163$SPC$*/$NL$
164$NL$
165#ifndef LOG_ISR_ENTER$NL$
166#define LOG_ISR_ENTER(intno)$NL$
167#endif /* LOG_ISR_ENTER */$NL$
168$NL$
169#ifndef LOG_ISR_LEAVE$NL$
170#define LOG_ISR_LEAVE(intno)$NL$
171#endif /* LOG_ISR_LEAVE */$NL$
172$NL$
173
174
175$ ---------------------------------------------------------------------
176$ タスクに関する出力
177$ ---------------------------------------------------------------------
178
179$
180$ 実行時優先度のコンフィギュレーションに成功したかどうか
181$
182$ DEF_EPR 処理中にエラーが発生した場合,この変数が0になる.
183$ DEF_EPR 処理中にエラーが発生したかどうかを判断して
184$ 特定処理の実行をブロックするために使用する.
185$
186$configurated_defepr_successfully = 1$
187
188/*$NL$
189$SPC$* Task Management Functions$NL$
190$SPC$*/$NL$
191$NL$
192
193$ タスクID番号の最大値
194const ID _kernel_tmax_tskid = (TMIN_TSKID + TNUM_TSKID - 1);$NL$
195$NL$
196
197$ ready_primap の初期値
198$init_rdypmap = 0$
199$tsk_index = 1$
200
201$ タスク属性.
202const ATR _kernel_tinib_tskatr[TNUM_TSKID] = {
203$JOINEACH tskid tsk_apriorder_list ","$
204$ // TA_ACT , TA_RSTR または TA_NULL である(E_RSATR)
205 $IF (TSK.TSKATR[tskid] & ~(TA_ACT | TA_RSTR | ALT(TARGET_TSKATR,0))) != 0$
206 $ERROR TSK.TEXT_LINE[tskid]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "tskatr", TSK.TSKATR[tskid], tskid, "CRE_TSK")$$END$
207 $END$
208
209 ($TSK.TSKATR[tskid]$)
210
211 $IF TSK.TSKATR[tskid] & TA_ACT$
212 $init_rdypmap = init_rdypmap + tsk_index$
213 $END$
214 $tsk_index = tsk_index << 1$
215$END$
216};$NL$
217
218const uint_t$TAB$_kernel_init_rdypmap = $init_rdypmap$U;$NL$
219
220$ 拡張情報(exinf). エラーはコンパイル時またはアプリのテストで検出するため,ここではしない.
221const intptr_t _kernel_tinib_exinf[TNUM_TSKID] = {
222$JOINEACH tskid tsk_apriorder_list ","$
223 (intptr_t)($TSK.EXINF[tskid]$)
224$END$
225};$NL$
226
227$ 起動番地(task).エラーはコンパイル時またはアプリのテストで検出するため,ここではしない.
228const TASK _kernel_tinib_task[TNUM_TSKID] = {
229$JOINEACH tskid tsk_apriorder_list ","$
230 ($TSK.TASK[tskid]$)
231$END$
232};$NL$
233
234$ 起動優先度(atskpri).
235$FOREACH tskid tsk_apriorder_list$
236$ // atskpri は TMIN_TPRI 以上,TMAX_TPRI 以下である.(E_PAR)
237 $IF !(TMIN_TPRI <= TSK.ATSKPRI[tskid] && TSK.ATSKPRI[tskid] <= TMAX_TPRI)$
238 $ERROR TSK.TEXT_LINE[tskid]$E_PAR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "atskpri", TSK.ATSKPRI[tskid], tskid, "CRE_TSK")$$END$
239 $END$
240
241$ // atskpri は重複がない.(E_PAR)
242 $FOREACH tskid2 tsk_apriorder_list$
243 $IF tskid != tskid2 && TSK.ATSKPRI[tskid] == TSK.ATSKPRI[tskid2] $
244 $ERROR TSK.TEXT_LINE[tskid]$E_PAR: $FORMAT(_("%1% of %2% (%3%) in %4% is duplicated"), "atskpri", tskid, TSK.ATSKPRI[tskid], "CRE_TSK")$$END$
245 $END$
246 $END$
247$END$
248
249$ 実行時優先度(exepri).
250const uint_t _kernel_tinib_epriority[TNUM_TSKID] = {
251$epri_allocated = 0$
252$tsk_index = 0$
253$JOINEACH tskid tsk_apriorder_list ","$
254 $epri = AT(tsk_epri_list, tsk_index)$
255
256$ // exepri は TMIN_TPRI 以上かつ TMAX_TPRI 以下である.(E_PAR)
257 $IF TMIN_TPRI > epri || TMAX_TPRI < epri$
258 $configurated_defepr_successfully = 0$
259 $ERROR TSK.TEXT_LINE[tskid]$E_PAR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "exepri", epri, tskid, "DEF_EPR")$$END$
260 $END$
261
262$ // exepri は atskpri 以下の値をもつ(優先度としては同じかそれより高い).(E_ILUSE)
263 $IF epri <= TMAX_TPRI && epri > TSK.ATSKPRI[tskid]$
264 $configurated_defepr_successfully = 0$
265 $ERROR TSK.TEXT_LINE[tskid]$E_ILUSE: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "exepri", epri, tskid, "DEF_EPR")$$END$
266 $END$
267
268$ // exepri の内部表現を決定し reallocate_tskepri に格納.
269 $FOREACH tskid2 tsk_apriorder_list $
270 $IF epri_allocated != 1 && epri <= TSK.ATSKPRI[tskid2]$
271 INT_PRIORITY($reallocate_tskapri[TSK.TSKID[tskid2]]$)
272 $reallocate_tskepri[tskid] = reallocate_tskapri[TSK.TSKID[tskid2]]$
273 $epri_allocated = 1$
274 $END$
275 $END$
276 $epri_allocated = 0$
277 $tsk_index = tsk_index + 1$
278$END$
279};$NL$$NL$
280
281$
282$ // 優先度割り当て結果を出力
283$
284/*$NL$
285$SPC$* Task priority configuration result:$NL$
286$FOREACH tskid SORT(TSK.ORDER_LIST, "TSK.ATSKPRI")$
287$SPC$* $TAB$$TSK.TSKID[tskid]$:$TAB$ IPRI = $reallocate_tskapri[TSK.TSKID[tskid]]$, EXEPRI = $reallocate_tskepri[tskid]$$NL$
288$END$
289$SPC$*/$NL$$NL$
290
291$
292$ タスクの最大スタック使用量の計算
293$
294
295$ スタックサイズに関するエラーチェック
296$FOREACH tskid TSK.ID_LIST$
297$ // stkszが0か,ターゲット定義の最小値(TARGET_MIN_STKSZ)よりも小さい場合(E_PAR)
298 $IF TSK.STKSZ[tskid] == 0 || (LENGTH(TARGET_MIN_STKSZ) &&
299 TSK.STKSZ[tskid] < TARGET_MIN_STKSZ)$
300 $ERROR TSK.TEXT_LINE[tskid]$E_PAR: $FORMAT(_("%1% `%2%\' of `%3%\' in %4% is too small"), "stksz", TSK.STKSZ[tskid], tskid, "CRE_TSK")$$END$
301 $END$
302$END$
303
304$
305$ 関数定義
306$
307$
308$ 関数1: 起動時優先度の低い順にソーティングするための比較関数
309$
310$FUNCTION compare_tskapri_rev$
311 $RESULT = reallocate_tskapri[ARGV[2]] - reallocate_tskapri[ARGV[1]]$
312$END$
313
314$
315$ 関数2: 指定したタスクに対するスタック使用量の最大を計算する関数
316$ 引数 : ARGV[1] : タスクID(内部表現, 起動時優先度の内部表現に等しい)
317$ 返値 : RESULT : 当該タスクに対するスタック使用量の最大値.
318$ この値は,当該タスクの実行開始から終了までの間に
319$ そのタスクに対するプリエンプトを考慮してスタック使用量を
320$ 計算した場合に,可能性のある組み合わせの中で最大となる値を返す.
321$
322$nest_level = 0$
323$
324$FUNCTION calc_stksz$
325$ // 変数リスト
326 $nest_level = nest_level + 1$
327 $arg[nest_level] = ARGV[1]$
328 $calculated_stack_size = 0$
329
330$ // 処理開始
331$SPC$* $LOG(nest_level-1)$Calculation start (Task ID = $arg[nest_level]$, StackSize[$arg[nest_level]$]=$TSK.STKSZ[arg[nest_level]]$)$NL$
332
333$ // 指定したタスクID のスタック計算が完了しているか
334 $IF LENGTH(done[arg[nest_level]]) == 0$
335
336$SPC$* $LOG(nest_level)$Task list with higher priority than $arg[nest_level]$ = $higher_pri_tsklist[arg[nest_level]]$$NL$
337
338$ // (1) 完了していない場合
339$ // 変数の初期化
340 $max_stksz[arg[nest_level]] = 0$
341 $higher_pri_maxstksz[arg[nest_level]] = 0$
342
343$ // 当該タスクID の実行時優先度より高い起動優先度を持つタスクが存在する場合
344 $IF LENGTH(higher_pri_tsklist[arg[nest_level]]) > 0$
345$ // それぞれの高優先度タスクに対し
346 $FOREACH id higher_pri_tsklist[arg[nest_level]]$
347$ // 再帰呼出すると変数が上書きされるため,保存しておく
348 $id_saved[nest_level] = id$
349$ // スタック計算を実行する
350 $calculated_stack_size = calc_stksz(id_saved[nest_level])$
351$ // 保存した変数を復帰
352 $id = id_saved[nest_level]$
353
354 $IF higher_pri_maxstksz[arg[nest_level]] < calculated_stack_size$
355$ // 記憶しておく
356 $higher_pri_maxstksz[arg[nest_level]] = calculated_stack_size$
357 $END$
358 $END$
359 $END$
360
361$SPC$* $LOG(nest_level)$higher_pri_maxstksz[$arg[nest_level]$] = $higher_pri_maxstksz[arg[nest_level]]$$NL$
362
363$ // 高優先度タスクのスタック使用量に,当該タスクの使用量を加算する
364 $max_stksz[arg[nest_level]] = higher_pri_maxstksz[arg[nest_level]] + TSK.STKSZ[arg[nest_level]]$
365
366$SPC$* $LOG(nest_level)$DONE(max_stksz[$arg[nest_level]$] = $max_stksz[arg[nest_level]]$)$NL$
367
368$ // 当該タスクIDに対しては計算を済ませたという記録を残しておく
369 $done[arg[nest_level]] = 1$
370
371 $ELSE$
372$ // (2) 計算が既に完了している場合,計算をスキップする.
373
374$SPC$* $LOG(nest_level)$SKIP(max_stksz[$arg[nest_level]$] = $max_stksz[arg[nest_level]]$)$NL$
375 $END$
376
377$ // 見積もりの最大値を返す
378 $RESULT = max_stksz[arg[nest_level]]$
379 $nest_level = nest_level - 1$
380$END$
381
382$
383$ 関数定義ここまで,ここからスタック計算処理の開始
384$
385
386$
387$ まずは木構造のデータ構造作成
388$
389$FOREACH id LSORT(tsk_apriorder_list, "compare_tskapri_rev")$
390
391$ // 各タスク毎に,その実行時優先度よりも高い起動時優先度を持つタスクのリストを作る.
392$ // それはプリエンプトされる可能性のあるタスクの一覧となる.
393 $FOREACH id2 LSORT(tsk_apriorder_list, "compare_tskapri_rev")$
394 $IF reallocate_tskepri[id] > reallocate_tskapri[id2]$
395 $higher_pri_tsklist[id] = APPEND(higher_pri_tsklist[id], id2)$
396 $END$
397 $END$
398
399$ // プリエンプトする・される関係を示す木構造の根(root)となるタスクの探索.
400$ // 対象タスク(id)の起動時優先度(reallocate_tskapri[id])より低い
401$ // (値としては大きい)起動時優先度をもつタスクの higher_pri_tsklist に,
402$ // 対象タスク(id) が含まれなければ,根となる.
403 $is_root = 1$
404 $FOREACH id2 LSORT(tsk_apriorder_list, "compare_tskapri_rev")$
405 $IF (is_root == 1) && (reallocate_tskapri[id] < reallocate_tskapri[id2])$
406 $IF LENGTH(FIND(higher_pri_tsklist[id2], id)) > 0$
407 $is_root = 0$
408 $END$
409 $END$
410 $END$
411$ // 根(root)となるタスクならば,リストへ追加
412 $IF is_root == 1$
413 $root_apri = APPEND(root_apri, id)$
414 $END$
415$END$
416
417$
418$ 出力開始
419$
420
421/* $NL$
422$SPC$* Task Stack Size Estimation: $NL$
423$SPC$* $NL$
424
425$ // 根となる各タスクに対して,その最大タスク使用量を計算し,リストへ追加する.
426$FOREACH root_id root_apri$
427 $stksz_estimated = APPEND(stksz_estimated, calc_stksz(root_id))$
428$END$
429
430$ // タスクのスタック使用量の最大値を決定
431$ // リスト中の要素の最大値がタスクの最大スタック使用量となる.
432$max_tsk_stksz = 0$
433$FOREACH size stksz_estimated$
434 $IF size > max_tsk_stksz$
435 $max_tsk_stksz = size$
436 $END$
437$END$
438
439$ // 確認
440$SPC$* List of Estimated Total Stack Sizes of Tasks = $stksz_estimated$$NL$
441$SPC$* Estimated Maximum Total Stack Size of Tasks = $max_tsk_stksz$$NL$
442$SPC$*/ $NL$
443#define TOPPERS_TSTKSZ ($max_tsk_stksz$)$NL$$NL$
444
445
446$ 全ての処理単位のスタックは共有される.
447$ そのため,スタックサイズに関するチェックは
448$ 共有スタック設定のところでまとめて行う.
449
450$ スタックの先頭番地(stk).
451$FOREACH tskid tsk_apriorder_list$
452$ // 常に NULL である.(E_PAR)
453 $IF !EQ(TSK.STK[tskid], "NULL")$
454 $ERROR TSK.TEXT_LINE[tskid]$E_PAR: $FORMAT(("'%1%' of %2% must be NULL."), "stk", "CRE_TSK")$$END$
455 $END$
456$END$
457
458$ ---------------------------------------------------------------------
459$ イベントフラグ
460$ ---------------------------------------------------------------------
461/*$NL$
462$SPC$* Eventflag Functions$NL$
463$SPC$*/$NL$
464$NL$
465
466$ エントリが (UINT8_MAX - TMIN_FLGID)個より多い場合は,エラーとする --> 現時点ではコメントアウト
467$ $IF LENGTH(ALM.ORDER_LIST) > (UINT8_MAX - TMIN_FLGID)$
468$ $ERROR$$FORMAT("The number of CRE_FLG must be equal to or less than (UINT8_MAX - TMIN_FLGID).")$$END$
469$ $END$
470
471$ イベントフラグID番号の最大値
472const ID _kernel_tmax_flgid = (TMIN_FLGID + TNUM_FLGID - 1);$NL$
473$NL$
474
475$ // iflgptnがFLGPTNに格納できない場合(E_PAR)
476$FOREACH flgid FLG.ORDER_LIST$
477 $IF (FLG.IFLGPTN[flgid] & ~((1 << TBIT_FLGPTN) - 1)) != 0$
478 $ERROR FLG.TEXT_LINE[flgid]$E_PAR: $FORMAT(_("too large %1% `%2%\' of `%3%\' in %4%"), "iflgptn", FLG.IFLGPTN[flgid], flgid, "CRE_FLG")$$END$
479 $END$
480$END$
481
482$ イベントフラグ初期化ブロックの生成
483$IF LENGTH(FLG.ID_LIST)$
484
485$ イベントフラグ属性
486 const ATR _kernel_flginib_atr[TNUM_FLGID] = {
487 $JOINEACH flgid FLG.ORDER_LIST ","$
488$ // flgatrが([TA_CLR])でない場合(E_RSATR)
489 $IF (FLG.FLGATR[flgid] & ~(TA_CLR)) != 0$
490 $ERROR FLG.TEXT_LINE[flgid]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "flgatr", FLG.FLGATR[flgid], flgid, "CRE_FLG")$$END$
491 $END$
492 ($FLG.FLGATR[flgid]$)
493 $END$
494 };$NL$
495
496$ イベントフラグパターンの初期値
497 const FLGPTN _kernel_flginib_iflgptn[TNUM_FLGID] = {
498 $JOINEACH flgid FLG.ORDER_LIST ","$
499 ($FLG.IFLGPTN[flgid]$)
500 $END$
501 };$NL$
502
503$ // イベントフラグの現在のフラグパターンを格納する変数
504 FLGPTN _kernel_flgcb_flgptn[TNUM_FLGID];$NL$
505$ELSE$
506 TOPPERS_EMPTY_LABEL(const ATR, _kernel_flginib_atr);$NL$
507 TOPPERS_EMPTY_LABEL(const FLGPTN, _kernel_flginib_iflgptn);$NL$
508 TOPPERS_EMPTY_LABEL(FLGPTN, _kernel_flgcb_flgptn);$NL$
509$END$
510$NL$
511
512$ ---------------------------------------------------------------------
513$ データキュー
514$ ---------------------------------------------------------------------
515/*$NL$
516$SPC$* Dataqueue Functions$NL$
517$SPC$*/$NL$
518$NL$
519
520$ データキューID番号の最大値
521const ID _kernel_tmax_dtqid = (TMIN_DTQID + TNUM_DTQID - 1);$NL$
522$NL$
523
524$IF LENGTH(DTQ.ID_LIST)$
525 $FOREACH dtqid DTQ.ORDER_LIST$
526$ // dtqatrが TA_NULL でない場合(E_RSATR)
527 $IF (DTQ.DTQATR[dtqid] != TA_NULL) $
528 $ERROR DTQ.TEXT_LINE[dtqid]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "dtqatr", DTQ.DTQATR[dtqid], dtqid, "CRE_DTQ")$$END$
529 $END$
530
531$ // dtqmbがNULLでない場合(E_NOSPT)
532 $IF !EQ(DTQ.DTQMB[dtqid], "NULL")$
533 $ERROR DTQ.TEXT_LINE[dtqid]$E_NOSPT: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "dtqmb", DTQ.DTQMB[dtqid], dtqid, "CRE_DTQ")$$END$
534 $END$
535
536$ // dtqcntが0である場合
537 $IF EQ(+DTQ.DTQCNT[dtqid], 0)$
538 $ERROR DTQ.TEXT_LINE[dtqid]$E_PAR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "dtqmb", DTQ.DTQCNT[dtqid], dtqid, "CRE_DTQ")$$END$
539 $END$
540
541
542$ // データキュー領域
543 $IF DTQ.DTQCNT[dtqid]$
544 static intptr_t _kernel_dtqmb_$dtqid$[$DTQ.DTQCNT[dtqid]$];$NL$
545 $END$
546 $END$
547
548$ // データキュー初期化ブロックの生成(属性)
549 const ATR _kernel_dtqinib_atr[TNUM_DTQID] = {
550 $JOINEACH dtqid DTQ.ORDER_LIST ",\n"$
551 $SPC$($DTQ.DTQATR[dtqid]$)
552 $END$
553 };$NL$
554 $NL$
555
556$ // データキュー初期化ブロックの生成(サイズ)
557 const uint8_t _kernel_dtqinib_size[TNUM_DTQID] = {
558 $JOINEACH dtqid DTQ.ORDER_LIST ",\n"$
559 $SPC$($DTQ.DTQCNT[dtqid]$)
560 $END$
561 };$NL$
562 $NL$
563
564$ // データキュー初期化ブロックの生成(管理領域)
565 intptr_t * const _kernel_dtqinib_data[TNUM_DTQID] = {
566 $JOINEACH dtqid DTQ.ORDER_LIST ",\n"$
567 $IF DTQ.DTQCNT[dtqid]$(_kernel_dtqmb_$dtqid$)$ELSE$NULL$END$
568 $END$
569 };$NL$
570 $NL$
571
572$ // データキューコントロールブロック
573 uint8_t _kernel_dtqcb_count[TNUM_DTQID];$NL$
574 uint8_t _kernel_dtqcb_head[TNUM_DTQID];$NL$
575 uint8_t _kernel_dtqcb_tail[TNUM_DTQID];$NL$
576$ELSE$
577 TOPPERS_EMPTY_LABEL(const ATR, _kernel_dtqinib_atr);$NL$
578 TOPPERS_EMPTY_LABEL(intptr_t * const, _kernel_dtqinib_data);$NL$
579 TOPPERS_EMPTY_LABEL(const uint8_t, _kernel_dtqinib_size);$NL$
580 TOPPERS_EMPTY_LABEL(uint8_t, _kernel_dtqcb_count);$NL$
581 TOPPERS_EMPTY_LABEL(uint8_t, _kernel_dtqcb_head);$NL$
582 TOPPERS_EMPTY_LABEL(uint8_t, _kernel_dtqcb_tail);$NL$
583$END$
584$NL$
585
586
587$ ---------------------------------------------------------------------
588$ 割込み管理機能
589$ ---------------------------------------------------------------------
590/*$NL$
591$SPC$* Interrupt Management Functions$NL$
592$SPC$*/$NL$
593$NL$
594
595$ // INTNO_ATTISR_VALID の要素が重複していないかどうかのチェック
596$i = 0$
597$FOREACH intno INTNO_ATTISR_VALID$
598 $j = 0$
599 $FOREACH intno2 INTNO_ATTISR_VALID$
600 $IF i < j && intno == intno2$
601 $ERROR$ $FORMAT(_("intno (%1%) of INTNO_ATTISR_VALID is duplicated"), intno)$$END$
602 $END$
603 $j = j + 1$
604 $END$
605 $i = i + 1$
606$END$
607
608$ // INHNO_ATTISR_VALID の要素が重複していないかどうかのチェック
609$i = 0$
610$FOREACH intno INHNO_ATTISR_VALID$
611 $j = 0$
612 $FOREACH intno2 INHNO_ATTISR_VALID$
613 $IF i < j && intno == intno2$
614 $ERROR$ $FORMAT(_("intno (%1%) of INHNO_ATTISR_VALID is duplicated"), intno)$$END$
615 $END$
616 $j = j + 1$
617 $END$
618 $i = i + 1$
619$END$
620
621
622$ // ATT_ISR で使用可能な割込み番号と,それに対応する割込みハンドラ番号の数が同じかどうか
623$ // 各リストの要素は重複していないことを前提としている.
624$IF LENGTH(INTNO_ATTISR_VALID) != LENGTH(INHNO_ATTISR_VALID)$
625 $ERROR$length of `INTNO_ATTISR_VALID' is different from length of `INHNO_ATTISR_VALID'$END$
626$END$
627
628
629$ // 割込み番号と割込みハンドラ番号の変換テーブルの作成
630$ // 割込み番号のリストと割込みハンドラ番号のリストは対応する要素が同じ順番で
631$ // 現れるように並べられていることを前提とする.
632$i = 0$
633$FOREACH intno INTNO_ATTISR_VALID$
634
635$ // INTNO_ATTISR_VALID に含まれる値は INTNO_CFGINT_VALID にも含まれるべきである.
636$ // INTNO_ATTISR_VALID は INTNO_CFGINT_VALID の部分集合になるはず.
637 $IF LENGTH(FIND(INTNO_CFGINT_VALID, intno)) == 0$
638 $ERROR$all elements of `INTNO_ATTISR_VALID' must be included in `INTNO_CFGINT_VALID'$END$
639 $END$
640
641 $inhno = AT(INHNO_ATTISR_VALID, i)$
642 $INHNO[intno] = inhno$
643 $INTNO[inhno] = intno$
644 $i = i + 1$
645$END$
646
647
648$ // INTNO_CFGINT_VALID の要素が INTNO_VALID に含まれるかどうかのチェック
649$ // INTNO_CFGINT_VALID は INTNO_VALID の部分集合になるはず.
650$FOREACH intno INTNO_CFGINT_VALID$
651 $IF LENGTH(FIND(INTNO_VALID, intno)) == 0$
652 $ERROR$all elements of `INTNO_CFGINT_VALID' must be included in `INTNO_VALID'$END$
653 $END$
654$END$
655
656
657$ // INHNO_ATTISR_VALID の要素が INHNO_VALID に含まれるかどうかのチェック
658$ // INHNO_ATTISR_VALID は INHNO_VALID の部分集合になるはず.
659$FOREACH inhno INHNO_ATTISR_VALID$
660 $IF LENGTH(FIND(INHNO_VALID, inhno)) == 0$
661 $ERROR$all elements of `INHNO_ATTISR_VALID' must be included in `INHNO_VALID'$END$
662 $END$
663$END$
664
665
666$ // 割込み要求ラインに関するエラーチェック
667$i = 0$
668$FOREACH intno INT.ORDER_LIST$
669$ // intnoがCFG_INTに対する割込み番号として正しくない場合(E_PAR)
670 $IF !LENGTH(FIND(INTNO_CFGINT_VALID, INT.INTNO[intno]))$
671 $ERROR INT.TEXT_LINE[intno]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "intno", INT.INTNO[intno], "CFG_INT")$$END$
672 $END$
673
674$ // intnoがCFG_INTによって設定済みの場合(E_OBJ)
675 $j = 0$
676 $FOREACH intno2 INT.ORDER_LIST$
677 $IF INT.INTNO[intno] == INT.INTNO[intno2] && j < i$
678 $ERROR INT.TEXT_LINE[intno]$E_OBJ: $FORMAT(_("%1% `%2%\' in %3% is duplicated"), "intno", INT.INTNO[intno], "CFG_INT")$$END$
679 $END$
680 $j = j + 1$
681 $END$
682
683$ // intatrが TA_ENAINT, TA_EDGE, またはその他ターゲットで利用可能な属性のいずれでもない場合(E_RSATR)
684 $IF (INT.INTATR[intno] & ~(TA_ENAINT|TA_EDGE|ALT(TARGET_INTATR,0))) != 0$
685 $ERROR INT.TEXT_LINE[intno]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of %3% `%4%\' in %5%"), "intatr", INT.INTATR[intno], "intno", INT.INTNO[intno], "CFG_INT")$$END$
686 $END$
687
688$ // intpriがCFG_INTに対する割込み優先度として正しくない場合(E_PAR)
689 $IF !LENGTH(FIND(INTPRI_CFGINT_VALID, INT.INTPRI[intno]))$
690 $ERROR INT.TEXT_LINE[intno]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "intpri", INT.INTPRI[intno], "CFG_INT")$$END$
691 $END$
692
693$ // カーネル管理の割込みとして固定されている割込みに,TMIN_INTPRI よりも小さい値が指定された場合(E_OBJ)
694 $IF LENGTH(FIND(INTNO_FIX_KERNEL, intno))$
695 $IF INT.INTPRI[intno] < TMIN_INTPRI$
696 $ERROR INT.TEXT_LINE[intno]$E_OBJ: $FORMAT(_("%1% `%2%\' must not have higher priority than %3%"), "intno", INT.INTNO[intno], "TMIN_INTPRI")$$END$
697 $END$
698 $END$
699
700$ // カーネル管理外の割込みとして固定されている割込みに,TMIN_INTPRI よりも小さい値が指定されなかった場合(E_OBJ)
701 $IF LENGTH(FIND(INTNO_FIX_NONKERNEL, intno))$
702 $IF INT.INTPRI[intno] >= TMIN_INTPRI$
703 $ERROR INT.TEXT_LINE[intno]$E_OBJ: $FORMAT(_("%1% `%2%\' must have higher priority than %3%"), "intno", INT.INTNO[intno], "TMIN_INTPRI")$$END$
704 $END$
705 $END$
706 $i = i + 1$
707$END$
708
709
710$ 割込みハンドラに関するエラーチェック
711$i = 0$
712$FOREACH inhno INH.ORDER_LIST$
713$ // 割込みハンドラ番号(inhno)が正しくない場合(E_PAR)
714 $IF !LENGTH(FIND(INHNO_DEFINH_VALID, INH.INHNO[inhno]))$
715 $ERROR INH.TEXT_LINE[inhno]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "inhno", INH.INHNO[inhno], "DEF_INH")$$END$
716 $END$
717
718$ // 同じ割込みハンドラ番号に対するDEF_INHが複数存在する場合(E_OBJ)
719 $j = 0$
720 $FOREACH inhno2 INH.ORDER_LIST$
721 $IF INH.INHNO[inhno] == INH.INHNO[inhno2] && j < i$
722 $ERROR INH.TEXT_LINE[inhno]$E_OBJ: $FORMAT(_("%1% `%2%\' in %3% is duplicated"), "inhno", INH.INHNO[inhno], "DEF_INH")$$END$
723 $END$
724 $j = j + 1$
725 $END$
726
727$ // 割込みハンドラ属性(inhatr) が TA_NULL, TA_NONKERNEL, 及びその他ターゲット依存で利用可能な属性のいずれでもない(E_RSATR)
728 $IF (INH.INHATR[inhno] & ~(TA_NONKERNEL|ALT(TARGET_INHATR,0))) != 0$
729 $ERROR INH.TEXT_LINE[inhno]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of %3% `%4%\' in %5%"), "inhatr", INH.INHATR[inhno], "inhno", INH.INHNO[inhno], "DEF_INH")$$END$
730 $END$
731
732$ // カーネル管理に固定されている割込みハンドラに,TA_NONKERNEL 属性が設定されている(E_RSATR)
733 $IF LENGTH(FIND(INHNO_FIX_KERNEL, inhno))$
734 $IF (INH.INHATR[inhno] & TA_NONKERNEL) != 0$
735 $ERROR INH.TEXT_LINE[inhno]$E_RSATR: $FORMAT(_("%1% `%2%\' must not be non-kernel interrupt"), "inhno", INH.INHNO[inhno])$$END$
736 $END$
737 $END$
738
739$ // カーネル管理外に固定されている割込みハンドラに,TA_NONKERNEL 属性が設定されていない(E_RSATR)
740 $IF LENGTH(FIND(INHNO_FIX_NONKERNEL, inhno))$
741 $IF (INH.INHATR[inhno] & TA_NONKERNEL) == 0$
742 $ERROR INH.TEXT_LINE[inhno]$E_RSATR: $FORMAT(_("%1% `%2%\' must be non-kernel interrupt"), "inhno", INH.INHNO[inhno])$$END$
743 $END$
744 $END$
745
746
747$ // 割込み番号と1対1対応する割込みハンドラ番号(ATT_ISRで指定可能な割込みハンドラ番号)は,以下のチェックも行う.
748$ // INHNO_ATTISR_VALID に含まれない割込みハンドラ番号はチェックされないことになる.
749 $IF LENGTH(INTNO[INH.INHNO[inhno]]) > 0$
750 $intno = INTNO[INH.INHNO[inhno]]$
751
752$ // 割込みハンドラ登録先の割込み要求ラインが属性設定されていない(CFG_INTがない)(E_OBJ)
753 $IF !LENGTH(INT.INTNO[intno])$
754 $ERROR INH.TEXT_LINE[inhno]$E_OBJ: $FORMAT(_("%1% `%2%\' corresponding to %3% `%4%\' is not configured with %5%"), "intno", INT.INTNO[intno], "inhno", INH.INHNO[inhno], "CFG_INT")$$END$
755 $ELSE$
756 $IF (INH.INHATR[inhno] & TA_NONKERNEL) == 0$
757$ // inhatrにTA_NONKERNELが指定されておらず,inhnoに対応
758$ // するintnoに対してCFG_INTで設定された割込み優先度が
759$ // TMIN_INTPRIよりも小さい場合(E_OBJ)
760 $IF INT.INTPRI[intno] < TMIN_INTPRI$
761 $ERROR INT.TEXT_LINE[intno]$E_OBJ: $FORMAT(_("%1% `%2%\' configured for %3% `%4%\' is higher than %5%"), "intpri", INT.INTPRI[intno], "inhno", INH.INHNO[inhno], "TMIN_INTPRI")$$END$
762 $END$
763 $ELSE$
764$ // inhatrにTA_NONKERNELが指定されており,inhnoに対応
765$ // するintnoに対してCFG_INTで設定された割込み優先度が
766$ // TMIN_INTPRI以上である場合(E_OBJ)
767 $IF INT.INTPRI[intno] >= TMIN_INTPRI$
768 $ERROR INT.TEXT_LINE[intno]$E_OBJ: $FORMAT(_("%1% `%2%\' configured for %3% `%4%\' is lower than or equal to %5%"), "intpri", INT.INTPRI[intno], "inhno", INH.INHNO[inhno], "TMIN_INTPRI")$$END$
769 $END$
770 $END$
771 $END$
772 $END$
773 $i = i + 1$
774$END$
775
776$ 割込みサービスルーチン(ISR)に関するエラーチェックと割込みハンドラの生成
777$FOREACH order ISR.ORDER_LIST$
778$ // isratrが(TA_NULL)でない場合(E_RSATR)
779 $IF (ISR.ISRATR[order] & ~ALT(TARGET_ISRATR,0)) != 0$
780 $ERROR ISR.TEXT_LINE[order]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of %3% `%4%\' in %5%"), "isratr", ISR.ISRATR[order], "isr", ISR.ISR[order], "ATT_ISR")$$END$
781 $END$
782
783$ // intnoがATT_ISRに対する割込み番号として正しくない場合(E_PAR)
784 $IF !LENGTH(FIND(INTNO_ATTISR_VALID, ISR.INTNO[order]))$
785 $ERROR ISR.TEXT_LINE[order]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "intno", ISR.INTNO[order], "ATT_ISR")$$END$
786 $END$
787
788$ // (TMIN_ISRPRI <= isrpri && isrpri <= TMAX_ISRPRI)でない場合(E_PAR)
789 $IF !(TMIN_ISRPRI <= ISR.ISRPRI[order] && ISR.ISRPRI[order] <= TMAX_ISRPRI)$
790 $ERROR ISR.TEXT_LINE[order]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "isrpri", ISR.ISRPRI[order], "ATT_ISR")$$END$
791 $END$
792$END$
793
794
795$FOREACH intno INTNO_ATTISR_VALID$
796 $inhno = INHNO[intno]$
797
798$ // 割込み番号intnoに対して登録されたISRのリストの作成
799 $isr_order_list = {}$
800 $FOREACH order ISR.ORDER_LIST$
801 $IF ISR.INTNO[order] == intno$
802 $isr_order_list = APPEND(isr_order_list, order)$
803 $order_for_error = order$
804 $END$
805 $END$
806
807$ // 割込み番号intnoに対して登録されたISRが存在する場合
808 $IF LENGTH(isr_order_list) > 0$
809$ // intnoに対応するinhnoに対してDEF_INHがある場合(E_OBJ)
810 $IF LENGTH(INH.INHNO[inhno])$
811 $ERROR ISR.TEXT_LINE[order_for_error]$E_OBJ: $FORMAT(_("%1% `%2%\' in %3% is duplicated with %4% `%5%\'"), "intno", ISR.INTNO[order_for_error], "ATT_ISR", "inhno", INH.INHNO[inhno])$$END$
812 $END$
813
814$ // intnoに対するCFG_INTがない場合(E_OBJ)
815 $IF !LENGTH(INT.INTNO[intno])$
816 $ERROR ISR.TEXT_LINE[order_for_error]$E_OBJ: $FORMAT(_("%1% `%2%\' is not configured with %3%"), "intno", ISR.INTNO[order_for_error], "CFG_INT")$$END$
817 $ELSE$
818$ // intnoに対してCFG_INTで設定された割込み優先度がTMIN_INTPRI
819$ // よりも小さい場合(E_OBJ)
820 $IF INT.INTPRI[intno] < TMIN_INTPRI$
821 $ERROR INT.TEXT_LINE[intno]$E_OBJ: $FORMAT(_("%1% `%2%\' configured for %3% `%4%\' is higher than %5%"), "intpri", INT.INTPRI[intno], "intno", ISR.INTNO[order_for_error], "TMIN_INTPRI")$$END$
822 $END$
823 $END$
824
825$ // DEF_INH(inhno, { TA_NULL, _kernel_inthdr_<intno> } );
826 $INH.INHNO[inhno] = inhno$
827 $INH.INHATR[inhno] = VALUE("TA_NULL", 0)$
828 $INH.INTHDR[inhno] = CONCAT("_kernel_inthdr_", intno)$
829 $INH.ORDER_LIST = APPEND(INH.ORDER_LIST, inhno)$
830
831$ // ISR用の割込みハンドラ
832 void$NL$
833 _kernel_inthdr_$intno$(void)$NL$
834 {$NL$
835 $IF LENGTH(isr_order_list) > 1$
836 $TAB$PRI saved_ipm;$NL$
837 $NL$
838 $TAB$i_begin_int($intno$);$NL$
839 $TAB$saved_ipm = i_get_ipm();$NL$
840 $ELSE$
841 $TAB$i_begin_int($intno$);$NL$
842 $END$
843$ // ISRを優先度順に呼び出す
844 $JOINEACH order SORT(isr_order_list, "ISR.ISRPRI") "\tif (i_sense_lock()) {\n\t\ti_unlock_cpu();\n\t}\n\ti_set_ipm(saved_ipm);\n"$
845 $TAB$LOG_ISR_ENTER($intno$);$NL$
846 $TAB$((ISR)($ISR.ISR[order]$))((intptr_t)($ISR.EXINF[order]$));$NL$
847 $TAB$LOG_ISR_LEAVE($intno$);$NL$
848 $END$
849 $TAB$i_end_int($intno$);$NL$
850 }$NL$
851 $END$
852$END$
853$NL$
854
855$
856$ 割込み管理機能のための標準的な初期化情報の生成
857$
858$ 割込みハンドラの初期化に必要な情報
859$IF !OMIT_INITIALIZE_INTERRUPT || ALT(USE_INHINIB_TABLE,0)$
860
861$ 割込みハンドラ数
862#define TNUM_INHNO $LENGTH(INH.ORDER_LIST)$$NL$
863const uint_t _kernel_tnum_inhno = TNUM_INHNO;$NL$
864$NL$
865$FOREACH inhno INH.ORDER_LIST$
866 INTHDR_ENTRY($INH.INHNO[inhno]$, $+INH.INHNO[inhno]$, $INH.INTHDR[inhno]$)$NL$$NL$
867$END$
868
869$ 割込みハンドラ初期化テーブル
870$IF LENGTH(INH.ORDER_LIST)$
871 const INHNO _kernel_inhinib_inhno[TNUM_INHNO] = {
872 $JOINEACH inhno INH.ORDER_LIST ","$
873 ($INH.INHNO[inhno]$)
874 $END$
875 };$NL$
876
877 const ATR _kernel_inhinib_inhatr[TNUM_INHNO] = {
878 $JOINEACH inhno INH.ORDER_LIST ","$
879 ($INH.INHATR[inhno]$)
880 $END$
881 };$NL$
882
883 const FP _kernel_inhinib_entry[TNUM_INHNO] = {
884 $JOINEACH inhno INH.ORDER_LIST ","$
885 (FP)(INT_ENTRY($INH.INHNO[inhno]$, $INH.INTHDR[inhno]$))
886 $END$
887 };$NL$
888$ELSE$
889 TOPPERS_EMPTY_LABEL(const INHNO, _kernel_inhinib_inhno);$NL$
890 TOPPERS_EMPTY_LABEL(const ATR, _kernel_inhinib_inhatr);$NL$
891 TOPPERS_EMPTY_LABEL(const FP, _kernel_inhinib_entry);$NL$
892$END$$NL$
893$END$
894
895$ 割込み要求ラインの初期化に必要な情報
896$IF !OMIT_INITIALIZE_INTERRUPT || ALT(USE_INTINIB_TABLE,0)$
897
898$ 割込み要求ライン数
899#define TNUM_INTNO $LENGTH(INT.ORDER_LIST)$$NL$
900const uint_t _kernel_tnum_intno = TNUM_INTNO;$NL$
901$NL$
902
903$ 割込み要求ライン初期化テーブル
904$IF LENGTH(INT.ORDER_LIST)$
905 const INTNO _kernel_intinib_intno[TNUM_INTNO] = {
906 $JOINEACH intno INT.ORDER_LIST ","$
907 ($INT.INTNO[intno]$)
908 $END$
909 };$NL$
910
911 const ATR _kernel_intinib_intatr[TNUM_INTNO] = {
912 $JOINEACH intno INT.ORDER_LIST ","$
913 ($INT.INTATR[intno]$)
914 $END$
915 };$NL$
916
917 const PRI _kernel_intinib_intpri[TNUM_INTNO] = {
918 $JOINEACH intno INT.ORDER_LIST ","$
919 ($INT.INTPRI[intno]$)
920 $END$
921 };$NL$
922$ELSE$
923 TOPPERS_EMPTY_LABEL(const INTNO, _kernel_intinib_intno);$NL$
924 TOPPERS_EMPTY_LABEL(const ATR, _kernel_intinib_intatr);$NL$
925 TOPPERS_EMPTY_LABEL(const PRI, _kernel_intinib_intpri);$NL$
926$END$
927$NL$
928$END$
929
930$ ---------------------------------------------------------------------
931$ CPU例外ハンドラ
932$ ---------------------------------------------------------------------
933/*$NL$
934$SPC$* CPU Exception Handler$NL$
935$SPC$*/$NL$
936$NL$
937
938$ // EXCNO_DEFEXC_VALID の要素が EXCNO_VALID に含まれるかどうかのチェック
939$ // EXCNO_DEFEXC_VALID は EXCNO_VALID の部分集合になるはず.
940$FOREACH excno EXCNO_DEFEXC_VALID$
941 $IF LENGTH(FIND(EXCNO_VALID, excno)) == 0$
942 $ERROR$all elements of `EXCNO_DEFEXC_VALID' must be included in `EXCNO_VALID'$END$
943 $END$
944$END$
945
946
947$ CPU例外ハンドラに関するエラーチェック
948$i = 0$
949$FOREACH excno EXC.ORDER_LIST$
950$ // excnoがDEF_EXCに対するCPU例外ハンドラ番号として正しくない場合(E_PAR)
951 $IF !LENGTH(FIND(EXCNO_DEFEXC_VALID, EXC.EXCNO[excno]))$
952 $ERROR EXC.TEXT_LINE[excno]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "excno", EXC.EXCNO[excno], "DEF_EXC")$$END$
953 $END$
954
955$ // excnoがDEF_EXCによって設定済みの場合(E_OBJ)
956 $j = 0$
957 $FOREACH excno2 EXC.ORDER_LIST$
958 $IF EXC.EXCNO[excno] == EXC.EXCNO[excno2] && j < i$
959 $ERROR EXC.TEXT_LINE[excno]$E_OBJ: $FORMAT(_("%1% `%2%\' in %3% is duplicated"), "excno", EXC.EXCNO[excno], "DEF_EXC")$$END$
960 $END$
961 $j = j + 1$
962 $END$
963
964$ // excatrが(TA_NULL)でない場合(E_RSATR)
965 $IF (EXC.EXCATR[excno] & ~ALT(TARGET_EXCATR,0)) != 0$
966 $ERROR EXC.TEXT_LINE[excno]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of %3% `%4%\' in %5%"), "excatr", EXC.EXCATR[excno], "excno", EXC.EXCNO[excno], "DEF_EXC")$$END$
967 $END$
968 $i = i + 1$
969$END$
970
971$ CPU例外ハンドラのための標準的な初期化情報の生成
972$IF !ALT(OMIT_INITIALIZE_EXCEPTION,0)$
973
974$ CPU例外ハンドラ数
975#define TNUM_EXCNO $LENGTH(EXC.ORDER_LIST)$$NL$
976const uint_t _kernel_tnum_excno = TNUM_EXCNO;$NL$
977$NL$
978$FOREACH excno EXC.ORDER_LIST$
979 EXCHDR_ENTRY($EXC.EXCNO[excno]$, $+EXC.EXCNO[excno]$, $EXC.EXCHDR[excno]$)$NL$$NL$
980$END$
981
982$ CPU例外ハンドラ初期化テーブル
983$IF LENGTH(EXC.ORDER_LIST)$
984 const EXCNO _kernel_excinib_excno[TNUM_EXCNO] = {
985 $JOINEACH excno EXC.ORDER_LIST ","$
986 ($EXC.EXCNO[excno]$)
987 $END$
988 };$NL$
989
990 const ATR _kernel_excinib_excatr[TNUM_EXCNO] = {
991 $JOINEACH excno EXC.ORDER_LIST ","$
992 ($EXC.EXCATR[excno]$)
993 $END$
994 };$NL$
995
996 const FP _kernel_excinib_entry[TNUM_EXCNO] = {
997 $JOINEACH excno EXC.ORDER_LIST ","$
998 (FP)(EXC_ENTRY($EXC.EXCNO[excno]$, $EXC.EXCHDR[excno]$))
999 $END$
1000 };$NL$
1001$ELSE$
1002 TOPPERS_EMPTY_LABEL(const EXCNO, _kernel_excinib_excno);$NL$
1003 TOPPERS_EMPTY_LABEL(const ATR, _kernel_excinib_excatr);$NL$
1004 TOPPERS_EMPTY_LABEL(const FP, _kernel_excinib_entry);$NL$
1005$END$
1006$NL$
1007$END$
1008
1009
1010$ ---------------------------------------------------------------------
1011$ 周期ハンドラ
1012$ ---------------------------------------------------------------------
1013
1014/*$NL$
1015$SPC$* Cyclic Handler Functions$NL$
1016$SPC$*/$NL$
1017$NL$
1018
1019$ 周期ハンドラID番号の最大値
1020const ID _kernel_tmax_cycid = (TMIN_CYCID + TNUM_CYCID - 1);$NL$
1021
1022$ 周期ハンドラのタイムイベントIDオフセット
1023$ 周期ハンドラのタイムイベントIDは0から開始
1024const uint_t _kernel_cycevtid_offset = 0;$NL$
1025$NL$
1026
1027$ エントリが TMAX_MAXCYC(kernel.h) 個より多い場合は,エラーとする
1028$IF LENGTH(CYC.ORDER_LIST) > TMAX_MAXCYC$
1029 $ERROR$$FORMAT(_("The number of CRE_CYC must be equal to or less than %1%."), +VALUE("TMAX_MAXCYC", TMAX_MAXCYC))$$END$
1030$END$
1031
1032$IF LENGTH(CYC.ORDER_LIST)$
1033$ 周期ハンドラ属性
1034 $CYCACT = 0$
1035 $FOREACH cycid CYC.ORDER_LIST$
1036$ // 周期ハンドラ属性(cycatr) が TA_NULL, TA_STA のいずれでもない(E_RSATR)
1037 $IF (CYC.CYCATR[cycid] & ~TA_STA) != 0$
1038 $ERROR CYC.TEXT_LINE[cycid]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "cycatr", CYC.CYCATR[cycid], cycid, "CRE_CYC")$$END$
1039 $END$
1040
1041 $IF(CYC.CYCATR[cycid] & TA_STA)$
1042 $CYCACT = CYCACT | (1 << (cycid-1))$
1043 $END$
1044 $END$
1045 const uint16_t _kernel_cycinib_cycact = $CYCACT$;$NL$
1046
1047$ 周期ハンドラ拡張情報
1048 const intptr_t _kernel_cycinib_exinf[TNUM_CYCID] = {
1049 $JOINEACH cycid CYC.ORDER_LIST ","$
1050 (intptr_t)($CYC.EXINF[cycid]$)
1051 $END$
1052 };$NL$
1053
1054$ 周期ハンドラアドレス
1055 const CYCHDR _kernel_cycinib_cychdr[TNUM_CYCID] = {
1056 $JOINEACH cycid CYC.ORDER_LIST ","$
1057 ($CYC.CYCHDR[cycid]$)
1058 $END$
1059 };$NL$
1060
1061$ 周期ハンドラ周期
1062 const RELTIM _kernel_cycinib_cyctim[TNUM_CYCID] = {
1063 $JOINEACH cycid CYC.ORDER_LIST ","$
1064$ // cyctim は 0 より大きく,TMAX_RELTIM 以下である.(E_PAR)
1065 $IF CYC.CYCTIM[cycid] <= 0 || TMAX_RELTIM < CYC.CYCTIM[cycid] $
1066 $ERROR CYC.TEXT_LINE[cycid]$E_PAR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "cyctim", CYC.CYCTIM[cycid], cycid, "CRE_CYC")$$END$
1067 $END$
1068
1069 ($CYC.CYCTIM[cycid]$)
1070 $END$
1071 };$NL$
1072
1073$ 周期ハンドラ位相
1074 const RELTIM _kernel_cycinib_cycphs[TNUM_CYCID] = {
1075 $JOINEACH cycid CYC.ORDER_LIST ","$
1076$ // cycphs は 0 以上,TMAX_RELTIM 以下である.(E_PAR)
1077 $IF CYC.CYCPHS[cycid] < 0 || TMAX_RELTIM < CYC.CYCPHS[cycid] $
1078 $ERROR CYC.TEXT_LINE[cycid]$E_PAR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "cycphs", CYC.CYCPHS[cycid], cycid, "CRE_CYC")$$END$
1079 $END$
1080
1081$ // 位相が0かつ,属性が TA_STA の場合は警告
1082 $IF CYC.CYCPHS[cycid] == 0 && (CYC.CYCATR[cycid] & TA_STA) != 0$
1083 $WARNING CYC.TEXT_LINE[cycid]$$FORMAT(_("%1% is not recommended when %2% is set to %3% in %4%"), "cycphs==0", "TA_STA", "cycatr", "CRE_CYC")$$END$
1084 $END$
1085
1086 ($CYC.CYCPHS[cycid]$)
1087 $END$
1088 };$NL$
1089 $NL$
1090
1091$ 周期ハンドラの次回起動時刻
1092EVTTIM _kernel_cyccb_evttim[TNUM_CYCID];$NL$
1093
1094$ELSE$
1095 const uint16_t _kernel_cycinib_cycact = 0;$NL$
1096 TOPPERS_EMPTY_LABEL(const intptr_t, _kernel_cycinib_exinf);$NL$
1097 TOPPERS_EMPTY_LABEL(const CYCHDR, _kernel_cycinib_cychdr);$NL$
1098 TOPPERS_EMPTY_LABEL(const RELTIM, _kernel_cycinib_cyctim);$NL$
1099 TOPPERS_EMPTY_LABEL(const RELTIM, _kernel_cycinib_cycphs);$NL$
1100 TOPPERS_EMPTY_LABEL(EVTTIM, _kernel_cyccb_evttim);$NL$
1101$END$
1102
1103$ 周期ハンドラ動作状態
1104uint16_t _kernel_cyccb_cycact;$NL$
1105
1106$NL$
1107$NL$
1108
1109$ ---------------------------------------------------------------------
1110$ アラームハンドラ
1111$ ---------------------------------------------------------------------
1112
1113/*$NL$
1114$SPC$* Alarm Handler Functions$NL$
1115$SPC$*/$NL$
1116$NL$
1117
1118$ エントリが TMAX_MAXALM(kernel.h) 個より多い場合は,エラーとする
1119$IF LENGTH(ALM.ORDER_LIST) > TMAX_MAXALM$
1120 $ERROR$$FORMAT(_("The number of CRE_ALM must be equal to or less than %1%."), +VALUE("TMAX_MAXALM",TMAX_MAXALM))$$END$
1121$END$
1122
1123$ アラームハンドラの最大ID値
1124const ID _kernel_tmax_almid = (TMIN_ALMID + TNUM_ALMID - 1);$NL$
1125
1126$ アラームハンドラのタイムイベントIDオフセット
1127const uint_t _kernel_almevtid_offset = $LENGTH(CYC.ORDER_LIST)$;$NL$
1128$NL$
1129
1130$FOREACH almid ALM.ORDER_LIST$
1131$ // almatrが(TA_NULL)でない場合(E_RSATR)
1132 $IF ALM.ALMATR[almid] != 0$
1133 $ERROR ALM.TEXT_LINE[almid]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "almatr", ALM.ALMATR[almid], almid, "CRE_ALM")$$END$
1134 $END$
1135$END$
1136
1137$IF LENGTH(ALM.ORDER_LIST)$
1138$ アラームハンドラ先頭番地
1139 const ALMHDR _kernel_alminib_almhdr[TNUM_ALMID] = {
1140 $JOINEACH almid ALM.ORDER_LIST ","$
1141 ($ALM.ALMHDR[almid]$)
1142 $END$
1143 };$NL$
1144
1145$ アラームハンドラ拡張情報
1146 const intptr_t _kernel_alminib_exinf[TNUM_ALMID] = {
1147 $JOINEACH almid ALM.ORDER_LIST ","$
1148 (intptr_t)($ALM.EXINF[almid]$)
1149 $END$
1150 };$NL$
1151$NL$
1152$ELSE$
1153 TOPPERS_EMPTY_LABEL(const ALMHDR, _kernel_alminib_almhdr);$NL$
1154 TOPPERS_EMPTY_LABEL(const intptr_t, _kernel_alminib_exinf);$NL$
1155$NL$
1156$END$
1157
1158$ アラームハンドラ状態
1159uint16_t _kernel_almcb_almact;$NL$
1160$NL$
1161
1162
1163$ ---------------------------------------------------------------------
1164$ タイムイベント管理
1165$ ---------------------------------------------------------------------
1166
1167/*$NL$
1168$SPC$* Time Event Management$NL$
1169$SPC$*/$NL$
1170$NL$
1171
1172$TNUM_TMEVT = LENGTH(CYC.ORDER_LIST) + LENGTH(ALM.ORDER_LIST)$
1173
1174#define TNUM_TMEVT $TNUM_TMEVT$$NL$
1175$NL$
1176
1177$ タイムイベントブロックのサイズ
1178const uint_t _kernel_tnum_tmevt_queue = TNUM_TMEVT;$NL$$NL$
1179
1180$IF TNUM_TMEVT != 0$
1181$ タイムイベントキュー
1182 QUEUE _kernel_tmevt_queue[TNUM_TMEVT+1];$NL$
1183$ タイムイベント時間
1184 EVTTIM _kernel_tmevt_time[TNUM_TMEVT];$NL$
1185$ タイムイベントのコールバック
1186 CBACK _kernel_tmevt_callback[TNUM_TMEVT];$NL$
1187$ タイムイベントコールバックの引数
1188 uintptr_t _kernel_tmevt_arg[TNUM_TMEVT];$NL$
1189 $NL$$NL$
1190$ELSE$
1191 TOPPERS_EMPTY_LABEL(QUEUE, _kernel_tmevt_queue);$NL$
1192 TOPPERS_EMPTY_LABEL(EVTTIM, _kernel_tmevt_time);$NL$
1193 TOPPERS_EMPTY_LABEL(CBACK, _kernel_tmevt_callback);$NL$
1194 TOPPERS_EMPTY_LABEL(uintptr_t, _kernel_tmevt_arg);$NL$
1195 $NL$$NL$
1196$END$
1197
1198$ ---------------------------------------------------------------------
1199$ 非タスクコンテキスト用スタック領域
1200$ ---------------------------------------------------------------------
1201/*$NL$
1202$SPC$* Interrupt Context Stack Size$NL$
1203$SPC$*/$NL$$NL$
1204
1205$ // 変数定義
1206$ // 非タスクコンテキスト用スタック領域のサイズ
1207$interrupt_context_stksz = 0$
1208
1209$ // DEF_ICS のエントリが存在するか?
1210$IF !LENGTH(ICS.ORDER_LIST)$
1211$ // ない場合.サイズは既定値 (DEFAULT_ISTKSZ) を使う
1212 #define TOPPERS_ISTKSZ DEFAULT_ISTKSZ$NL$$NL$
1213 $interrupt_context_stksz = DEFAULT_ISTKSZ$
1214$ELSE$
1215$ // DEF_ICS のエントリがある場合
1216
1217$
1218$ // エラーチェック
1219$
1220$ // 静的API「DEF_ICS」が複数ある(E_OBJ)
1221 $IF LENGTH(ICS.ORDER_LIST) > 1$
1222 $ERROR$E_OBJ: $FORMAT(_("too many %1%"), "DEF_ICS")$$END$
1223 $END$
1224$ // DEF_ICS で0を指定した場合(E_PAR)
1225 $IF ICS.ISTKSZ[1] == 0$
1226 $ERROR ICS.TEXT_LINE[1]$E_PAR: $FORMAT(_("%1% in %2% is 0"), "istksz", "DEF_ICS")$$END$
1227 $END$
1228$ // 常に NULL である.(E_PAR)
1229 $IF !EQ(ICS.ISTK[1], "NULL")$
1230 $ERROR ICS.TEXT_LINE[1]$E_PAR: $FORMAT(("'%1%' of %2% must be NULL."), "istk", "DEF_ICS")$$END$
1231 $END$
1232
1233 #define TOPPERS_ISTKSZ ($ICS.ISTKSZ[1]$)$NL$
1234 $interrupt_context_stksz = ICS.ISTKSZ[1]$
1235 $NL$
1236$END$
1237$NL$
1238
1239$ ---------------------------------------------------------------------
1240$ 共有スタック領域
1241$ SSPではすべての処理単位のスタックを共有するため,
1242$ ここでシステム全体のスタック領域を確保する.
1243$ ---------------------------------------------------------------------
1244
1245$
1246$ 共有スタックのコンフィギュレーションに成功したかどうか
1247$
1248$ DEF_STK 処理中にエラーが発生した場合,この変数が0になる.
1249$ DEF_STK 処理中にエラーが発生したかどうかを判断して
1250$ 特定処理の実行をブロックするために使用する.
1251$
1252$configurated_defstk_successfully = 1$
1253
1254/*$NL$
1255$SPC$* Stack Area for System$NL$
1256$SPC$*/$NL$
1257$NL$
1258
1259$ // 変数定義
1260$ // 割り当てられた共有スタック領域のサイズ
1261$allocated_stack_size = 0$
1262
1263$ // DEF_STK のエントリが存在するか?
1264$IF !LENGTH(STK.ORDER_LIST)$
1265$ // (1) DEF_STK のエントリがない場合
1266 static STK_T _kernel_stack[COUNT_STK_T(TOPPERS_TSTKSZ+TOPPERS_ISTKSZ)];$NL$
1267 #define TOPPERS_STK _kernel_stack$NL$
1268 #define TOPPERS_STKSZ ROUND_STK_T(TOPPERS_TSTKSZ+TOPPERS_ISTKSZ)$NL$
1269 $NL$
1270
1271 $allocated_stack_size = max_tsk_stksz + interrupt_context_stksz$
1272$ELSE$
1273$ // (2) DEF_STK のエントリがある場合
1274
1275$ // エラーチェック
1276$ // 静的API「DEF_STK」が複数ある(E_OBJ)
1277 $IF LENGTH(STK.ORDER_LIST) > 1$
1278 $configurated_defstk_successfully = 0$
1279 $ERROR$E_OBJ: $FORMAT(_("too many %1%"), "DEF_STK")$$END$
1280 $END$
1281$ // DEF_STK の stksz で 0 を指定した場合(E_PAR)
1282 $IF STK.STKSZ[1] == 0$
1283 $configurated_defstk_successfully = 0$
1284 $ERROR STK.TEXT_LINE[1]$E_PAR: $FORMAT(_("%1% in %2% is 0"), "stksz", "DEF_STK")$$END$
1285 $END$
1286
1287 $IF EQ(STK.STK[1], "NULL")$
1288$ // stk が NULL の場合,スタック領域を自動割付け
1289 static STK_T _kernel_stack[COUNT_STK_T($STK.STKSZ[1]$)];$NL$
1290 #define TOPPERS_STK _kernel_stack$NL$
1291 #define TOPPERS_STKSZ ROUND_STK_T($STK.STKSZ[1]$)$NL$
1292 $ELSE$
1293$ // stk が NULL 以外の場合(アプリ側でスタック領域を用意する場合)
1294
1295$ // stkszがターゲット毎に定まるアライメントサイズの倍数にアライメントされていない場合(E_PAR)
1296 $IF LENGTH(CHECK_STKSZ_ALIGN) && (STK.STKSZ[1] & (CHECK_STKSZ_ALIGN - 1))$
1297 $configurated_defstk_successfully = 0$
1298 $ERROR STK.TEXT_LINE[1]$E_PAR: $FORMAT(_("%1% `%2%\' in %3% is not aligned"), "stksz", STK.STKSZ[1], "DEF_STK")$$END$
1299 $END$
1300
1301 #define TOPPERS_STK ($STK.STK[1]$)$NL$
1302 #define TOPPERS_STKSZ ($STK.STKSZ[1]$)$NL$
1303 $END$
1304
1305 $allocated_stack_size = STK.STKSZ[1]$
1306$END$
1307$NL$
1308
1309$ 共有スタック用のスタック領域
1310const SIZE _kernel_stksz = TOPPERS_STKSZ;$NL$
1311STK_T *const _kernel_stk = TOPPERS_STK;$NL$
1312$NL$
1313#ifdef TOPPERS_ISTKPT$NL$
1314STK_T *const _kernel_istkpt = TOPPERS_ISTKPT(TOPPERS_STK, TOPPERS_STKSZ);$NL$
1315#endif /* TOPPERS_ISTKPT */$NL$
1316$NL$
1317
1318$
1319$ // 優先度割り当ておよびスタック設定に関する結果を標準出力へ表示
1320$
1321$IF configurated_defepr_successfully == 1 && configurated_defstk_successfully == 1$
1322 $FILE "stdout"$
1323 =====================================$NL$
1324 Task priority configuration result:$NL$
1325 $FOREACH tskid SORT(TSK.ORDER_LIST, "TSK.ATSKPRI")$
1326 $TAB$$TSK.TSKID[tskid]$:$TAB$ IPRI = $reallocate_tskapri[TSK.TSKID[tskid]]$, EXEPRI = $reallocate_tskepri[tskid]$$NL$
1327 $END$
1328 =====================================$NL$
1329
1330 =====================================$NL$
1331 Stack size configuration result:$NL$
1332 $TAB$Estimated task stack size = $max_tsk_stksz$$NL$
1333 $TAB$Specified interrupt stack size = $interrupt_context_stksz$(value=$FORMAT("%d",+interrupt_context_stksz)$)$NL$
1334 $TAB$Allocated total stack size = $allocated_stack_size$(value=$FORMAT("%d",+allocated_stack_size)$)$NL$
1335$ // サイズのチェック.スタックサイズの推定値が実際に割当てられたサイズより大きい場合,警告する.
1336 $IF (max_tsk_stksz+interrupt_context_stksz) > allocated_stack_size$
1337 $TAB$!!!WARNING!!!: Estimated stack size is more than the allocated stack size.$NL$
1338 $WARNING STK.TEXT_LINE[1]$ $FORMAT("Estimated stack size is more than the allocated stack size.")$$END$
1339 $END$
1340 =====================================$NL$
1341$END$
1342$
1343$ // 出力先を元に戻しておく
1344$
1345$FILE "kernel_cfg.c"$
1346
1347
1348$ ---------------------------------------------------------------------
1349$ 各モジュールの初期化関数
1350$ ---------------------------------------------------------------------
1351/*$NL$
1352$SPC$* Module Initialization Function$NL$
1353$SPC$*/$NL$
1354$NL$
1355void$NL$
1356_kernel_initialize_object(void)$NL$
1357{$NL$
1358$IF TNUM_TMEVT > 0$
1359$TAB$_kernel_initialize_time_event();$NL$
1360$END$
1361$TAB$_kernel_initialize_task();$NL$
1362$TAB$_kernel_initialize_interrupt();$NL$
1363$TAB$_kernel_initialize_exception();$NL$
1364$IF LENGTH(CYC.ID_LIST)$
1365 $TAB$_kernel_initialize_cyclic();$NL$
1366$END$
1367$IF LENGTH(ALM.ID_LIST)$
1368 $TAB$_kernel_initialize_alarm();$NL$
1369$END$
1370$IF LENGTH(FLG.ID_LIST)$
1371 $TAB$_kernel_initialize_eventflag();$NL$
1372$END$
1373$IF LENGTH(DTQ.ID_LIST)$
1374 $TAB$_kernel_initialize_dataqueue();$NL$
1375$END$
1376}$NL$
1377$NL$
1378
1379$ ---------------------------------------------------------------------
1380$ 初期化ルーチンの実行関数
1381$ ---------------------------------------------------------------------
1382/*$NL$
1383$SPC$* Initialization Routine$NL$
1384$SPC$*/$NL$
1385$NL$
1386void$NL$
1387_kernel_call_inirtn(void)$NL$
1388{$NL$
1389$FOREACH order INI.ORDER_LIST$
1390$ // iniatrが(TA_NULL)でない場合(E_RSATR)
1391 $IF INI.INIATR[order] != 0$
1392 $ERROR INI.TEXT_LINE[order]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of %3% `%4%\' in %5%"), "iniatr", INI.INIATR[order], "inirtn", INI.INIRTN[order], "ATT_INI")$$END$
1393 $END$
1394 $TAB$((INIRTN)($INI.INIRTN[order]$))((intptr_t)($INI.EXINF[order]$));$NL$
1395$END$
1396}$NL$
1397$NL$
1398
1399$ ---------------------------------------------------------------------
1400$ 終了処理ルーチンの実行関数
1401$ ---------------------------------------------------------------------
1402/*$NL$
1403$SPC$* Termination Routine$NL$
1404$SPC$*/$NL$
1405$NL$
1406void$NL$
1407_kernel_call_terrtn(void)$NL$
1408{$NL$
1409$FOREACH rorder TER.RORDER_LIST$
1410$ // teratrが(TA_NULL)でない場合(E_RSATR)
1411 $IF TER.TERATR[rorder] != 0$
1412 $ERROR TER.TEXT_LINE[rorder]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of %3% `%4%\' in %5%"), "teratr", TER.TERATR[rorder], "terrtn", TER.TERRTN[rorder], "ATT_TER")$$END$
1413 $END$
1414 $TAB$((TERRTN)($TER.TERRTN[rorder]$))((intptr_t)($TER.EXINF[rorder]$));$NL$
1415$END$
1416}$NL$
1417$NL$
1418
1419
Note: See TracBrowser for help on using the repository browser.