リアルタイムOSの内部構造を見てみよう!

第05回 SH3のアーキテクチャ

次の回からは,さらに踏み込んでASPカーネルを紐解いていきます.そうなるとどうしても,プロセッサ依存の部分がでてきますので,プロセッサアーキテクチャを知る必要があります.そこで今回は,対象とするターゲットSH3のアーキテクチャについて簡単に説明します.特に,汎用レジスタ,ステータスレジスタ,割込み発生時のプロセッサの処理が重要になります.
Super-Hシリーズ
・RISC型の組込み用マイクロプロセッサ
・16ビット固定長命令と,5段のパイプライン

SH3
SuperHの第3世代目
SH1,2が割込みベクタテーブルを採用していたのに対して,SH3はどんな割込みが発生しても飛ぶ場所は1か所という仕様です.どこに分岐するかはソフトウェアで実現します.

SH7727
・SH3+X/Yメモリ+DSPモジュール
・ASPカーネルでは,内蔵タイマ(TMU0)と外部のSIO(ST16C2550CQ48)をカーネルの出力(SYSLOG出力)に使用しています.
動作モード
CPUの動作モードには,特権モードとユーザーモードがありますが,ASPカーネルでは,カーネルもタスクも特権モードで動いています(第3回で解説済).どちらのモードで動作するかは,ステータスレジスタ(SR)のMDビットにより変更します.今回は常に特権モードで動きますので,常にSR.MDは1となります(1:特権モード,2:ユーザーモード).

レジスタ構成
SH3のレジスタ構成について解説します.

汎用レジスタ:R0〜R15 (R0_BANK0〜R7_BANK0,R0_BANK1〜R7_BANK1,R8〜R15)
制御レジスタ:GBR,SR,SSR,SPC
システムレジスタ:MACH/MACL,RP(リターンアドレスが入る),PC(プログラムカウンタ)

○汎用レジスタ
汎用レジスタは,R0〜R15までの計16本用意されています.この16本の汎用レジスタのうちR0〜R7の8本は,BANK0とBANK1の2枚のレジスタバンク構成となっています.【図5-1】



【図5-1 CPUレジスタ構成】

R0〜R7レジスタは,物理的には2つありますが,一度に見えるのはどちらか1つです.どちらがその時見えるかは,ステータスレジスタのRBビットにより切り替えます.つまり,プログラムではr0と記述して,アクセスしますが,実際に,どちらのバンクのR0にアクセスするかは,RBビットの設定に依存します.RB = 0 でBANK0が,RB = 1 でBANK1が見える仕組みです.r0_bankと記述すれば裏バンクのR0にアクセスできます.
ASPカーネルでは,このバンク構成を割込みの入口で使用します.
このように,汎用レジスタの一部にバンクを持つことで,例外処理の高速化が期待できます,通常,例外処理では作業領域を得るために汎用レジスタの退避/復帰処理を行いますが,SHではレジスタバンクを用いることで,退避/復帰作業をハードウェアで行うため,処理にかかるオーバーヘッドが軽減されます.
もう少し,具体的に見ていきましょう.
普段はBANK0を使っていますが,割込みが発生すると,自動的にRBビットが1となりBANK1に切り替わる仕組みになっています.そうすることで,もともと使っていたレジスタを破壊せずに切り替えをすることができます.このようにレジスタバンクを切り替えることで,退避/復帰作業をハードウェアで行うため,処理にかかるオーバーヘッドが軽減される仕組みになっているのです.
割込みの入り口のプログラムを読むときはすでに,ハードウェアによってレジスタバンクがBANK1に切り替わっていることに注意します.

GNU Compilerでのレジスタ割り当て

SH3ではスタックポインタは専用のレジスタとして用意していません.どの汎用レジスタをスタックポインタとして使用してもいいですが,GNUコンパイラはR15をスタックポインタで使用します.以下に,GNU Compilerでのレジスタ割り当てを示します.

R0:返却値 関数の戻り値
R1-R3:スクラッチレジスタ 
呼び出された関数は保存せずに破壊してもいいというきまり.必要ならば自分でスタック上に保存する必要がある.
R4-R7:引数 引数5つ以上の場合は,スタックに積む.
R8-R13:呼び出し先が退避すべき作業レジスタ.
呼び出された関数で使う場合は保存する必要がある.
R14:フレームポインタ
R15:スタックポインタ

ASPのソースコードを読む際には,
・R0〜R7:呼び出された関数では,破壊してもよいレジスタ(コーラーセーブドレジスタ)
・R8〜R13; 呼び出された側で保存(コーリーセーブドレジスタ)
ということに注意してみてください.
これは,ディスパッチのところで関係してきますので,後日詳しく解説します.




○制御レジスタ
SR:ステータスレジスタ
ステータスレジスタは,CPUの動作状態を表すいくつかのフラグビットによって構成されます.具体的には,動作モード切り替えビット(MD),例外処理を禁止するブロックビット(BL),現在使用中のレジスタバンクを示すビット(RB),条件付き分岐に使用するフラグ(T)と,15レベルの割込みマスク4ビット(I)などがあります.

ステータスレジスタ


名称 内容
MD
処理モードビット
今回は,常に特権モードなので,値は,1固定
レジスタバンクビット
RB
どちらのバンクを使うか
1”のとき,R0_BANK1〜R7_BANK1 R8〜R15が汎用レジスタとなる.
“0”のとき,R0_BANK0〜R7_BANK0 R8〜R15が汎用レジスタとなる.
 例外が発生すると自動的に”1”となり,BANK1が見えるようになる.
