# -*- coding: utf-8 -*- # # TOPPERS/SSP Kernel # Toyohashi Open Platform for Embedded Real-Time Systems/ # Advanced Standard Profile Kernel # # Copyright (C) 2015 by FUJI SOFT INCORPORATED, JAPAN # Copyright (C) 2015,2016 by Embedded and Real-Time Systems Laboratory # Graduate School of Information Science, Nagoya Univ., JAPAN # Copyright (C) 2017 by Naoki Saito # Nagoya Municipal Industrial Research Institute, JAPAN # # 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ # ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改 # 変・再配布(以下,利用と呼ぶ)することを無償で許諾する. # (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 # 権表示,この利用条件および下記の無保証規定が,そのままの形でソー # スコード中に含まれていること. # (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 # 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 # 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 # の無保証規定を掲載すること. # (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 # 用できない形で再配布する場合には,次のいずれかの条件を満たすこ # と. # (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 # 作権表示,この利用条件および下記の無保証規定を掲載すること. # (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに # 報告すること. # (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 # 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. # また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理 # 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを # 免責すること. # # 本ソフトウェアは,無保証で提供されているものである.上記著作権者お # よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的 # に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ # アの利用により直接的または間接的に生じたいかなる損害に関しても,そ # の責任を負わない. # # $Id: interrupt.trb 678 2016-03-06 02:36:09Z ertl-hiro $ # # # 割込み管理機能の生成スクリプト # $kernelCfgC.comment_header("Interrupt Management Functions") # # トレースログマクロのデフォルト定義 # $kernelCfgC.add(<= $TMIN_INTPRI error_ercd("E_OBJ", params, "%%intno must have higher priority " \ "than TMIN_INTPRI in %apiname") end end end # カーネル管理に固定されているintnoに対して,intpriにTMIN_INTPRIより # も小さい値が指定された場合(E_OBJ) if !$INTNO_FIX_KERNEL.nil? if !$INTNO_FIX_KERNEL.index(params[:intno]).nil? if params[:intpri] < $TMIN_INTPRI error_ercd("E_OBJ", params, "%%intno must have lower or equal " \ "priority to TMIN_INTPRI in %apiname") end end end end # # 割込みハンドラに関するエラーチェック # $cfgData[:DEF_INH].each do |key, params| # inhnoが割込みハンドラ番号として正しくない場合(E_PAR) if $INHNO_VALID.index(params[:inhno]).nil? error_illegal("E_PAR", params, :inhno) end # inhatrが無効の場合(E_RSATR) #(TARGET_INHATR以外のビットがセットされている場合) if (params[:inhatr] & ~($TARGET_INHATR)) != 0 error_illegal_sym("E_RSATR", params, :inhatr, :inhno) end # カーネル管理外に固定されているinhnoに対して,inhatrにTA_NONKERNELが # 指定されていない場合(E_RSATR) if !$INHNO_FIX_NONKERNEL.nil? if !$INHNO_FIX_NONKERNEL.index(params[:inhno]).nil? if (params[:inhatr] & $TA_NONKERNEL) == 0 error_ercd("E_RSATR", params, "%%inhno must be " \ "non-kernel interrupt in %apiname") end end end # カーネル管理に固定されているinhnoに対して,inhatrにTA_NONKERNELが指 # 定されている場合(E_RSATR) if !$INHNO_FIX_KERNEL.nil? if !$INHNO_FIX_KERNEL.index(params[:inhno]).nil? if (params[:inhatr] & $TA_NONKERNEL) != 0 error_ercd("E_RSATR", params, "%%inhno must not be " \ "non-kernel interrupt in %apiname") end end end if $toIntnoVal.has_key?(params[:inhno].val) intnoVal = $toIntnoVal[params[:inhno].val] # inhnoに対応するintnoに対するCFG_INTがない場合(E_OBJ) if !$cfgData[:CFG_INT].has_key?(intnoVal) error_ercd("E_OBJ", params, "intno `#{intnoVal}' corresponding to " \ "%%inhno in %apiname is not configured with CFG_INT") else intnoParams = $cfgData[:CFG_INT][intnoVal] if (params[:inhatr] & $TA_NONKERNEL) == 0 # inhatrにTA_NONKERNELが指定されておらず,inhnoに対応するintno # に対してCFG_INTで設定された割込み優先度がTMIN_INTPRIよりも小 # さい場合(E_OBJ) if intnoParams[:intpri] < $TMIN_INTPRI error_ercd("E_OBJ", params, "intpri `#{intnoParams[:intpri]}' " \ "configured for %%inhno must be lower or equal to TMIN_INTPRI") end else # inhatrにTA_NONKERNELが指定されており,inhnoに対応するintnoに # 対してCFG_INTで設定された割込み優先度がTMIN_INTPRI以上である # 場合(E_OBJ) if intnoParams[:intpri] >= $TMIN_INTPRI error_ercd("E_OBJ", params, "intpri `#{intnoParams[:intpri]}' " \ "configured for %%inhno must be higher than TMIN_INTPRI") end end end end end # # 割込みサービスルーチン(ISR)に関するエラーチェックと割込みハンドラの生成 # $cfgData[:ATT_ISR].sort.each do |key, params| # isratrが無効の場合(E_RSATR) #(TARGET_ISRATR以外のビットがセットされている場合) if (params[:isratr] & ~($TARGET_ISRATR)) != 0 error_illegal("E_RSATR", params, "isratr") end # intnoがATT_ISRに対する割込み番号として正しくない場合(E_PAR) if $INTNO_ATTISR_VALID.index(params[:intno]).nil? error_illegal("E_PAR", params, "intno") end # (TMIN_ISRPRI <= isrpri && isrpri <= TMAX_ISRPRI)でない場合(E_PAR) if !($TMIN_ISRPRI <= params[:isrpri] && params[:isrpri] <= $TMAX_ISRPRI) error_illegal("E_PAR", params, "isrpri") end end $INTNO_ATTISR_VALID.each do |intnoVal| # 割込み番号intnoに対して登録されたISRのリストの作成 isrParamsList = [] $cfgData[:ATT_ISR].sort.each do |key, params| if params[:intno] == intnoVal isrParamsList.push(params) end end # 割込み番号intnoに対して登録されたISRが存在する場合 if isrParamsList.size > 0 inhnoVal = $toInhnoVal[intnoVal] # intnoに対応するinhnoに対してDEF_INHがある場合(E_OBJ) if $cfgData[:DEF_INH].has_key?(inhnoVal) inhnoParams = $cfgData[:DEF_INH][inhnoVal] error_ercd("E_OBJ", isrParamsList[0], "%%intno in %apiname " \ "is duplicated with inhno #{inhnoParams[:inhno]}") end # intnoに対するCFG_INTがない場合(E_OBJ) if !$cfgData[:CFG_INT].has_key?(intnoVal) error_ercd("E_OBJ", isrParamsList[0], "%%intno in %apiname " \ "is not configured with CFG_INT") else intnoParams = $cfgData[:CFG_INT][intnoVal] # intnoに対してCFG_INTで設定された割込み優先度がTMIN_INTPRIよりも # 小さい場合(E_OBJ) if intnoParams[:intpri] < $TMIN_INTPRI error_ercd("E_OBJ", isrParamsList[0], "intpri `#{intnoParams[:intpri]}' configured for " \ "%%intno with CFG_INT in higher than TMIN_INTPRI") end end # 次のDEF_INHに相当するデータを生成 # DEF_INH(inhno, { TA_NULL, _kernel_inthdr_ } ); $cfgData[:DEF_INH][inhnoVal] = { inhno: NumStr.new(inhnoVal), inhatr: NumStr.new($TA_NULL, "TA_NULL"), inthdr: "_kernel_inthdr_#{intnoVal}" } # 割込みサービスルーチン用の割込みハンドラ $kernelCfgC.add("void") $kernelCfgC.add("_kernel_inthdr_#{intnoVal}(void)") $kernelCfgC.add("{") if isrParamsList.size > 1 $kernelCfgC.add("\tPRI saved_ipm;") $kernelCfgC.add $kernelCfgC.add("\ti_begin_int(#{intnoVal});") $kernelCfgC.add("\tsaved_ipm = i_get_ipm();") else $kernelCfgC.add("\ti_begin_int(#{intnoVal});") end # 割込みサービスルーチンを優先度順に呼び出す i = 0 # stable sortを行うための変数 isrParamsList.sort_by {|params| [ params[:isrpri].val, i += 1 ]} \ .each_with_index do |params, index| if index > 0 $kernelCfgC.add $kernelCfgC.add("\tif (i_sense_lock()) {") $kernelCfgC.add("\t\ti_unlock_cpu();") $kernelCfgC.add2("\t}") $kernelCfgC.add("\ti_set_ipm(saved_ipm);") end $kernelCfgC.add("\tLOG_ISR_ENTER(#{intnoVal});") $kernelCfgC.add("\t((ISR)(#{params[:isr]}))" \ "((intptr_t)(#{params[:exinf]}));") $kernelCfgC.add("\tLOG_ISR_LEAVE(#{intnoVal});") end $kernelCfgC.add("\ti_end_int(#{intnoVal});") $kernelCfgC.add2("}") end end # # 割込みハンドラのための標準的な初期化情報の生成 # if !$OMIT_INITIALIZE_INTERRUPT || $USE_INHINIB_TABLE # # 定義する割込みハンドラの数 # $kernelCfgC.add(< 0 $kernelCfgC.append("(#{params[:inhno]})") end $kernelCfgC.add("};") $kernelCfgC.append("const ATR\t_kernel_inhinib_inhatr[TNUM_INHNO] = {") $cfgData[:DEF_INH].each.with_index do |(key, params), index| $kernelCfgC.append(",") if index > 0 $kernelCfgC.append("(#{params[:inhatr]})") end $kernelCfgC.add("};") $kernelCfgC.append("const FP\t_kernel_inhinib_entry[TNUM_INHNO] = {") $cfgData[:DEF_INH].each.with_index do |(key, params), index| $kernelCfgC.append(",") if index > 0 $kernelCfgC.append("(FP)(INT_ENTRY(#{params[:inhno]}, #{params[:inthdr]}))") end $kernelCfgC.add2("};") else $kernelCfgC.add("TOPPERS_EMPTY_LABEL(const INHNO, _kernel_inhinib_inhno);") $kernelCfgC.add("TOPPERS_EMPTY_LABEL(const ATR, _kernel_inhinib_inhatr);") $kernelCfgC.add2("TOPPERS_EMPTY_LABEL(const FP, _kernel_inhinib_entry);") end end # # 割込み要求ラインのための標準的な初期化情報の生成 # if !$OMIT_INITIALIZE_INTERRUPT || $USE_INTINIB_TABLE # # 設定する割込み要求ラインの数 # $kernelCfgC.add(< 0 $kernelCfgC.append("(#{params[:intno]})") end $kernelCfgC.add("};") $kernelCfgC.append("const ATR _kernel_intinib_intatr[TNUM_INTNO] = {") $cfgData[:CFG_INT].each_with_index do |(key, params), index| $kernelCfgC.append(",") if index > 0 $kernelCfgC.append("(#{params[:intatr]})") end $kernelCfgC.add("};") $kernelCfgC.append("const PRI _kernel_intinib_intpri[TNUM_INTNO] = {") $cfgData[:CFG_INT].each_with_index do |(key, params), index| $kernelCfgC.append(",") if index > 0 $kernelCfgC.append("(#{params[:intpri]})") end $kernelCfgC.add2("};") else $kernelCfgC.add("TOPPERS_EMPTY_LABEL(const INTNO, _kernel_intinib_intno);") $kernelCfgC.add("TOPPERS_EMPTY_LABEL(const ATR, _kernel_intinib_intatr);") $kernelCfgC.add2("TOPPERS_EMPTY_LABEL(const PRI, _kernel_intinib_intpri);") end end # # 割込み管理機能初期化関数の追加 # $initializeFunctions.push("_kernel_initialize_interrupt();")