source: rubycfg_asp/trunk/asp_dcre/kernel/interrupt.trb@ 315

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

SVNプロパティを設定

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby; charset=UTF-8
File size: 17.7 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,2016 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: interrupt.trb 678 2016-03-06 02:36:09Z ertl-hiro $
41#
42
43#
44# 割込み管理機能の生成スクリプト
45#
46
47#
48# kernel_cfg.cの生成
49#
50$kernelCfgC.comment_header("Interrupt Management Functions")
51
52#
53# ATT_ISRで使用できる割込み番号とそれに対応する割込みハンドラ番号のデ
54# フォルト定義
55#
56if $INTNO_ATTISR_VALID.nil?
57 $INTNO_ATTISR_VALID = $INTNO_VALID
58end
59if $INHNO_ATTISR_VALID.nil?
60 $INHNO_ATTISR_VALID = $INHNO_VALID
61end
62
63#
64# CFG_INTで使用できる割込み優先度のデフォルト定義
65#
66if $INTPRI_CFGINT_VALID.nil?
67 $INTPRI_CFGINT_VALID = $TMIN_INTPRI.upto($TMAX_INTPRI).to_a
68end
69
70#
71# 割込み番号と割込みハンドラ番号の変換テーブルの作成
72#
73if $INTNO_ATTISR_VALID.length != $INHNO_ATTISR_VALID.length
74 error_exit("length of `INTNO_ATTISR_VALID' is different from" \
75 " length of `INHNO_ATTISR_VALID'")
76end
77$toInhnoVal = {}
78$toIntnoVal = {}
79inhno_attisr_valid = $INHNO_ATTISR_VALID.dup
80$INTNO_ATTISR_VALID.each do |intnoVal|
81 inhnoVal = inhno_attisr_valid.shift
82 $toInhnoVal[intnoVal] = inhnoVal
83 $toIntnoVal[inhnoVal] = intnoVal
84end
85
86#
87# 割込み要求ラインに関するエラーチェック
88#
89$cfgData[:CFG_INT].each do |key, params|
90 # intnoが割込み番号として正しくない場合(E_PAR)[NGKI2972]
91 if $INTNO_VALID.index(params[:intno]).nil?
92 error_illegal("E_PAR", params, :intno)
93 end
94
95 # intatrが無効の場合(E_RSATR)[NGKI2969]
96 #(TA_ENAINT,TA_EDGE,TARGET_INTATR以外のビットがセットされている場合)
97 if (params[:intatr] & ~($TA_ENAINT|$TA_EDGE|$TARGET_INTATR)) != 0
98 error_illegal_sym("E_RSATR", params, :intatr, :intno)
99 end
100
101 # intpriがCFG_INTに対する割込み優先度として正しくない場合(E_PAR)
102 # [NGKI2973]
103 if $INTPRI_CFGINT_VALID.index(params[:intpri]).nil?
104 error_illegal_sym("E_OBJ", params, :intpri, :intno)
105 end
106
107 # カーネル管理外に固定されているintnoに対して,intpriにTMIN_INTPRIよ
108 # りも小さい値が指定されなかった場合(E_OBJ)[NGKI2983]
109 if !$INTNO_FIX_NONKERNEL.nil?
110 if !$INTNO_FIX_NONKERNEL.index(params[:intno]).nil?
111 if params[:intpri] >= $TMIN_INTPRI
112 error_ercd("E_OBJ", params, "%%intno must have higher priority " \
113 "than TMIN_INTPRI in %apiname")
114 end
115 end
116 end
117
118 # カーネル管理に固定されているintnoに対して,intpriにTMIN_INTPRIより
119 # も小さい値が指定された場合(E_OBJ)[NGKI2984]
120 if !$INTNO_FIX_KERNEL.nil?
121 if !$INTNO_FIX_KERNEL.index(params[:intno]).nil?
122 if params[:intpri] < $TMIN_INTPRI
123 error_ercd("E_OBJ", params, "%%intno must have lower or equal " \
124 "priority to TMIN_INTPRI in %apiname")
125 end
126 end
127 end
128end
129
130#
131# 割込みハンドラに関するエラーチェック
132#
133$cfgData[:DEF_INH].each do |key, params|
134 # inhnoが割込みハンドラ番号として正しくない場合(E_PAR)[NGKI3055]
135 if $INHNO_VALID.index(params[:inhno]).nil?
136 error_illegal("E_PAR", params, :inhno)
137 end
138
139 # inhatrが無効の場合(E_RSATR)[NGKI3052]
140 #(TARGET_INHATR以外のビットがセットされている場合)
141 if (params[:inhatr] & ~($TARGET_INHATR)) != 0
142 error_illegal_sym("E_RSATR", params, :inhatr, :inhno)
143 end
144
145 # カーネル管理外に固定されているinhnoに対して,inhatrにTA_NONKERNELが
146 # 指定されていない場合(E_RSATR)[NGKI3067]
147 if !$INHNO_FIX_NONKERNEL.nil?
148 if !$INHNO_FIX_NONKERNEL.index(params[:inhno]).nil?
149 if (params[:inhatr] & $TA_NONKERNEL) == 0
150 error_ercd("E_RSATR", params, "%%inhno must be " \
151 "non-kernel interrupt in %apiname")
152 end
153 end
154 end
155
156 # カーネル管理に固定されているinhnoに対して,inhatrにTA_NONKERNELが指
157 # 定されている場合(E_RSATR)[NGKI3068]
158 if !$INHNO_FIX_KERNEL.nil?
159 if !$INHNO_FIX_KERNEL.index(params[:inhno]).nil?
160 if (params[:inhatr] & $TA_NONKERNEL) != 0
161 error_ercd("E_RSATR", params, "%%inhno must not be " \
162 "non-kernel interrupt in %apiname")
163 end
164 end
165 end
166
167 if $toIntnoVal.has_key?(params[:inhno].val)
168 intnoVal = $toIntnoVal[params[:inhno].val]
169
170 # inhnoに対応するintnoに対するCFG_INTがない場合(E_OBJ)[NGKI3062]
171 if !$cfgData[:CFG_INT].has_key?(intnoVal)
172 error_ercd("E_OBJ", params, "intno `#{intnoVal}' corresponding to " \
173 "%%inhno in %apiname is not configured with CFG_INT")
174 else
175 intnoParams = $cfgData[:CFG_INT][intnoVal]
176 if (params[:inhatr] & $TA_NONKERNEL) == 0
177 # inhatrにTA_NONKERNELが指定されておらず,inhnoに対応するintno
178 # に対してCFG_INTで設定された割込み優先度がTMIN_INTPRIよりも小
179 # さい場合(E_OBJ)[NGKI3065]
180 if intnoParams[:intpri] < $TMIN_INTPRI
181 error_ercd("E_OBJ", params, "intpri `#{intnoParams[:intpri]}' " \
182 "configured for %%inhno must be lower or equal to TMIN_INTPRI")
183 end
184 else
185 # inhatrにTA_NONKERNELが指定されており,inhnoに対応するintnoに
186 # 対してCFG_INTで設定された割込み優先度がTMIN_INTPRI以上である
187 # 場合(E_OBJ)[NGKI3066]
188 if intnoParams[:intpri] >= $TMIN_INTPRI
189 error_ercd("E_OBJ", params, "intpri `#{intnoParams[:intpri]}' " \
190 "configured for %%inhno must be higher than TMIN_INTPRI")
191 end
192 end
193 end
194 end
195end
196
197#
198# 割込みサービスルーチン(ISR)に関するエラーチェック
199#
200$cfgData[:ATT_ISR].sort.each do |key, params|
201 # isratrが無効の場合(E_RSATR)[NGKI2998]
202 #(TARGET_ISRATR以外のビットがセットされている場合)
203 if (params[:isratr] & ~($TARGET_ISRATR)) != 0
204 error_illegal("E_RSATR", params, "isratr")
205 end
206
207 # intnoがATT_ISRに対する割込み番号として正しくない場合(E_PAR)
208 # [NGKI3003]
209 if $INTNO_ATTISR_VALID.index(params[:intno]).nil?
210 error_illegal("E_PAR", params, "intno")
211 end
212
213 # (TMIN_ISRPRI <= isrpri && isrpri <= TMAX_ISRPRI)でない場合(E_PAR)
214 # [NGKI3005]
215 if !($TMIN_ISRPRI <= params[:isrpri] && params[:isrpri] <= $TMAX_ISRPRI)
216 error_illegal("E_PAR", params, "isrpri")
217 end
218end
219
220$INTNO_ATTISR_VALID.each do |intnoVal|
221 # 割込み番号intnoに対して登録されたISRのリストの作成
222 isrParamsList = []
223 $cfgData[:ATT_ISR].sort.each do |key, params|
224 if params[:intno] == intnoVal
225 isrParamsList.push(params)
226 end
227 end
228
229 # 割込み番号intnoに対して登録されたISRが存在する場合
230 if isrParamsList.size > 0
231 inhnoVal = $toInhnoVal[intnoVal]
232
233 # intnoに対応するinhnoに対してDEF_INHがある場合(E_OBJ)[NGKI3013]
234 if $cfgData[:DEF_INH].has_key?(inhnoVal)
235 inhnoParams = $cfgData[:DEF_INH][inhnoVal]
236 error_ercd("E_OBJ", isrParamsList[0], "%%intno in %apiname " \
237 "is duplicated with inhno #{inhnoParams[:inhno]}")
238 end
239
240 # intnoに対するCFG_INTがない場合(E_OBJ)[NGKI3012]
241 if !$cfgData[:CFG_INT].has_key?(intnoVal)
242 error_ercd("E_OBJ", isrParamsList[0], "%%intno in %apiname " \
243 "is not configured with CFG_INT")
244 else
245 intnoParams = $cfgData[:CFG_INT][intnoVal]
246
247 # intnoに対してCFG_INTで設定された割込み優先度がTMIN_INTPRIよりも
248 # 小さい場合(E_OBJ)[NGKI3014]
249 if intnoParams[:intpri] < $TMIN_INTPRI
250 error_ercd("E_OBJ", isrParamsList[0],
251 "intpri `#{intnoParams[:intpri]}' configured for " \
252 "%%intno with CFG_INT in higher than TMIN_INTPRI")
253 end
254 end
255 end
256end
257
258#
259# 割込みサービスルーチン(ISR)管理のデータ構造
260#
261intnoIsrList = []
262$INTNO_ATTISR_VALID.each do |intnoVal|
263 inhnoVal = $toInhnoVal[intnoVal]
264 if $cfgData[:CFG_INT].has_key?(intnoVal) \
265 && !$cfgData[:DEF_INH].has_key?(inhnoVal)
266 intnoIsrList.push(intnoVal)
267 end
268end
269
270intnoIsrList.sort!
271$isrQueueHeader = {}
272intnoIsrList.each_with_index do |intnoVal, index|
273 $isrQueueHeader[intnoVal] = "&(_kernel_isr_queue_table[#{index}])"
274end
275
276$kernelCfgC.add2("const uint_t _kernel_tnum_isr_queue = #{intnoIsrList.size};")
277
278if intnoIsrList.size > 0
279 $kernelCfgC.add("const ISR_ENTRY _kernel_isr_queue_list" \
280 "[#{intnoIsrList.size}] = {")
281 intnoIsrList.each_with_index do |intnoVal, index|
282 $kernelCfgC.add(",") if index > 0
283 $kernelCfgC.append("\t{ #{intnoVal}, #{$isrQueueHeader[intnoVal]} }")
284 end
285 $kernelCfgC.add
286 $kernelCfgC.add2("};")
287 $kernelCfgC.add2("QUEUE _kernel_isr_queue_table[#{intnoIsrList.size}];")
288else
289 $kernelCfgC.add("TOPPERS_EMPTY_LABEL(const ISR_ENTRY, " \
290 "_kernel_isr_queue_list);")
291 $kernelCfgC.add2("TOPPERS_EMPTY_LABEL(QUEUE, _kernel_isr_queue_table);")
292end
293
294#
295# 割込みサービスルーチン(ISR)呼出しのための割込みハンドラ
296#
297intnoIsrList.each do |intnoVal|
298 inhnoVal = $toInhnoVal[intnoVal]
299
300 # 次のDEF_INHに相当するデータを生成
301 # DEF_INH(inhno, { TA_NULL, _kernel_inthdr_<intno> } );
302 $cfgData[:DEF_INH][inhnoVal] = {
303 inhno: NumStr.new(inhnoVal),
304 inhatr: NumStr.new($TA_NULL, "TA_NULL"),
305 inthdr: "_kernel_inthdr_#{intnoVal}"
306 }
307
308 # 割込みサービスルーチン用の割込みハンドラ
309 $kernelCfgC.add("void")
310 $kernelCfgC.add("_kernel_inthdr_#{intnoVal}(void)")
311 $kernelCfgC.add("{")
312 $kernelCfgC.add("\ti_begin_int(#{intnoVal});")
313 $kernelCfgC.add("\t_kernel_call_isr(#{$isrQueueHeader[intnoVal]});");
314 $kernelCfgC.add("\ti_end_int(#{intnoVal});")
315 $kernelCfgC.add2("}")
316end
317
318#
319# 割込みサービスルーチンに関する一般的な情報の生成
320#
321class IsrObject
322 def initialize()
323 @inibList = { "ISRINIB" => "aisrinib_table"}
324 end
325
326 def generate()
327 # AID_ISRの処理
328 numAutoObjid = 0
329 $cfgData[:AID_ISR].each do |key, params|
330 numAutoObjid += params["noisr".to_sym]
331 end
332 numObjid = $cfgData[:ATT_ISR].size + numAutoObjid
333
334 # kernel_cfg.hの生成
335 $kernelCfgH.add("#define TNUM_ISRID\t#{numAutoObjid}")
336
337 # オブジェクトのID番号のマクロ定義の生成
338 $cfgData[:ATT_ISR].sort.each do |key, params|
339 if params[:isrid]
340 $kernelCfgH.add("#define #{params[:isrid]}\t#{params[:isrid].val}")
341 end
342 end
343 $kernelCfgH.add()
344
345 # オブジェクトのID番号を保持する変数
346 if $USE_EXTERNAL_ID
347 $cfgData[:ATT_ISR].sort.each do |key, params|
348 if params[:isrid]
349 $kernelCfgC.add("const ID #{params[:isrid]}_id" \
350 " = #{params[:isrid].val};")
351 end
352 end
353 $kernelCfgC.add()
354 end
355
356 # 静的に生成されたオブジェクトの数
357 $kernelCfgC.add("#define TNUM_SISR\t#{$cfgData[:ATT_ISR].size}")
358 $kernelCfgC.add("#define TNUM_ISR\t#{numObjid}")
359
360 # オブジェクトID番号の最大値
361 $kernelCfgC.add("const ID _kernel_tmax_isrid" \
362 " = (TMIN_ISRID + TNUM_ISRID - 1);")
363 $kernelCfgC.add("const uint_t _kernel_tnum_sisr = TNUM_SISR;")
364
365 # データ構造
366 if $cfgData[:ATT_ISR].size > 0
367 # 事前準備(エラーチェック,メモリ領域の生成)
368 $cfgData[:ATT_ISR].sort.each do |key, params|
369 prepare(key, params)
370 end
371
372 # オブジェクト全体に対して必要なメモリ領域の生成(オプション)
373 if respond_to?(:generateData)
374 generateData()
375 end
376
377 # オブジェクト初期化ブロックの生成
378 $kernelCfgC.add("const ISRINIB _kernel_sisrinib_table" \
379 "[TNUM_SISR] = {")
380 $cfgData[:ATT_ISR].sort.each_with_index do |(key, params), index|
381 $kernelCfgC.add(",") if index > 0
382 $kernelCfgC.append("\t{ " + generateInib(key, params) + " }")
383 end
384 $kernelCfgC.add
385 $kernelCfgC.add2("};")
386 else
387 $kernelCfgC.add2("TOPPERS_EMPTY_LABEL(const ISRINIB, " \
388 "_kernel_sisrinib_table);")
389 end
390
391 # 動的生成オブジェクト用のオブジェクト初期化ブロック
392 @inibList.each do |type, array|
393 if numAutoObjid > 0
394 $kernelCfgC.add2("#{type} _kernel_#{array}[#{numAutoObjid}];")
395 else
396 $kernelCfgC.add2("TOPPERS_EMPTY_LABEL(#{type}, _kernel_#{array});")
397 end
398 end
399
400 if numObjid > 0
401 # オブジェクト管理ブロックの生成
402 $kernelCfgC.add2("ISRCB _kernel_isrcb_table" \
403 "[TNUM_ISR];")
404
405 # オブジェクト初期化関数の追加
406 $initializeFunctions.push("_kernel_initialize_isr();")
407 else
408 $kernelCfgC.add2("TOPPERS_EMPTY_LABEL(ISRCB, " \
409 "_kernel_isrcb_table);")
410 end
411 end
412
413 def prepare(key, params)
414 # エラーチェックは実施済みなので,ここでの処理は不要
415 end
416
417 def generateInib(key, params)
418 return("(#{params[:isratr]}), (intptr_t)(#{params[:exinf]}), " \
419 "(#{params[:intno]}), " \
420 "(#{$isrQueueHeader[params[:intno].val]}), " \
421 "(ISR)(#{params[:isr]}), (#{params[:isrpri]})")
422 end
423end
424IsrObject.new.generate()
425
426#
427# 割込みハンドラのための標準的な初期化情報の生成
428#
429if !$OMIT_INITIALIZE_INTERRUPT || $USE_INHINIB_TABLE
430 #
431 # 定義する割込みハンドラの数
432 #
433 $kernelCfgC.add(<<EOS)
434#define TNUM_INHNO #{$cfgData[:DEF_INH].size}
435const uint_t _kernel_tnum_inhno = TNUM_INHNO;
436EOS
437
438 if $cfgData[:DEF_INH].size != 0
439 #
440 # 割込みハンドラのエントリ
441 #
442 $cfgData[:DEF_INH].each do |key, params|
443 if (params[:inhatr] & $TA_NONKERNEL) == 0
444 $kernelCfgC.add("INTHDR_ENTRY(#{params[:inhno]}, " \
445 "#{params[:inhno].val}, #{params[:inthdr]})")
446 end
447 end
448 $kernelCfgC.add("")
449
450 #
451 # 割込みハンドラ初期化ブロック
452 #
453 $kernelCfgC.add("const INHINIB _kernel_inhinib_table[TNUM_INHNO] = {")
454 $cfgData[:DEF_INH].each_with_index do |(key, params), index|
455 $kernelCfgC.add(",") if index > 0
456 if (params[:inhatr] & $TA_NONKERNEL) == 0
457 inthdr = "(FP)(INT_ENTRY(#{params[:inhno]}, #{params[:inthdr]}))"
458 else
459 inthdr = "(FP)(#{params[:inthdr]})"
460 end
461 $kernelCfgC.append("\t{ (#{params[:inhno]}), (#{params[:inhatr]}), " \
462 "#{inthdr} }")
463 end
464 $kernelCfgC.add
465 $kernelCfgC.add2("};")
466 else
467 $kernelCfgC.add2("TOPPERS_EMPTY_LABEL(const INHINIB, " \
468 "_kernel_inhinib_table);")
469 end
470end
471
472#
473# 割込み要求ラインのための標準的な初期化情報の生成
474#
475if !$OMIT_INITIALIZE_INTERRUPT || $USE_INTINIB_TABLE
476 #
477 # 設定する割込み要求ラインの数
478 #
479 $kernelCfgC.add(<<EOS)
480#define TNUM_INTNO #{$cfgData[:CFG_INT].size}
481const uint_t _kernel_tnum_intno = TNUM_INTNO;
482EOS
483
484 #
485 # 割込み要求ライン初期化ブロック
486 #
487 if $cfgData[:CFG_INT].size != 0
488 $kernelCfgC.add("const INTINIB _kernel_intinib_table[TNUM_INTNO] = {")
489 $cfgData[:CFG_INT].each_with_index do |(key, params), index|
490 $kernelCfgC.add(",") if index > 0
491 $kernelCfgC.append("\t{ (#{params[:intno]}), (#{params[:intatr]}), " \
492 "(#{params[:intpri]}) }")
493 end
494 $kernelCfgC.add
495 $kernelCfgC.add2("};")
496 else
497 $kernelCfgC.add2("TOPPERS_EMPTY_LABEL(const INTINIB, " \
498 "_kernel_intinib_table);")
499 end
500end
501
502#
503# 割込み管理機能初期化関数の追加
504#
505$initializeFunctions.push("_kernel_initialize_interrupt();")
Note: See TracBrowser for help on using the repository browser.