RL78/G13のミラー領域

UARTの実装を行っている過程で、文字列を出力する簡単なプログラムが、思ったよう
に動作しないで、随分悩んだ・・・

調べると、ミラー領域に関する認識が甘かったようで、データフラッシュ領域と当たって
いた事が判った。

8/16ビットマイコンでは、ポインターは16ビットサイズで、基本64キロバイトの
領域しかダイナミックにアクセス出来ない。

RL78では、物理的なメモリー空間は1Mバイト(64Kが16ページ)ある。
プログラム領域は、0番地から始まり、128Kバイト品(R5F100LGAFB)の場合、
0x1FFFFまで使える。

RAM領域は、128キロバイト品の場合、12キロバイトあり、0xFCF00から
始まる。

データフラッシュは128キロバイト品の場合、8キロバイトあり、0xF1000
から0xF2FFFまである。
※64キロバイト品では、半分の4キロバイト

RL78のgccでは、R/Wアクセスする領域は、常に0xF0000~
0xFFFFFをベースとしていて、RAM領域をベースにアクセスするようになって
いる。
ここで問題になるのが、プログラム領域に置かれた読み出し専用データのアクセスとなる。
RL78では、「ミラー領域」を使ってこれを解決していて、RAM領域、
データフラッシュ領域以外は、ROM領域のアクセスと同等となる
仕組みがある。

ここで、以前に修正したリンカースクリプトが問題となった・・・

 .rodata (MAX(__romdatastart + __romdatacopysize, 0x2000)) : {

この「0x2000」のオフセットが何なのか、判ってなかった為、これを無効
(0x0000)としていた・・・
※0x2000の領域が「空く」のは勿体無い・・

当然、「0x0000」にすると、文字列データは、先頭から配置される為、テストして
いたプログラムでは、0x2000以下の領域に配置される、ミラー領域では、このエリ
アは、データフラッシュ領域の為、0xF1000~0xF1FFFがアクセスされてい
た。
それには、途中で気がついて、オフセットを0x2000に戻したが、それでも、直らな
い、良く調べると、128KB品は、データフラッシュが倍の8Kバイトあり、
0xF1000~0xF2FFFまでとなっていた。
そこで、オフセットを「0x3000」とする事で、解決した。

 .rodata (MAX(__romdatastart + __romdatacopysize, 0x3000)) : {

※リンカースクリプトは修正済みでプッシュしてある。

つまり文字列などの固定データは、0x3000以降、0xCF00までに置く必要があ
る。
まぁ、このくらいの領域があれば、当面困る事は無いと思われる。

先頭の空いた領域には、「.lowtext」セクションが割り当ててあるので、ここには、割り込
みルーチンなどを優先的に配置するのが良さそうだと思う。
※割り込みルーチンは、ベクターが16ビット固定なので、必ず64K以内に配置する必要
がある。

また、64K以降のエリアへは、「__far」を使う事で、ポインターを32ビット扱いとして
アクセスする事も出来るが、C++ ではこのキーワードを上手く扱えないようで、悩んでる。
※とりあえず、Cの関数だけで操作するしか無い。

Cの関数宣言では、ポインターが32ビット扱いになり、逆アセンブルリストを観た感じでは
ESレジスター付き20ビットでアクセスするコードになっている。

「コード」の呼び出しは、20ビット対応の「call」命令が使われているので、全域に対して
アクセスでき、64Kの壁を意識する必要は無いようだ。

 12c:   fc be 32 00        call    !!32be <_main>

※コードが64Kを超えて伸びていっても問題は無いと思われる。

-----
RL78は、Z80のようだと思ったら、実際Z80(78K0)がベースのようだwww

※昔、ゲームボーイのプログラムで、Z80のアセンブラを随分扱ったので、馴染みがある。
でも、32MHzで動くZ80となると、かなり話が違う。