いろんなものはつながっている

組み込みOS自作入門(8)割り込み処理

割り込みの種類

・外部ハードウェアによって割り込線がアサートさせることで発生する割り込み
・不正メモリアクセスやゼロ除算などによりCPU内部で発生する割り込み
・システムコール命令やトラップ命令などによりプログラム側からわざと発生させる割り込み

割り込みコントローラ

割り込み入力が1本のとき割り込みコントローラでまとめる。割り込みが発生したとき、どこから張り込みが発生したのかわからないので割り込みコントローラのレジスタをみにいって判断する。

割り込み1

割り込みがおこったときの流れ

1.スタックにプログラムカウンタとCCR(コンディションコードレジスタ)の値を保存する
2.割り込み要因に応じて割り込みベクタを参照し割り込みハンドラにジャンプする(プログラムカウンタに割り込みベクタの値を設定する)。
3.割り込みハンドラが実行される。
4.割り込みハンドラ終了時に割り込み復帰命令(rte)をよぶ。これによりスタックからプログラムカウンタとCCRの値がレジスタに復旧されてもとにもどり中断していた個所から実行が再開される。

正確ではないかもしれないが自分が理解したイメージ図は以下。

割り込み発生時はプログラムカウンタに設定されているアドレス位置の命令を実行しており、

割り込み2

割り込みが発生したらプログラムカウンタやレジスタに値をスタックに保存する。
割り込み3

割り込み前の処理の情報をスタックに退避させたのち、割り込みハンドラの処理を行う。

割り込み4

割り込みハンドラの処理がおわったら割り込み前に行っていた処理を再び実行するため、スタックに退避していたレジスタの値を戻す。
割り込み5

割り込み前の処理を引き続き行う。

割り込み6

割り込みハンドラの登録

私が理解した割り込みベクタ、割り込みハンドラ、割り込み処理の実態のメモリ配置イメージ図は以下。

割り込み7

割り込みベクタに割り込みハンドラを登録する。何番目が何の割り込みに対するものかCPUで決まっている。例えば、リセットは0番、トラップ命令は8~11番、外部割込みはは12~17番に割り当てられている。

void (*vector[])(void) = {
    start, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    intr_syscall, itr_softerr, itr_softerr, itr_softerr,
    NULL, ....

割り込みベクタで定義されている割り込みハンドラでレジスタの退避をし割り込み処理の関数(iterrupt)をよんでいる。

_intr_softerr:
	mov.l	er6, @-er7 /*                */
	mov.l	er5, @-er7 /*                */
	mov.l	er4, @-er7 /*                */
	mov.l	er3, @-er7 /*汎用レジスタ値を*/
	mov.l	er2, @-er7 /*スタックに保存  */
	mov.l	er1, @-er7 /*                */
	mov.l	er0, @-er7 /*                */
	mov.l	er7, er1   /* 第2引数にスタックポインタを設定*/
	mov.w	#SOFTVEC_TYPE_SOFTERR, r0 /*第1引数に割り込み処理の */
					 /*種類を設定              */
	jsr	@_interrupt/* interrupt()の呼び出し */
	mov.l	@er7+, er0 /*                */
	mov.l	@er7+, er1 /*                */
	mov.l	@er7+, er2 /*スタックから    */
	mov.l	@er7+, er3 /*汎用レジスタ値を*/
	mov.l	@er7+, er4 /*もどす          */
	mov.l	@er7+, er5 /*                */
	mov.l	@er7+, er6 /*                */
	rte

interrupt()はソフトウェア割り込みベクタを処理するための共通割り込みハンドラとして定義されている

void interrupt(softvec_type type, unsigned long sp)
{
    softvec_handler_t handler = SOFTVEC[type];
    if(handler)
        handler(type, sp);
}

もちろん、SOFTVEC[type]に応じた関数をあらかじめ登録しておく必要がある。そのための関数softvec_setintrが用意されている。

int softvec_setintr(softvec_type_t type, softvec_handler_t handler)
{
    SOFTVECS[type] = handler;
    return 0;
}

この関数を用いて割り込み時処理する関数をf(softvec_type type, unsigned long sp)というインターフェースで作成しておき、

INTR_DISABLE;  /*  */
softvec_setintr(SOFTVEC_TYPE_SERINTR, f);

というように登録する。

関連記事

コメント

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

スポンサード リンク

カテゴリー

スポンサード リンク