既にマイコン内のROMに焼きこまれたプログラムにパッチを当ててプログラムを修正する手段としてROMコレクション機能があります。
この機能は既にあるプログラムを修正できると言う便利な機能ですが、
いつでも無条件で使用できるものではありません。
この機能を使用するには前もって、そのための処理の一部をプログラム中に埋め込んでおく必要がありますし、
代わりに実行させるプログラムを読み込むための外部メモリも必要になります。
ROMコレクションの動作やそのために必要なこと等について以下に説明します。
[1] ROMコレクションの基本的な動作
ROMコレクションでは CPU (ハードウエア) が自動的に実行する部分と、
アプリケーション側で対応すべき部分とが混在しているので、これらを区別して考える必要があります。
既に、必要な設定が行われた状態でROMコレクションの動きを以下に示します。
78K0でのROMコレクション処理の動きの概略
| (1) |
プログラム実行中、CPUが命令をフェッチする際にそのフェッチ・アドレスと、
CORADnレジスタに設定されているROMコレクション・アドレスとの比較を行い、
アドレスが一致した場合には本来の命令ではなく、分岐命令 (BR !0F7FDH命令) を実行します。
置き換えられた分岐命令の実行によりそれまでの処理を中断して 0F7FDH番地に分岐します。
このとき、どのコレクション・アドレスでの一致が発生したかをCORCNレジスタの対応するビット
(CORST0, 1) をセットします。 |
ここまでが、ROMコレクションのハードウエアで処理される内容で、
これ以降はアプリケーション・プログラムで処理する内容です。
| (2) |
BR !0F7FDH命令により内部拡張RAMの後ろに分岐してきますので、
実際にROMコレクション処理を行うアドレスへ分岐させる必要があります。 |
| (3) |
ROMコレクションは最大2箇所設定ができるので、
どのアドレスでの一致による処理かを CORST0, 1 ビットで判断して、
対応したプログラム (パッチ処理) を実行します。
対応したCORSTビットをクリアするのを忘れないでください。 |
| (4) |
パッチ処理が完了したら、元のプログラムに分岐します。 |
以上のように、ROMコレクション用のハードウエアと、アプリケーション・プログラムに
前もって組み込んである処理プログラムとを用いて修正用プログラムを実行させることで
パッチ処理を行えるようになっています。
[2] ROMコレクションを行うために準備するハードウエア
ROMコレクションを行うには、修正プログラムを読み込むためのハードウエアが必要になります。
シリアル・インタフェースで制御するEEPROMを接続し、その中に修正用プログラムを書き込んでおきます。
この場合には、初期化処理のなかで、そのプログラムをシリアル・インタフェースを介して読み出し、
内部拡張RAMに書き込んで置く必要があります。
[3] 初期化プログラムでの対応
ROMコレクションを使用するためには上で説明したハードウエアを準備し、
初期化プログラムにおいて必要な設定を行っておく必要があります。
ROMコレクションのための初期化処理
ROMコレクションを使用するためには、初期化処理で上記フローの処理を行う必要があります。
以下、このフローに沿って説明します。
なお、外部に接続したメモリを使用できるように、
最初にシリアル・インタフェースの初期化を行っておいてください。
| (1) |
入力ポートを準備するか、
外部に接続したメモリの特定のアドレスにROMコレクションを使う必要があるかどうかのフラグを準備しておき、
それを確認することで処理を行います。
ROMコレクションを使用する必要がない場合には (2)〜(4) の処理は飛ばして、
次の処理に移ります。 |
| (2) |
パラメータの設定
ROMコレクションで必要なパラメータ (コレクション・アドレス) を外部に接続したメモリから読み込んで、
CORADレジスタへセットします。 |
| (3) |
修正プログラムの読み込み
引き続き、ROMコレクションで代わりに実行させたいプログラムを外部に接続したメモリから読み込んで、
実際にプログラムを実行させる内部拡張RAMへ書き込みます。
実際にプログラムを実行するのは内部拡張RAMになるので、
内部拡張RAMの後ろから数十バイトをROMコレクション用として前もって確保しておいてください。
なお、(2) の処理と前後することもあり得ます。 |
| (4) |
CORENの設定
最後に、使用したいROMコレクション・アドレスに対応したCORCNレジスタのCOREN0, 1をセットすることで、
ROMコレクション処理が有効になります。
以上の処理で (2)〜(4) の部分を具体的にプログラムにすると以下のようになります。
このプログラム例ではシリアル・インタフェースからの1バイトの読み出しをサブルーチンGET1CHで実行して、
結果は Aレジスタに入ってくるものとします (HLレジスタは影響を受けないものとします)。
また、ROMコレクション用の内部拡張RAMの先頭アドレスを PATCH とします。
ただし、ROMコレクションでは内部拡張RAMを256バイト以下しか使用しないものとします。
;
; ROMコレクション関係初期化
;
MOV CORCN,#0 ; ROMコレクション禁止
MOVW HL,#PATCH ; コピー先アドレスを設定
LOOP1:
CALL !GET1CH ; 1バイトを読み出す
MOV [HL],A ; 内部拡張RAMへの書き込み
INC L ; アドレス更新
BNZ $LOOP1 ; 0F7FFHまで完了するまでループ
MOVW AX,!PATCH ; チャネル0の設定アドレスをリード
MOVW CORAD0,AX ; アドレス設定
PUSH AX ; チャネル0のアドレスをセーブ
MOVW AX,!PATCH+2 ; チャネル1の設定アドレスをリード
MOVW CORAD1,AX ; アドレス設定
OR A,X ; アドレスチェック
BZ $NEXT1 ; アドレスが0000なら無視
SET1 COREN1 ; チャネル1を有効に
NEXT1:
POP AX ; チャネル0のアドレスを復帰
OR A,X
BZ $NEXT2 ; アドレスが0000なら無視
SET1 COREN0 ; チャネル0を有効に
NEXT2:
;
; ROMコレクション初期化完了
;
|
|
[4] ROMコレクションの前処理
アドレスが一致して、修正したい命令の代わりに BR !0F7FDH 命令が実行され、0F7FDH番地へ分岐します。
0F7FFH番地までしか命令はおけませんので、ここには分岐命令を配置し、
実際のROMコレクションで実行する処理の先頭に分岐させます。
[5] ROMコレクションの修正用プログラムの構成
ROMコレクションで使用する修正プログラムやパラメータについて説明します。
外付けのメモリにはROMコレクションを設定するアドレスを2つ、
修正用のプログラムとエントリ用の分岐命令を用意する必要があります。
簡単のために、領域として64バイトを確保したとします。
この64バイト分のデータを内部拡張RAMの最後の部分(0F7C0H〜0F7FFH)に転送するものとします。
このときROMコレクションしたいアドレスの1つ目が PATCH0 で戻り番地を RETADR0、
2つ目を PATCH1 で戻り番地を RETADR1 すると、以下のようなプログラムを準備すればいいことになります。
PATCH0 を ADDR0 に、PATCH1 を ADDR1 に DW擬似命令で定義します。
ROMコレクションの初期設定で、ADDR0 と ADDR1 の内容を確認し、
その内容が 0000ならば対応したチャネルのROMコレクションは使用せず、
0000以外の場合には対応したチャネルのROMコレクションを使用する
(CORCNレジスタの該当するビットをセットする)ようにします。
PATCH CSEG AT 0F7C0H
ADDR0: DW PATCH0 ; コレクションを設定したい番地
ADDR1: DW PATCH1 ; コレクションを設定したい番地
STARTADR:
BT CORCN.0, $PROCE0
PROCE1:
CLR1 CORCN.2 ; CONST1に対応した処理
; ; ここに必要な処理を記述する
; ; ここに必要な処理を記述する
BR !RETADR1 ; 処理終了してメインに分岐
PROCE0:
CLR1 CORCN.0 ; CONST0に対応した処理
; ; ここに必要な処理を記述する
; ; ここに必要な処理を記述する
BR !RETADR0 ; 処理終了してメインに分岐
ENTRY CSEG AT 0F7FDH
BR !STARTADR
END
|
[6] ROMコレクションの競合について
通常はROMコレクションが同時に複数発生することはありません。
しかしながら、割り込み処理にもROMコレクションを設定した場合には、
ROMコレクション処理中に割り込みが発生し、
割り込み処理の中で別のROMコレクションが発生することが考えられます。
このような場合には、
ROMコレクション対象のプログラムの優先度の高いチャネルのCORSTビットから順に確認を行うことで、
ROMコレクションのチャネルに優先度を設定できます。
このように処理に優先度をつけることで割り込みにもROMコレクション処理を行うことができます。