ブロックビット
BL
1のときに例外・割込みを抑止する.
1の時に,例外が発生すると,リセットがかかってしまう仕様.割込みの禁止には使っていない.
割込みマスクビット
I3−I0 
割込み要求マスクレベルを表す4ビットデータ
値が大きいほど優先度が高い.1111がMAXですべての割込みを受け付けない,割込み禁止となる.
 
分岐のためのフラグ
0か1かで分岐するかどうかを決める.


GBR:グローバルベースレジスタ
GBR間接アドレッシング時のベースアドレスを保持します.

VBR:ベクタベースレジスタ
割込みが発生したときに,まず決められた場所に飛びます.そのアドレスを格納します.この値を変えることによって,任意の場所に割込みを置くことができます.

SPC:退避プログラムカウンタ(Saved PC)
例外が発生した際,復帰先の命令アドレス(PC)を保持します.

SSR:退避ステータスレジスタ(Saved SR)
例外処理発生時,SRを退避するレジスタ



○システムレジスタ
PC:プログラムカウンタ
現在実行中のメモリの番地を格納します.

PR:プロシージャーレジスタ
サブルーチンプロシージャーに分岐する際,戻るべきアドレス(PC+2)を保持します.関数呼び出しなどに利用.

SHでは,割込みやリセット,アドレスエラーの発生,TRAP命令など,PCの変更を行う要求を例外処理と呼びます.

例外処理のシーケンス
プログラム実行中に例外が発生すると,プロセッサは次の動作を行います.
・PCをSPCに退避
・SRをSSRに退避
・割込みを禁止(SR.BL = 1),特権モード(SR.MD = 1)
・R0〜R7をBANK1に切り替える(SR.RB = 1)
・例外処理ルーチンを実行

 ここまでが,プロセッサが行うことです.すでにRBビットが1になっていることに注意してください.

例外処理ルーチンの配置場所
リセット 0x00
内部要因 VBR + 100h
TLBミスヒット VBR + 400h
NMI,外部要因(外部割込み) VBR + 600h
つまり,割込みが発生すると,VBR+600番地からプログラムが実行されます.カーネルでは,この位置に割込みが発生したときに実行するプログラムを置いています.

例外処理ルーチンからの復帰
例外処理中に例外復帰命令(RTE)を実行すると,プロセッサは次の処理を行います.

・SPCをPCに復帰 
・SSRをSRに復帰
例外処理の入り口でSPCとSSRに保存したPCとSRをもとに戻します.

カーネルの割込みの出口処理では,RTE命令を発行しています.

例外処理に関するレジスタ
600番地の割込み入り口処理プログラムは,どの割込みが入ったかをプログラムで判断する必要があります.割込み事象レジスタに,発生した割込みの割込み要因番号が設定されます.このレジスタを読んでどの割込みが発生したかをソフトウェアで判断します.

割込み事象レジスタ(INTEVT)
割込み事象レジスタ2(INTEVT2)
割込み発生時に割込みの要因が設定されます.

今回のSH7727では, INTEVT2を参照する必要があります.

割込み関連の機能
○プロセッサの割込み優先度(IPM)
SRのビット7,6,5,4に割込み優先度が設定されます.

○各割込みの割込み優先度
割込み優先順位レジスタ(IPRA〜IPRG)に設定.
割込み要因ごとに,設定するレジスタとビット位置が決まっています.

○割込み要因の判定
割込み要因ごとに割込み番号を持っています.
割込み受付後,例外事象レジスタ(INTEVT2)にその番号が設定されます.


割込み処理の流れ(まとめ)
割込みが発生した時に,プロセッサが行うことをもう一度まとめます.

・ PCとSRをそれぞれSPC,SSRに退避
・ SRのBLを1にセット.以降すべての例外をブロック
・ SRのMDを1にセット.特権モードへ(ASPカーネルでは,タスクや割込みハンドラは特権モードで動作している)
・ SRのRBを1にセット,レジスタバンク1を使用
・ 例外要因をINTEVTとINTEVT2の該当するビットに書き込む.(ASPでは,INTEVT2を使用します.)
・ VBR+0x600から例外処理ルーチンを実行

多重割込み
割込みが発生した時,上記のことをプロセッサが行います.
割込みを受け付けた後,ハンドラ実行中に他の割込みを受け付けること(多重割込み)は,リアルタイム性が求められる場合には必要です.ASPカーネルでは多重割込みを受け付け可能とするために,割込みを許可する前に,次のことを行っています.(つまり,プロセッサでなくカーネルで処理するべき事項です.)

・SR.I3-I0に,受け付けた割込み優先度を設定する
  今受け付けた割込みより,低い優先度を受けつける必要はないので,プロセッサの割込み優先度を,受けつけた割込み優先度に上げる必要があります.

・SSR,SPCの退避
  割込みが入ると,SSR SSCが自動的に上書きされ,前の値が消されてしまうので退避が必要.

・BLビットをクリア

これ以降,高優先度の割込みを受け付けることになります.

ここまでの内容を以下の図でまとめます.【図5-2】
割込み発生時に,プロセッサがやってくれることと,カーネルプログラムが行うことを区別して理解してください.(今回の該当部分の処理のみを抜き出しています.)



【図5-2 割込み発生時の処理】

カーネル内の例外処理ルーチンについては,後日詳細を解説します.

この連載は,年末年始はお休みさせていただきます.新年は1月8日更新予定です.みなさまよいお年を...