TOPPERS/ASP3カーネル GIC(ARM Generic Interrupt Controller)依存部 設計メモ 対応バージョン: Release 3.0.0 最終更新: 2016年1月16日 ---------------------------------------------------------------------- TOPPERS/ASP Kernel Toyohashi Open Platform for Embedded Real-Time Systems/ Advanced Standard Profile Kernel Copyright (C) 2014-2016 by Embedded and Real-Time Systems Laboratory Graduate School of Information Science, Nagoya Univ., JAPAN 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改 変・再配布(以下,利用と呼ぶ)することを無償で許諾する. (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 権表示,この利用条件および下記の無保証規定が,そのままの形でソー スコード中に含まれていること. (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 の無保証規定を掲載すること. (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 用できない形で再配布する場合には,次のいずれかの条件を満たすこ と. (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 作権表示,この利用条件および下記の無保証規定を掲載すること. (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに 報告すること. (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを 免責すること. 本ソフトウェアは,無保証で提供されているものである.上記著作権者お よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的 に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ アの利用により直接的または間接的に生じたいかなる損害に関しても,そ の責任を負わない. $Id: gic_design.txt 533 2016-01-15 23:29:33Z ertl-hiro $ ---------------------------------------------------------------------- ○目次 ・参考文献 ・GIC依存部の位置づけ - GIC依存部を構成するファイル ・チップ依存のパラメータ - アプリケーションから参照できるパラメータ - カーネル内部で使用するパラメータ ・GICにおける割込みハンドラおよびCPU例外ハンドラの出入口処理 - GICにおける割込みハンドラの出入口処理 - GICにおけるCPU例外ハンドラの出入口処理 ○参考文献 [1] TOPPERSプロジェクト 設計メモ「GIC(ARM Generic Interrupt Controller)に関するメモ」. ○GIC依存部の位置づけ GIC依存部は,カーネルのターゲット依存部の中で,GICアーキテクチャ (GICv1およびGICv2)に準拠した割込みコントローラを持つチップに共通に使 用できる部分である.また,GICの前身と思われるARM11 MPCoreのDistributed Interrupt Controllerにも適用できるように実装する. TOPPERS_SAFEG_SECUREがマクロ定義されている場合には,GICがセキュリティ拡 張されていることを想定し,セキュアモードで使用するものとする. GICv1とGICv2でレジスタ名が変更になっているが,ソースコード中では, GICv2のレジスタ名を使用する. ●GIC依存部を構成するファイル GIC依存部は,次の3つのファイルで構成される. arch/arm_gcc/common/ gic_kernel_impl.h カーネルの割込みGIC依存部のヘッダファイル gic_kernel_impl.c カーネルの割込みGIC依存部 gic_support.S カーネルの割込みGIC依存部のアセンブリ言語部 ○チップ依存のパラメータ ●アプリケーションから参照できるパラメータ target_kernel.h(または,そこからインクルードされるファイル)で,以下の 定数をマクロ定義しておく. (1) TMIN_INTPRI 割込み優先度の最小値(最高値) (2) TMAX_INTPRI 割込み優先度の最大値(最低値) TMAX_INTPRIは,-1に定義する.TMAX_INTPRIは,ターゲットチップのGICでサポー トする割込み優先度の段数により,-15,-31,-63,-127,-255のいずれかに定 義する. ●カーネル内部で使用するパラメータ target_kernel_impl.h(または,そこからインクルードされるファイル)から gic_kernel_impl.hをインクルードする前に,必要に応じて,以下の定数をマク ロ定義しておく. (1) GIC_TNUM_INTNO 割込みの数 ターゲットチップのGICがサポートする割込みの数.SGI(Software Generated Interrupt),PPI(Private Peripheral Interrupt),SPI(Shared Peripheral Interrupt)の合計数. (2) GICC_BASE CPUインタフェースのベースアドレス (3) GICD_BASE ディストリビュータのベースアドレス GICのCPUインタフェースおよびディストリビュータのベースアドレス. (4) TOPPERS_SAFEG_SECURE セキュアモード(オプション) セキュアモードでカーネルを動作させ,FIQをカーネル管理の割込みと扱う場合 に,このシンボルをマクロ定義する. (5) GIC_ARM11MPCORE ARM11 MPCoreへの対応(オプション) ARM11 MPCoreのDistributed Interrupt Controllerの場合には,このシンボル をマクロ定義する. ○GICにおける割込みハンドラおよびCPU例外ハンドラの出入口処理 ●GICにおける割込みハンドラの出入口処理 GICにおける割込みハンドラの出入口処理(irc_begin_intおよびirc_end_int) の実現方法には,いくつかのアプローチがある. 【アプローチ1】 このアプローチは,GICの想定している(よって,最もシンプルな)ものである. 割込みハンドラの入口では何も行わず,割込みハンドラの出口でEOIを発行する. ---------------------------------------- ALABEL(irc_begin_int) /* * 割込み要因を取得する. */ ldr r1, =GICC_IAR ldr r3, [r1] push {r3} /* irc_end_intで用いる情報を保存 */ /* * 割込み番号を返値としてリターンする. */ lsl r0, r3, #22 /* 下位10ビットを取り出す */ lsr r0, r0, #22 bx lr ALABEL(irc_end_int) /* * EOIを発行してリターンする. */ pop {r3} /* irc_begin_intで保存した情報を復帰 */ ldr r1, =GICC_EOIR /* EOIレジスタへの書込み */ str r3, [r1] bx lr ---------------------------------------- このアプローチには,次の問題点がある. (1) 割込みハンドラからのリターン時に,割込み優先度マスクを元に戻すとい う仕様を実装していると言えるか微妙である.特に,CPU例外ハンドラをこれと 整合するように実装した場合,割込み優先度マスクを一切操作しないという実 装になり,仕様に準拠していないように思われる. (2) 割込み優先度が256段階ある時(この場合,ARM GICでは,割込み優先度の すべてのビットをプリエンプションに使うという設定ができない)に,このア プローチでは,割込み優先度のすべてのビットをプリエンプションに使うこと ができず,TOPPERS標準割込み処理モデルからの逸脱となる. (3) 割込みハンドラから割込み優先度マスクを参照/設定することができない. ASP3カーネルでは問題ないが,ATK2カーネルでは,このアプローチは用いるこ とができない. 【アプローチ2】 問題点(1)と(3)を解決するためには,発生した割込み要因の割込み優先度を, 割込み優先度マスクに設定しておく方法が考えられる. ---------------------------------------- ALABEL(irc_begin_int) /* * 割込み要因を取得する. */ ldr r1, =GICC_IAR ldr r3, [r1] /* * 割込み要因の割込み優先度を求め,割込み優先度マスクに設定する. */ ldr r1, =GICC_RPR /* 受け付けた割込みの割込み優先度を取得 */ ldr r0, [r1] ldr r1, =GICC_PMR /* 割込み発生前の割込み優先度を取得 */ ldr r2, [r1] str r0, [r1] /* 新しい割込み優先度マスクをセットする */ DATA_SYNC_BARRIER /* 割込み優先度マスクがセットされるのを待つ */ push {r2,r3} /* irc_end_intで用いる情報を保存 */ /* * 割込み番号を返値としてリターンする. */ lsl r0, r3, #22 /* 下位10ビットを取り出す */ lsr r0, r0, #22 bx lr ALABEL(irc_end_int) /* * EOIを発行する. */ pop {r2,r3} /* irc_begin_intで保存した情報を復帰 */ ldr r1, =GICC_EOIR /* EOIレジスタへの書込み */ str r3, [r1] /* * 割込み優先度マスクを元に戻してリターンする. */ ldr r1, =GICC_PMR str r2, [r1] bx lr ---------------------------------------- しかし,このアプローチでは,アプローチ1の2つめの欠点は解決できない. 【アプローチ3】 アプローチ1の2つめの欠点を解決するためには,割込みハンドラの入口処理で EOIを発行してしまう方法が考えられる. ---------------------------------------- ALABEL(irc_begin_int) /* * 割込み要因を取得する. */ ldr r1, =GICC_IAR ldr r3, [r1] /* * 割込み要因の割込み優先度を求め,割込み優先度マスクに設定する. */ ldr r1, =GICC_RPR /* 受け付けた割込みの割込み優先度を取得 */ ldr r0, [r1] ldr r1, =GICC_PMR /* 割込み発生前の割込み優先度を取得 */ ldr r2, [r1] str r0, [r1] /* 新しい割込み優先度マスクをセットする */ DATA_SYNC_BARRIER /* 割込み優先度マスクがセットされるのを待つ */ push {r2} /* irc_end_intで用いる情報を保存 */ /* * EOIを発行する. */ ldr r1, =GICC_EOIR /* EOIレジスタへの書込み */ str r3, [r1] /* * 割込み番号を返値としてリターンする. */ lsl r0, r3, #22 /* 下位10ビットを取り出す */ lsr r0, r0, #22 bx lr ALABEL(irc_end_int) /* * 割込み優先度マスクを元に戻してリターンする. */ pop {r2} /* irc_begin_intで保存した情報を復帰 */ ldr r1, =GICC_PMR /* 割込み優先度マスクを元に戻す */ str r2, [r1] bx lr ---------------------------------------- 現在の実装では,アプローチ3を採用している. ●GICにおけるCPU例外ハンドラの出入口処理 GICにおけるCPU例外ハンドラの入口処理(irc_begin_exc)では,CPU例外発生 前の割込み優先度マスクをスタックに保存し,CPU例外ハンドラの入口処理 (irc_end_exc)で割込み優先度マスクを元に戻す. ---------------------------------------- ALABEL(irc_begin_exc) /* * 割込み優先度マスクを保存する. */ ldr r1, =GICC_PMR /* 現在の割込み優先度を取得 */ ldr r2, [r1] push {r2} /* irc_end_excで用いる情報を保存 */ bx lr ---------------------------------------- ALABEL(irc_end_exc) /* * 割込み優先度マスクを元に戻す. */ pop {r2} /* irc_begin_excで保存した情報を復帰 */ ldr r1, =GICC_PMR /* 割込み優先度マスクを元に戻す */ str r2, [r1] bx lr ---------------------------------------- 以上