/* * TOPPERS/SSP Kernel * Smallest Set Profile Kernel * * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory * Toyohashi Univ. of Technology, JAPAN * Copyright (C) 2005,2006 by Embedded and Real-Time Systems Laboratory * Graduate School of Information Science, Nagoya Univ., JAPAN * Copyright (C) 2008 by Witz Corporation, JAPAN * Copyright (C) 2010-2014 by Naoki Saito * Nagoya Municipal Industrial Research Institute, JAPAN * * 上記著作権者は,以下の (1)〜(4) の条件を満たす場合に限り,本ソフトウェ * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改変・ * 再配布(以下,利用と呼ぶ)することを無償で許諾する. * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作権 * 表示,この利用条件および下記の無保証規定が,そのままの形でソース * コード中に含まれていること. * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使用 * できる形で再配布する場合には,再配布に伴うドキュメント(利用者マ * ニュアルなど)に,上記の著作権表示,この利用条件および下記の無保 * 証規定を掲載すること. * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使用 * できない形で再配布する場合には,次のいずれかの条件を満たすこと. * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著作 * 権表示,この利用条件および下記の無保証規定を掲載すること. * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに報 * 告すること. * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損害 * からも,上記著作権者およびTOPPERSプロジェクトを免責すること.また, * 本ソフトウェアのユーザまたはエンドユーザからのいかなる理由に基づ * く請求からも,上記著作権者およびTOPPERSプロジェクトを免責すること. * * 本ソフトウェアは,無保証で提供されているものである.上記著作権者およ * びTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的に対す * る適合性も含めて,いかなる保証も行わない.また,本ソフトウェアの利用 * により直接的または間接的に生じたいかなる損害に関しても,その責任を負 * わない. * */ /* * プロセッサ依存モジュール(RL78) */ #pragma EI #pragma DI #include /* * 割込み発生回数を保存する変数 */ uint8_t intnest; /* * (1) コンテキストに関する定義 */ /* * コンテキストの参照 */ bool_t sense_context(void) { /* ネストカウンタ0より大なら非タスクコンテキスト */ return (intnest > 0); } /* * (2) システム状態に関する定義 */ /* * CPUロックフラグ実現のための変数 */ bool_t lock_flag; /* CPUロックフラグの値を保持する変数 */ #if TMIN_INTPRI != -4 uint8_t saved_psw; /* 割込み優先度レベルを保存する変数 */ #endif /* * CPU ロック状態への移行 * この関数は,CPU ロック状態のときに呼びだされないことを前提とする. */ void t_lock_cpu(void) { #if TMIN_INTPRI == -4 DI(); #else /* タスクでは割込み優先度マスクの値は 0 のはずなので保存する必要がない */ set_psw(PSW_SET_ISP(get_psw(), ISP_LOCK)); #endif lock_flag = true; } void i_lock_cpu(void) { #if TMIN_INTPRI == -4 DI(); #else uint8_t psw; /* * get_psw() の返り値を直接 saved_isp に保存せず,一時変数 * psw へ保存するのは,get_psw() の呼びだし直後に割込みが発生し, * 起動された割込み処理で saved_isp が変更される可能性があるため. */ psw = get_psw(); if (TIPM_LOCK < ISP2IPM(PSW2ISP(psw))) { set_psw(PSW_SET_ISP(psw, ISP_LOCK)); } saved_psw = psw; #endif lock_flag = true; } /* * CPUロック状態の解除 * この関数は,CPU ロック状態のときにのみ呼びだされることを前提とする. */ void t_unlock_cpu(void) { lock_flag = false; #if TMIN_INTPRI == -4 EI(); #else /* タスク実行時は割込みマスク全解除状態のはずなので,全解除にしておく */ set_psw(PSW_SET_ISP(get_psw(), ISP_ENAALL)); #endif } void i_unlock_cpu(void) { lock_flag = false; #if TMIN_INTPRI == -4 EI(); #else set_psw(PSW_SET_ISP(get_psw(), PSW2ISP(saved_psw))); #endif } /* * CPUロック状態の参照 */ bool_t x_sense_lock(void) { return lock_flag; } /* * 割込み優先度マスク(IPM) の設定 * 指定した割込み優先度(-1, -2, ..., TMIN_INTPRI) を元に * プロセッサの割込み優先度レベル (IPL) を設定する. */ void x_set_ipm(PRI intpri) { set_psw(PSW_SET_ISP(get_psw(), IPM2ISP(intpri))); } PRI x_get_ipm(void) { return (ISP2IPM(PSW2ISP(get_psw()))); } /* * (7) dispacher での割込み待ち */ void idle_loop(void) { t_unlock_cpu(); t_lock_cpu(); } /* * プロセッサ依存の初期化 */ void prc_initialize(void) { } /* * プロセッサ依存の終了処理 */ void prc_terminate(void) { /* 特に必要な処理はない */ } /* * 割込み要求禁止フラグのセット */ bool_t x_disable_int(INTNO intno) { volatile uint8_t *reg_addr; /* レベル定義が0である場合はCFG_INTされていない */ if(intpri_table[intno] == 0U) { return (false); } // 割込みマスク・フラグ・レジスタの該当ビットを1にセット if(intno < 32) { reg_addr = (volatile uint8_t *)TADR_MK0L; reg_addr += (intno/8); } else { reg_addr = (volatile uint8_t *)TADR_MK2L; reg_addr += ((intno-32) / 8); } *reg_addr |= (uint8_t)(1 << (intno % 8)); return(true); } /* * 割込み要求禁止フラグのクリア */ bool_t x_enable_int(INTNO intno) { volatile uint8_t *reg_addr; /* レベル定義が0である場合はCFG_INTされていない */ if(intpri_table[intno] == 0u) { return (false); } // 割込みマスク・フラグ・レジスタの該当ビットを0にセット if(intno < 32) { reg_addr = (volatile uint8_t *)TADR_MK0L; reg_addr += (intno/8); } else { reg_addr = (volatile uint8_t *)TADR_MK2L; reg_addr += ((intno-32) / 8); } *reg_addr &= (uint8_t)~(1 << (intno % 8)); return(true); } /* * 割込み要求のクリア */ void x_clear_int(INTNO intno) { volatile uint8_t *reg_addr; // 割込み要求フラグ・レジスタの該当ビットを0にセット if(intno < 32) { reg_addr = (volatile uint8_t *)TADR_IF0L; reg_addr += (intno/8); } else { reg_addr = (volatile uint8_t *)TADR_IF2L; reg_addr += ((intno-32) / 8); } *reg_addr &= (uint8_t)~(1 << (intno % 8)); } /* * 割込み要求のチェック */ bool_t x_probe_int(INTNO intno) { volatile uint8_t *reg_addr; // 割込み要求フラグ・レジスタの該当ビットが 1 なら true if(intno < 32) { reg_addr = (volatile uint8_t *)TADR_IF0L; reg_addr += (intno/8); } else { reg_addr = (volatile uint8_t *)TADR_IF2L; reg_addr += ((intno-32) / 8); } return((*reg_addr & (uint8_t)(1 << (intno % 8))) != 0); } /* * 割込み要求ラインの属性の設定 */ void x_config_int(INTNO intno, ATR intatr, PRI intpri) { volatile uint8_t *reg_addr; uint8_t portno; assert(VALID_INTNO_CFGINT(intno)); assert(TMIN_INTPRI <= intpri && intpri <= TMAX_INTPRI); /* * 割込みのマスク * * 割込みを受け付けたまま,レベルトリガ/エッジトリガの設定や,割 * 込み優先度の設定を行うのは危険なため,割込み属性にかかわらず, * 一旦マスクする. */ (void) x_disable_int(intno); /* * 優先度の設定 */ // 優先順位指定フラグ・レジスタの該当ビットに値をセット if(intno < 32) { reg_addr = (volatile uint8_t *)TADR_PR00L; reg_addr += (intno/8); } else { reg_addr = (volatile uint8_t *)TADR_PR02L; reg_addr += ((intno-32) / 8); } // 優先順位レベルの設定(低位ビット) if((IPM2ILVL(intpri) & 0x01) != 0) { *reg_addr |= (uint8_t)(1 << (intno % 8)); } else { *reg_addr &= (uint8_t)~(1 << (intno % 8)); } // 優先順位レベルの設定(高位ビット) if((IPM2ILVL(intpri) & 0x02) != 0) { *(reg_addr+4) |= (uint8_t)(1 << (intno % 8)); } else { *(reg_addr+4) &= (uint8_t)~(1 << (intno % 8)); } /* * トリガの設定 */ if(intno <= 7) { reg_addr = (volatile uint8_t *)TADR_EGP0; // EGP0 portno = (uint8_t)(intno - 2); } else { reg_addr = (volatile uint8_t *)TADR_EGP1; // EGP1 portno = (uint8_t)(intno - 29); } /* INT端子の場合は割込み検知方法を設定する */ if((intatr & TA_POSEDGE) != 0U) { // 外部割込み立ち上がりエッジ許可レジスタの該当ビットを1にセット *reg_addr |= (uint8_t)(1 << (portno % 8)); // 外部割込み立ち下がりエッジ許可レジスタの該当ビットを0にセット *(reg_addr+1) &= (uint8_t)~(1 << (portno % 8)); } else if((intatr & TA_NEGEDGE) != 0U) { // 外部割込み立ち上がりエッジ許可レジスタの該当ビットを0にセット *reg_addr &= (uint8_t)~(1 << (portno % 8)); // 外部割込み立ち下がりエッジ許可レジスタの該当ビットを1にセット *(reg_addr+1) |= (uint8_t)(1 << (portno % 8)); } else if((intatr & TA_BOTHEDGE) != 0U) { // 外部割込み立ち上がりエッジ許可レジスタの該当ビットを1にセット *reg_addr |= (uint8_t)(1 << (portno % 8)); // 外部割込み立ち下がりエッジ許可レジスタの該当ビットを1にセット *(reg_addr+1) |= (uint8_t)(1 << (portno % 8)); } else { // どちらでもない場合はエッジ検出を禁止 // 外部割込み立ち上がりエッジ許可レジスタの該当ビットを0にセット *reg_addr &= (uint8_t)~(1 << (portno % 8)); // 外部割込み立ち下がりエッジ許可レジスタの該当ビットを0にセット *(reg_addr+1) &= (uint8_t)~(1 << (portno % 8)); } /* * 割込みのマスク解除(優先度設定) */ if ((intatr & TA_ENAINT) != 0U) { (void) x_enable_int(intno); } } /* * NMIを除くすべての割込みの禁止 */ uint8_t TOPPERS_disint(void) { volatile uint8_t TOPPERS_psw; TOPPERS_psw = get_psw(); DI(); return(TOPPERS_psw); } /* * 割込み優先度マスク(内部表現)の現在値の設定 */ void TOPPERS_enaint(uint8_t TOPPERS_psw) { if(TOPPERS_psw & PSW_IE_MASK) { EI(); } }