start.asm

start.asm ( m68k実装ではstart.s ) では次のことを行います。

  • 最低限のコアレジスタ初期化
  • 作業用のスタック設定
  • イベントベクトルの設定
  • IVG15への遷移と割り込み禁止の解除

最低限のコアレジスタ初期化

SYSCFGとLCxとLxを0で初期化します。
SYSCFGはシステム設定用のコアレジスタです。このレジスタはBF533のRev0.2ではアノーマリによってソフトで初期化されることが求められています。そこでstart.asmの中で初期化を行います。
LCxレジスタはループカウンタです。これが0でないと乱数で初期化されたLTx、LBxで構成されるループを実行してしまいます。そのために真っ先にループカウンタを0にしてしまいます。
Lxはコンパイラの作業モデルとして0であることが求められるのでやはり0に初期化しておきます。

作業用のスタック設定

startエントリーから始まるコードは最終的にC言語で書かれたkernel_start()を呼ぶため、スタックが必要です。そこでイベント割り込みスタックを一時的にスタックとして設定します。kernel_startはexit_and_dispatch()を呼ぶことで最終的にスタックを放棄するため、この部分はそれほど神経質に扱う必要はありません。

イベントベクトルの設定

イベントベクトルはイベントハンドラのアドレスです。イベントハンドラアセンブリ言語で記述されており、TOPPERS/JSPが要求する一風変わった割り込み処理方法を実装します。内部からはユーザー定義のC関数を呼び出します。このC関数がユーザーから見た割り込みハンドラになります。

IVG15への遷移と割り込み禁止の解除

ここが一番おもしろい部分です。TOPPERS/JSP for BLACKfinではすべてのタスクをスーパーバイザーモードで動かします。リセット直後の状態もスーパーバイザーモードですが、そのままでは優先順位が高すぎて割り込みを受け付けられませんのでrti命令を実行してリセット状態から抜けなければなりません。
ところが、rtiを実行するとユーザー状態になってしまいます。ユーザー状態からはraise命令を使って割り込みを起こすことが出来ません。そこで、rti命令実行前にraise命令を使ってIVG15割り込みを発生します。発生した割り込みはILATレジスタに登録されますが、まだ実行レベルが高すぎて受け付けられません。この割り込みはrti命令実行後に遅延実行されることになります。遅延割り込みによってリセット状態からユーザーモードに遷移し、自動的にスーパーバイザー状態に最遷移することができます。

    r0.L = task_level;    // IVG15はタスクに遷移するためのエントリー
    r0.H = task_level;
    [p0++p1] = r0;        // IVG15のイベントベクトル
    
    p2.L = user;          // ダミーの戻り番地を設定
    p2.H = user;
    reti = p2;
    csync;
    raise    15;          // IVG15を生起する。割り込みは遅延発生する。
    
    p0.H = (IMASK>>16)&0xffff;
    p0.L = IMASK&0xffff;
    r0 = 0x801F(z);       // IVG15を受付可能に
    [p0] = r0;
    csync;
    rti;                  // ユーザーモードへ遷移する
    
task_level:               // ここからタスクの実行順位
    [--sp] = reti;        // 戻り番地を捨てて割り込み可能にする
    jump _kernel_start;
user:
    jump    user;