マイクロコントローラのリセット時に各PE(プロセッサ・エレメント)のプログラム・カウンタが分岐してくるアドレスに,PEごとのエントリ・ポイント・アドレスへの分岐命令を配置します。RESETベクタのアドレスを保持するRBASEレジスタが512バイト単位で値を保持するため,RESETベクタの先頭は512バイトに整列します。
.section "RESET_PE1", text .align 512 jr32 __start ; RESET .align 16 jr32 _Dummy ; SYSERR : .align 16 jr32 _Dummy_EI ; INTn(priority15) |
セクション名は任意に変更可能ですが,最適化リンカの-startオプションと連動して変更する必要があります。
各PEのリセット時の分岐先が同一のアドレスである場合,1つのRESET_PEnセクションを各PEで共有して使用します。
拡張仕様(テーブル参照方式)の例外ハンドラ・アドレスを使用する場合,使用する例外ハンドラ・ルーチンのアドレスを本テーブルの対応する要素位置に配置します。テーブル・アドレスを保持するINTBPレジスタが512バイト単位で値を保持するため,テーブルの先頭は512バイトに整列します。
サンプルではEIINTTBL_PEnセクションに配置しています。
.section "EIINTTBL_PE1", const .align 512 .dw #_Dummy_EI ; INT0 .dw #_Dummy_EI ; INT1 .dw #_Dummy_EI ; INT2 .rept 512 - 3 .dw #_Dummy_EI ; INTn .endm |
セクション名は任意に変更可能ですが,スタートアップ内のINTBPレジスタ設定処理と連動して変更する必要があります。
FE,EI各レベルの例外ハンドラ・ルーチンのサンプルです。 何もせず自分自身への分岐を繰り返します。
通常は,Cソース記述で#pragma interruptを用いて用意します。
リセット時にRESETベクタから分岐してくるラベル(アドレス)です。
ロックステップ機能を使用する準備として,各PEの汎用レジスタと,EIPC,CTPC,FPEPCレジスタを初期化します。
$nowarning mov r0, r1 $warning mov r0, r2 mov r0, r3 : mov r0, r31 ldsr r0, 0, 0 ; EIPC ldsr r0, 16, 0 ; CTPC |
FPEPCはFPUを有効にした後でなければ初期化できないため,後で初期化します。詳細は「FPUの初期設定」を参照してください。
各PEが共通に実行する処理です。自分自身のPEID(プロセッサ・エレメント番号)値を読み出し,その値から各PEごとに用意された初期化処理へ分岐します。
stsr 0, r10, 2 ; get HTCFG0 shr 16, r10 ; get PEID cmp 1, r10 bz .L.entry_PE1 cmp 2, r10 bz .L.entry_PE2 : cmp 7, r10 bz .L.entry_PE7 |
使用しないPEを待機させておくための,自分自身への分岐を繰り返すのみのルーチンです。
各PE用に用意したハードウェア初期化処理(_hdwinit_PEn)と,例外ハンドラ・アドレスの拡張仕様(テーブル参照方式)を使用するための設定処理(_set_table_reference_method)を呼び出し,ユーザ・プログラム向けの初期化ルーチン(_cstart_pmn)へ分岐します。
.L.entry_PE1: jarl _hdwinit_PE1, lp ; initialize hardware mov #__sEIINTTBL_PE1, r6 jar _set_table_reference_method, lp ; set table reference method jr32 __cstart_pm1 |
サンプルではECC機能を使用するための準備として,RAM領域を初期化します。PE1用の初期化処理でGlobal RAMとLocal RAM(PE1用)を,PE2用の初期化処理でLocal RAM(PE2用)を初期化します。