チョコです。
ミラー領域はプログラムの効率を低下させることなく,コード・フラッシュにアクセスするための方法です。
RL78は,基本的には1Mバイトのメモリ空間をもった16bitのMCUです。レジスタは16ビットなので,これだけでは1Mバイトのメモリ空間の全てのアドレスを指し示す(アドレッシングする)ことはできません。通常は,データのアクセスは0xF0000~0xFFFFFの64kバイトの領域(これをnearと呼びます)を使用することで,16ビットのレジスタやイミディエート値でアドレッシングすることができます。この領域にはRAMやSFRが配置されているので,普通のデータアクセス処理はここ(near)だけで済みます。
ところが,コード・フラッシュに配置した定数はこれではアクセスできません。そこで,RL78では2つの方法が準備されています。一つはESレジスタでアドレスの上位4ビットを指定して,残り16ビットをレジスタ等で指定する方法です(これが,farになります)。このような命令セットが準備されているので,1Mバイトのメモリ空間を全てアクセスすることは可能ですが,farでのアクセスはどうしても命令が1バイト長くなったり,実行クロック数が1クロック余分にかかってしまいます。これに対応したのがミラー領域です。16ビットでアクセスできる0xF0000~0xFFFFFの64kバイトの領域は全て占有されているわけではなく,空いている領域が存在します。その空き領域を利用してコード・フラッシュをアクセスできるようにしたのがミラー領域です。ミラー領域を使うと,コード・フラッシュの一部をESレジスタを使用しない通常の命令でアクセスできるようになります。
CA78K0Rを使ってC言語でプログラミングを行う場合には定数(const)データはディフォルトでミラー領域に配置されます。
ただし,アドレス変換のオーバーヘッドをなくすために,ミラー領域のアドレスの上位4ビットを単純に0(または,一部の製品では1も選択可能)にしてコード・フラッシュへのアドレスとしています。ミラー領域は0xF2000番地以降のアドレスになるので,アクセスできるコード・フラッシュは0x02000番地以降になってしまいます。このため,一部のRL78/G12では0x02000番地以降にコード・フラッシュが存在しないためにミラー領域が使えなくなっています。
なお,8ビットのRL78/G10ではミラー領域のアドレス変換をアドレスの上位5ビットに拡張し,0xF8000~のアドレスを0x00000に変換しています。これで,コード・フラッシュの0番地からミラー領域を使ってアクセスできるようになっています。
M16C経験者としてはRL78の0xF0000~0xFFFFF(データアクセス)がnearという事実にいまだに馴染めません(^_^;)
アーキテクチャの違いなので慣れるしかないんですが。。。
すとさん,ここらはデバイスによって異なってきますので,慣れていただくしかありません。
通常は,上位4bitは無視して,0x0000~0xFFFFだけで考えていただければ済みますので。
ミラー領域のないRL78/G12で、ROM領域で定数を使用するには、どのように記述すればよいのでしょうか?
(CA78K0Rを使ってC言語でプログラミングを行う場合)
"__far"を定数の宣言に追加するだけです。たとえば,RL78/G13のIICマスタのサンプルコードの定数データをROMに配置してミラー領域を使わないでアクセス(farデータとしてアクセス)させるようにするには,以下のように記述してください。
static const __far uint8_t tx_data[16]= /* Transmission data( 16 byte ) */
{
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F
};
このように宣言しておけば,"rx_buffer[ptr] = tx_data[ptr];"のようにROMからRAMへのコピーで,ROM読み出し部分は以下のようにESを用いた命令に展開されます。
mov ES,#highw (_tx_data)
mov a,ES:_tx_data[b]
チョコさん
Sneijderです。
私も、理解がまだできていないので、質問させてください。
RL78には、データ部のnear/far、コード部のnear/farについてです。
これは、
コード部のnear領域にconstデータを配置することで、
ミラー領域にミラー領域のサイズ分展開でき、
展開した分はnear属性として、参照できる。
という仕組みであると認識して良いですか?
ミラー領域のサイズをオーバーしているconstデータは、
データ部から見るとfarにあたる為、
far属性として、参照している。という
認識で良いですか?
お手数お掛けしますが、回答お願いします。
Sneijder さんのご質問に回答いたします。
> コード部のnear領域にconstデータを配置することで、
> ミラー領域にミラー領域のサイズ分展開でき、
> 展開した分はnear属性として、参照できる。
おおむねそのようなご理解でいいかと思います。(コードにはnear領域というものはありません。)
RL78/G10を除いたRL78シリーズでは,基本的にnear領域のミラー領域のアドレスの上位4ビットを
0または1(64kバイト以上のFlash内蔵の場合)にするだけで,下位の16ビットはそのまま使用します。
そのため,ミラー領域が始まるアドレス(0xF2000)の下位の2000(8kバイトのアドレス)以降に
Flashが存在しないRL78/G12の8kバイト以下の製品ではミラー領域は存在しないことになります。
> ミラー領域のサイズをオーバーしているconstデータは、
> データ部から見るとfarにあたる為、
> far属性として、参照している。という
> 認識で良いですか?
「far属性として、参照している」は正確ではないですね。「far属性として、参照しないといけない」
が正しいです。
Sneijder です。
返信誠にありがとうございます。
おかげ様でミラー領域について、理解することができました。
デバッガで確認しても、
default の MAA = 0 で、
展開元と展開先を確認しました。
あとで、ミラー領域に展開されているデータへのアクセス数と
ミラー領域以外に展開されているデータへのアクセス数を
逆アセンブラで確認しようと思います。
ただ、もうひとつ質問があるのですが、、、、
リンクディレクティブで
@@CNSTをROMという2000h~10000hの領域に配置するよう
指定しています。
@@CNSTのサイズは5000hあります。
このROMの中の3000h~6000hがミラー領域に展開される範囲だとして
デバッガで確認したところ、
@@CNSTは2000hから配置されており、
ミラー領域に展開されているデータは
@@CNSTの1000h部分から4000h部分までとなっていることを確認しました。
これは上記回答していただいた内容に一致していますので、
問題ないのですが、
Mapファイル中の、@@CNSTの箇所に「CSEG MIRRORP 」の記述がなくなりました。
これはなぜ消えるのか、わかっていません。
ご教示いただけますでしょうか?
お忙しい中申し訳ございませんが、宜しく御願いします。
> Mapファイル中の、@@CNSTの箇所に「CSEG MIRRORP 」の記述がなくなりました。
これは,リンクディレクティブで@@CNSTの配置先を指定したためです。
ディフォルトでは,ミラー領域に優先的に配置していきますが,
リンクディレクティブでの指定が優先されます。そのため,配置属性から
「CSEG MIRRORP 」の記述がなくなったものです。
なお,「3000h~6000hがミラー領域に展開される範囲」とすると,2000h
~2fffhに配置された部分はアクセスできなくなりますので,ご注意ください。
ご回答ありがとうございました。
指定せず、defaultでの使用の方が、
Mapファイルに出力され、可読性がありますね。
>なお,「3000h~6000hがミラー領域に展開される範囲」とすると,2000h
>~2fffhに配置された部分はアクセスできなくなりますので,ご注意ください。
これも動作を確認しました。
2000h~2fffhに配置したデータの参照は、「__far」の修飾子をつけることで、
解決できました。
お時間いただき、誠にありがとうございました。
今後のノウハウにさせて頂きます。
今後とも宜しく御願い致します。
RL78/G10ハードウェアマニュアルのミラー領域の頁(p.28)には
「MOV A, ES:!789Hの代わりにMOV A, !789HでROMにアクセスできる」とありますが、
これは本当に正しいのでしょうか。
後者の方法だと2nd SFRへのアクセスになってしまうような気がします。