source: EcnlProtoTool/trunk/asp3_dcre/kernel/kernel.trb@ 439

Last change on this file since 439 was 439, checked in by coas-nagasima, 4 years ago

mrubyを2.1.1に更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby;charset=UTF-8
File size: 18.5 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# TOPPERS/ASP Kernel
4# Toyohashi Open Platform for Embedded Real-Time Systems/
5# Advanced Standard Profile Kernel
6#
7# Copyright (C) 2015 by FUJI SOFT INCORPORATED, JAPAN
8# Copyright (C) 2015-2019 by Embedded and Real-Time Systems Laboratory
9# Graduate School of Information Science, Nagoya Univ., JAPAN
10#
11# 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
12# ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
13# 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
14# (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
15# 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
16# スコード中に含まれていること.
17# (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
18# 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
19# 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
20# の無保証規定を掲載すること.
21# (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22# 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
23# と.
24# (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
25# 作権表示,この利用条件および下記の無保証規定を掲載すること.
26# (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
27# 報告すること.
28# (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
29# 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
30# また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
31# 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
32# 免責すること.
33#
34# 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
35# よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
36# に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
37# アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
38# の責任を負わない.
39#
40# $Id$
41#
42
43#
44# コンフィギュレータのパス2の生成スクリプト
45#
46
47#
48# タイムスタンプファイルの指定
49#
50$timeStampFileName = "kernel_cfg.timestamp"
51
52#
53# kernel_cfg.hの先頭部分の生成
54#
55$kernelCfgH = GenFile.new("kernel_cfg.h")
56$kernelCfgH.add(<<EOS)
57/* kernel_cfg.h */
58#ifndef TOPPERS_KERNEL_CFG_H
59#define TOPPERS_KERNEL_CFG_H
60EOS
61
62#
63# kernel_cfg.cの先頭部分の生成
64#
65$kernelCfgC = GenFile.new("kernel_cfg.c")
66$kernelCfgC.add(<<EOS)
67/* kernel_cfg.c */
68#include "kernel/kernel_int.h"
69#include "kernel_cfg.h"
70
71#if !(TKERNEL_PRID == 0x0007U && (TKERNEL_PRVER & 0xf000U) == 0x3000U)
72#error The kernel does not match this configuration file.
73#endif
74EOS
75
76#
77# インクルードディレクティブ(#include)の生成
78#
79$kernelCfgC.comment_header("Include Directives")
80GenerateIncludes($kernelCfgC)
81$kernelCfgC.add()
82
83#
84# スタック領域の確保関数
85#
86# スタック領域の定義分と,スタック領域のサイズ記述を配列で返す.
87#
88unless defined? AllocStack()
89 def AllocStack(stack, size)
90 # 大きい方に丸めたサイズで確保する[NGKI1050][NGKI3220]
91 $kernelCfgC.add("static STK_T #{stack}[COUNT_STK_T(#{size})];")
92 return("ROUND_STK_T(#{size})")
93 end
94end
95
96#
97# カーネルオブジェクトに関する情報の生成(仮想クラス)
98#
99class KernelObject
100 def initialize(obj, object, obj_s = obj)
101 @obj = obj
102 @OBJ = obj.tr("a-z", "A-Z")
103 @object = object
104 @obj_s = obj_s
105 @OBJ_S = obj_s.tr("a-z", "A-Z")
106 @objid = (obj + "id").to_sym
107 @noobj = ("no" + obj).to_sym
108 @api = "CRE_#{@OBJ}".to_sym
109 @aidapi = "AID_#{@OBJ}".to_sym
110 @inibList = { "#{@OBJ_S}INIB" => "a#{@obj_s}inib_table"}
111 end
112
113 def generate()
114 # AID_@OBJの処理
115 numAutoObjid = 0
116 $cfgData[@aidapi].each do |_, params|
117 numAutoObjid += params[@noobj]
118 end
119 numObjid = $cfgData[@api].size + numAutoObjid
120
121 # kernel_cfg.hの生成
122 $kernelCfgH.add("#define TNUM_#{@OBJ}ID\t#{numObjid}")
123
124 # オブジェクトのID番号のマクロ定義の生成
125 $cfgData[@api].sort.each do |_, params|
126 $kernelCfgH.add("#define #{params[@objid]}\t#{params[@objid].val}")
127 end
128 $kernelCfgH.add()
129
130 # オブジェクトのID番号を保持する変数
131 if $USE_EXTERNAL_ID
132 $cfgData[@api].sort.each do |_, params|
133 $kernelCfgC.add("const ID #{params[@objid]}_id" \
134 " = #{params[@objid].val};")
135 end
136 $kernelCfgC.add()
137 end
138
139 # 静的に生成されたオブジェクトの数
140 $kernelCfgC.add("#define TNUM_S#{@OBJ}ID\t#{$cfgData[@api].size}")
141
142 # オブジェクトID番号の最大値
143 $kernelCfgC.add("const ID _kernel_tmax_#{@obj}id" \
144 " = (TMIN_#{@OBJ}ID + TNUM_#{@OBJ}ID - 1);")
145 $kernelCfgC.add2("const ID _kernel_tmax_s#{@obj}id" \
146 " = (TMIN_#{@OBJ}ID + TNUM_S#{@OBJ}ID - 1);")
147
148 # データ構造
149 if $cfgData[@api].size > 0
150 # 事前準備(エラーチェック,メモリ領域の生成)
151 $cfgData[@api].sort.each do |key, params|
152 prepare(key, params)
153 end
154
155 # オブジェクト全体に対して必要なメモリ領域の生成(オプション)
156 if respond_to?(:generateData)
157 generateData()
158 end
159
160 # オブジェクト初期化ブロックの生成
161 $kernelCfgC.add("const #{@OBJ_S}INIB _kernel_#{@obj_s}inib_table" \
162 "[TNUM_S#{@OBJ}ID] = {")
163 $cfgData[@api].sort.each_with_index do |(key, params), index|
164 $kernelCfgC.add(",") if index > 0
165 $kernelCfgC.append("\t{ " + generateInib(key, params) + " }")
166 end
167 $kernelCfgC.add
168 $kernelCfgC.add2("};")
169 else
170 $kernelCfgC.add2("TOPPERS_EMPTY_LABEL(const #{@OBJ_S}INIB, " \
171 "_kernel_#{@obj_s}inib_table);")
172 end
173
174 # 動的生成オブジェクト用のオブジェクト初期化ブロック
175 @inibList.each do |type, array|
176 if numAutoObjid > 0
177 $kernelCfgC.add2("#{type} _kernel_#{array}[#{numAutoObjid}];")
178 else
179 $kernelCfgC.add2("TOPPERS_EMPTY_LABEL(#{type}, _kernel_#{array});")
180 end
181 end
182
183 if numObjid > 0
184 # オブジェクト管理ブロックの生成
185 $kernelCfgC.add2("#{@OBJ_S}CB _kernel_#{@obj_s}cb_table" \
186 "[TNUM_#{@OBJ}ID];")
187
188 # オブジェクト初期化関数の追加
189 $initializeFunctions.push("_kernel_initialize_#{@object}();")
190 else
191 $kernelCfgC.add2("TOPPERS_EMPTY_LABEL(#{@OBJ_S}CB, " \
192 "_kernel_#{@obj_s}cb_table);")
193 end
194 end
195end
196
197#
198# 通知ハンドラの生成関数
199#
200def generateNotifyHandler(key, params, objid)
201 # パラメータを変数に格納
202 nfymode = params[:nfymode]
203 nfymode1 = nfymode & 0x0f
204 nfymode2 = nfymode & ~0x0f
205 # par1 = params[:par1]
206 par2 = params[:par2]
207
208 # 通知処理のパラメータ数による補正処理
209 if nfymode == $TNFY_HANDLER || nfymode1 == $TNFY_SETVAR \
210 || nfymode1 == $TNFY_SETFLG \
211 || nfymode1 == $TNFY_SNDDTQ
212 # 通知処理のパラメータが2つの場合
213 numpar = 2
214 epar1 = params[:par3]
215 epar2 = params[:par4]
216 else
217 # 通知処理のパラメータが1つの場合
218 numpar = 1
219 epar1 = params[:par2]
220 epar2 = params[:par3]
221 end
222
223 # パラメータ数のチェック
224 if (numpar == 2 && par2.nil?) || (nfymode2 != 0 && epar1.nil?) \
225 || (nfymode2 == $TENFY_SETFLG && epar2.nil?)
226 # パラメータが足りない場合
227 error_api(params, "too few parameters for nfymode `#{nfymode}' " \
228 "in %apiname of %#{objid}")
229 elsif (nfymode2 == 0 && !epar1.nil?) \
230 || (nfymode2 != $TENFY_SETFLG && !epar2.nil?)
231 # パラメータが多すぎる場合
232 error_api(params, "too many parameters for nfymode `#{nfymode}' " \
233 "in %apiname of %#{objid}")
234 elsif nfymode1 == $TNFY_HANDLER && nfymode2 == 0 #[NGKI3721]
235 # タイムイベントハンドラの呼出し
236 funcname = "(NFYHDR)(#{par2})"
237 else
238 # 通知ハンドラの関数名
239 funcname = "_kernel_nfyhdr_#{params[objid]}"
240
241 # エラー通知のための変数のアドレスとオブジェクトIDを格納する
242 # 変数の生成(エラーチェックのために必要)
243 if nfymode2 == $TENFY_SETVAR || nfymode2 == $TENFY_INCVAR
244 $kernelCfgC.add2("intptr_t *const #{funcname}_p_evar =" \
245 " (intptr_t *)(#{epar1});")
246 elsif nfymode2 == $TENFY_ACTTSK || nfymode2 == $TENFY_WUPTSK
247 $kernelCfgC.add2("const ID #{funcname}_etskid = #{epar1};")
248 elsif nfymode2 == $TENFY_SIGSEM
249 $kernelCfgC.add2("const ID #{funcname}_esemid = #{epar1};")
250 elsif nfymode2 == $TENFY_SETFLG
251 $kernelCfgC.add2("const ID #{funcname}_eflgid = #{epar1};")
252 elsif nfymode2 == $TENFY_SNDDTQ
253 $kernelCfgC.add2("const ID #{funcname}_edtqid = #{epar1};")
254 end
255
256 # 関数の先頭部分の生成
257 $kernelCfgC.add("static void")
258 $kernelCfgC.add("#{funcname}(intptr_t exinf)")
259 $kernelCfgC.add("{")
260
261 if nfymode2 == 0
262 # エラー通知がない場合
263 errorCode = "(void) "
264 else
265 # エラー通知がある場合
266 $kernelCfgC.add2("\tER\tercd;")
267 errorCode = "ercd = "
268 end
269
270 # イベント通知処理の処理
271 if nfymode1 == $TNFY_SETVAR && nfymode2 == 0 #[NGKI3721]
272 # 変数の設定
273 $kernelCfgC.add("\t*((intptr_t *) exinf) = (#{par2});")
274 elsif nfymode1 == $TNFY_INCVAR && nfymode2 == 0 #[NGKI3721]
275 # 変数のインクリメント
276 $kernelCfgC.add("\t(void) loc_cpu();")
277 $kernelCfgC.add("\t*((intptr_t *) exinf) += 1;")
278 $kernelCfgC.add("\t(void) unl_cpu();")
279 elsif nfymode1 == $TNFY_ACTTSK
280 # タスクの起動
281 $kernelCfgC.add("\t#{errorCode}act_tsk((ID) exinf);")
282 elsif nfymode1 == $TNFY_WUPTSK
283 # タスクの起床
284 $kernelCfgC.add("\t#{errorCode}wup_tsk((ID) exinf);")
285 elsif nfymode1 == $TNFY_SIGSEM
286 # セマフォの返却
287 $kernelCfgC.add("\t#{errorCode}sig_sem((ID) exinf);")
288 elsif nfymode1 == $TNFY_SETFLG
289 # イベントフラグのセット
290 $kernelCfgC.add("\t#{errorCode}set_flg(((ID) exinf), #{par2});")
291 elsif nfymode1 == $TNFY_SNDDTQ
292 # データキューへの送信
293 $kernelCfgC.add("\t#{errorCode}psnd_dtq(((ID) exinf), #{par2});")
294 else
295 # nfymodeの値が正しくない場合(E_PAR)[NGKI3730]
296 error_illegal_id("E_PAR", params, :nfymode, objid)
297 end
298
299 if nfymode2 != 0
300 # エラー通知処理の処理
301 $kernelCfgC.add("\tif (ercd != E_OK) {")
302
303 if nfymode2 == $TENFY_SETVAR
304 # 変数の設定
305 $kernelCfgC.add("\t\t*#{funcname}_p_evar = (intptr_t) ercd;")
306 elsif nfymode2 == $TENFY_INCVAR
307 # 変数のインクリメント
308 $kernelCfgC.add("\t\t(void) loc_cpu();")
309 $kernelCfgC.add("\t\t*#{funcname}_p_evar += 1;")
310 $kernelCfgC.add("\t\t(void) unl_cpu();")
311 elsif nfymode2 == $TENFY_ACTTSK
312 # タスクの起動
313 $kernelCfgC.add("\t\t(void) act_tsk(#{funcname}_etskid);")
314 elsif nfymode2 == $TENFY_WUPTSK
315 # タスクの起床
316 $kernelCfgC.add("\t\t(void) wup_tsk(#{funcname}_etskid);")
317 elsif nfymode2 == $TENFY_SIGSEM
318 # セマフォの返却
319 $kernelCfgC.add("\t\t(void) sig_sem(#{funcname}_esemid);")
320 elsif nfymode2 == $TENFY_SETFLG
321 # イベントフラグのセット
322 $kernelCfgC.add("\t\t(void) set_flg(#{funcname}_eflgid, #{epar2});")
323 elsif nfymode2 == $TENFY_SNDDTQ
324 # データキューへの送信
325 $kernelCfgC.add("\t\t(void) psnd_dtq(#{funcname}_edtqid," \
326 " (intptr_t) ercd);")
327 else
328 # nfymodeの値が正しくない場合(E_PAR)[NGKI3730]
329 error_illegal_id("E_PAR", params, :nfymode, objid)
330 end
331 $kernelCfgC.add("\t}")
332 end
333
334 # 関数の末尾部分の生成
335 $kernelCfgC.add2("}")
336 end
337 return(funcname)
338end
339
340#
341# 各機能モジュールのコンフィギュレーション
342#
343$initializeFunctions = []
344IncludeTrb("kernel/task.trb")
345IncludeTrb("kernel/semaphore.trb")
346IncludeTrb("kernel/eventflag.trb")
347IncludeTrb("kernel/dataqueue.trb")
348IncludeTrb("kernel/pridataq.trb")
349IncludeTrb("kernel/mutex.trb")
350IncludeTrb("kernel/mempfix.trb")
351IncludeTrb("kernel/cyclic.trb")
352IncludeTrb("kernel/alarm.trb")
353IncludeTrb("kernel/interrupt.trb")
354IncludeTrb("kernel/exception.trb")
355
356#
357# 非タスクコンテキスト用のスタック領域
358#
359$kernelCfgC.comment_header("Stack Area for Non-task Context")
360
361if $cfgData[:DEF_ICS].size == 0
362 # DEF_ICSがない場合のデフォルト値の設定
363 if !defined?($DEFAULT_ISTK)
364 # スタック領域の自動割付け
365 istksz = AllocStack("_kernel_istack", "DEFAULT_ISTKSZ")
366 istk = "_kernel_istack"
367 else
368 istksz = "DEFAULT_ISTKSZ"
369 istk = "DEFAULT_ISTK"
370 end
371else
372 # 静的API「DEF_ICS」が複数ある場合(E_OBJ)[NGKI3216]
373 if $cfgData[:DEF_ICS].size > 1
374 error("E_OBJ: too many DEF_ICS")
375 end
376
377 # DEF_ICSがある場合の処理
378 params0 = $cfgData[:DEF_ICS][1]
379
380 # パラメータが省略された時のデフォルト値の設定
381 params0[:istk] ||= "NULL"
382
383 # istkszがターゲット定義の最小値(TARGET_MIN_ISTKSZ,未定義の場合は1)
384 # よりも小さい場合(E_PAR)[NGKI3254]
385 if params0[:istksz] < $TARGET_MIN_ISTKSZ
386 error_wrong("E_PAR", params0, :istksz, "too small")
387 end
388
389 if params0[:istk] == "NULL"
390 # スタック領域の自動割付け
391 istksz = AllocStack("_kernel_istack", params0[:istksz])
392 istk = "_kernel_istack"
393 else
394 # istkszがターゲット定義の制約に合致しない場合(E_PAR)[NGKI3222]
395 if (params0[:istksz] & ($CHECK_STKSZ_ALIGN - 1)) != 0
396 error_wrong("E_PAR", params0, :istksz, "not aligned")
397 end
398
399 istksz = "(#{params0[:istksz]})"
400 istk = "(void *)(#{params0[:istk]})"
401 end
402end
403
404$kernelCfgC.add(<<EOS)
405const size_t _kernel_istksz = #{istksz};
406STK_T *const _kernel_istk = #{istk};
407
408#ifdef TOPPERS_ISTKPT
409STK_T *const _kernel_istkpt = TOPPERS_ISTKPT(#{istk}, #{istksz});
410#endif /* TOPPERS_ISTKPT */
411EOS
412
413#
414# カーネルメモリプール領域
415#
416$kernelCfgC.comment_header("Kernel Memory Pool Area")
417
418if $cfgData[:DEF_MPK].size == 0
419 # DEF_MPKがない場合のデフォルト値の設定
420 mpksz = "0"
421 mpk = "NULL"
422else
423 # 静的API「DEF_MPK」が複数ある(E_OBJ)[NGKI5073]
424 if ($cfgData[:DEF_MPK].size > 1)
425 error("E_OBJ: too many DEF_MPK")
426 end
427
428 # DEF_MPKがある場合の処理
429 params0 = $cfgData[:DEF_MPK][1]
430
431 # パラメータが省略された時のデフォルト値の設定
432 params0[:mpk] ||= "NULL"
433
434 # mpkszが0の場合(E_PAR)[NGKI5071]
435 if params0[:mpksz] == 0
436 error_wrong("E_PAR", params0, :mpksz, "zero")
437 end
438
439 if params0[:mpk] == "NULL"
440 # カーネルメモリプール領域の自動割付け
441 $kernelCfgC.add("static MB_T _kernel_memory_pool" \
442 "[COUNT_MB_T(#{params0[:mpksz]})];")
443 mpksz = "ROUND_MB_T(#{params0[:mpksz]})"
444 mpk = "_kernel_memory_pool"
445 else
446 # mpkszがターゲット定義の制約に合致しない場合(E_PAR)[NGKI5083]
447 if (params0[:mpksz] & ($CHECK_MB_ALIGN - 1)) != 0
448 error_wrong("E_PAR", params0, :mpksz, "not aligned")
449 end
450
451 mpksz = "(#{params0[:mpksz]})"
452 mpk = "(void *)(#{params0[:mpk]})"
453 end
454end
455
456$kernelCfgC.add(<<EOS)
457const size_t _kernel_mpksz = #{mpksz};
458MB_T *const _kernel_mpk = #{mpk};
459EOS
460
461#
462# タイムイベント管理
463#
464$kernelCfgC.comment_header("Time Event Management")
465$kernelCfgC.add(<<EOS)
466TMEVTN _kernel_tmevt_heap[1 + TNUM_TSKID + TNUM_CYCID + TNUM_ALMID];
467EOS
468
469#
470# 各モジュールの初期化関数
471#
472$kernelCfgC.comment_header("Module Initialization Function")
473$kernelCfgC.append(<<EOS)
474void
475_kernel_initialize_object(void)
476{
477EOS
478$initializeFunctions.each do |func|
479 $kernelCfgC.add("\t#{func}")
480end
481$kernelCfgC.add2("}")
482
483#
484# 初期化ルーチン機能
485#
486
487# kernel_cfg.hの生成
488$kernelCfgH.add2("#define TNUM_INIRTN\t#{$cfgData[:ATT_INI].size}")
489
490# kernel_cfg.cの生成
491$kernelCfgC.comment_header("Initialization Routine")
492
493# エラーチェック
494$cfgData[:ATT_INI].each do |_, params|
495 # iniatrが無効の場合(E_RSATR)[NGKI3241][NGKI3202][NGKI3203]
496 #(TA_NULLでない場合)
497 if (params[:iniatr] != $TA_NULL)
498 error_illegal_sym("E_RSATR", params, :iniatr, :inirtn)
499 end
500end
501
502# 初期化ルーチンの数の定義
503$kernelCfgC.add2("const uint_t _kernel_tnum_inirtn = TNUM_INIRTN;");
504
505# 初期化ルーチンテーブルの生成
506if $cfgData[:ATT_INI].size > 0
507 $kernelCfgC.add("const INIRTNB _kernel_inirtnb_table[TNUM_INIRTN] = {")
508 $cfgData[:ATT_INI].each_with_index do |(_, params), index|
509 $kernelCfgC.add(",") if index > 0
510 $kernelCfgC.append("\t{ (INIRTN)(#{params[:inirtn]}), " \
511 "(intptr_t)(#{params[:exinf]}) }")
512 end
513 $kernelCfgC.add
514 $kernelCfgC.add2("};")
515else
516 $kernelCfgC.add2("TOPPERS_EMPTY_LABEL(const INIRTNB, " \
517 "_kernel_inirtnb_table);")
518end
519
520#
521# 終了処理ルーチン機能
522#
523
524# kernel_cfg.hの生成
525$kernelCfgH.add2("#define TNUM_TERRTN\t#{$cfgData[:ATT_TER].size}")
526
527# kernel_cfg.cの生成
528$kernelCfgC.comment_header("Termination Routine")
529
530# エラーチェック
531$cfgData[:ATT_TER].each do |_, params|
532 # teratrが無効の場合(E_RSATR)[NGKI3248][NGKI3208][NGKI3209]
533 #(TA_NULLでない場合)
534 if (params[:teratr] != $TA_NULL)
535 error_illegal_sym("E_RSATR", params, :teratr, :terrtn)
536 end
537end
538
539# 終了処理ルーチンの数の定義
540$kernelCfgC.add2("const uint_t _kernel_tnum_terrtn = TNUM_TERRTN;");
541
542# 終了処理ルーチンテーブルの生成
543if $cfgData[:ATT_TER].size > 0
544 $kernelCfgC.add("const TERRTNB _kernel_terrtnb_table[TNUM_TERRTN] = {")
545 $cfgData[:ATT_TER].reverse_each.each_with_index do |(_, params), index|
546 $kernelCfgC.add(",") if index > 0
547 $kernelCfgC.append("\t{ (TERRTN)(#{params[:terrtn]}), " \
548 "(intptr_t)(#{params[:exinf]}) }")
549 end
550 $kernelCfgC.add
551 $kernelCfgC.add2("};")
552else
553 $kernelCfgC.add2("TOPPERS_EMPTY_LABEL(const TERRTNB, " \
554 "_kernel_terrtnb_table);")
555end
556
557#
558# kernel_cfg.hの末尾部分の生成
559#
560$kernelCfgH.append(<<EOS)
561#endif /* TOPPERS_KERNEL_CFG_H */
562EOS
Note: See TracBrowser for help on using the repository browser.