RX62シリーズでgccを使う際の注意点

ルネサス エレクトロニクス製マイコン、RX62シリーズでgccを使う場合の注意点について、 @nahitafu さんのツイートをまとめました。
1
なひたふ(内藤竜治) @nahitafu

HEWでKPITのGCCを選択してRX62Nのプログラムを作成し、char message[] = "hogehoge";ってやったら、hogehogeは生成されたMOTファイルの0x1001番地に配置されてしまう。これはRAM上のアドレスだ。ROMには書き込まれない。

2011-05-12 04:58:12
なひたふ(内藤竜治) @nahitafu

一方、ルネサスコンパイラでは、char message[] = "hogehogehoge";ってやっても、ちゃんと0xFFFF8558番地、つまりROM上に配置された。

2011-05-12 04:58:19
なひたふ(内藤竜治) @nahitafu

でも、KPITのGCCでも、const char message[] = "hogehogehogehogehogehogehogehoge";ってconstをつければ、ROM上に格納されるんだな、これが。

2011-05-12 05:01:10
なひたふ(内藤竜治) @nahitafu

KPITのGCCでも自分でビルドしたGCCでも同じ。GCCでの挙動がおかしいのはリンカスクリプトのせいだと思うが、つまるところ、constではない配列の初期値が設定されないという現象が起こる。スタートアッププログラムは何もない領域をコピーしようとする。

2011-05-12 05:02:23
なひたふ(内藤竜治) @nahitafu

GCCでは、グローバルでconstでもstaticでもない配列の初期値は.dataというセクションに格納されるようだ。

2011-05-12 05:06:10
なひたふ(内藤竜治) @nahitafu

KPIT GCCではリンカスクリプトはgsiという拡張子のファイルに書かれていて、デフォルトで.data 0x00001001 : AT (_mdata)となっている。_mdataはROM上の物理アドレス。.data 0x00001001は仮想アドレス。この記述には問題ない。

2011-05-12 05:06:20
なひたふ(内藤竜治) @nahitafu

しかし、グローバルでconstでない配列の初期値はMOTファイル中でROM上のアドレスにならないので、困ったことになる。例えば、割り込みベクタテーブルの初期値とかがROMに書き込まれない。これは、rx-elf-objdumpが悪いのか、リンカスクリプトが悪いのか。さあ困った。

2011-05-12 05:12:44
なひたふ(内藤竜治) @nahitafu

GNUリンカが吐き出したMAPファイルを見ると、.data 0x00000000 0x888 load address 0xffff0000となっているので仮想アドレスと物理アドレスの解釈は正しそうだ。するってえと原因はrx-elf-objcopyか

2011-05-12 05:23:05
なひたふ(内藤竜治) @nahitafu

rx-elf-objcopyのオプションに--change-section-lma .data=0xffff0000をつけてアドレスを変更すればよいようだ。これでGCCで作ったプログラムのROM化もできた。問題は実際にROM上に配置すべきアドレスが自動で得られないこと。

2011-05-12 06:15:38
なひたふ(内藤竜治) @nahitafu

果たしてこんなオプションをつけることが正解なのだろうか。しかし、HEWに組み込んだKPITのGCCでさえ、デフォルトのままではグローバル変数の初期値を正しく設定してくれない。

2011-05-12 06:26:47
なひたふ(内藤竜治) @nahitafu

いろいろ書いてきたけど、要するにRX用のGCCで作ったプログラムをROM化するとグローバル変数の初期値が設定されないことがわかった。自前でビルドしたGCCでもKPITのGCCでもダメ。配列に限らず、int t=0x12345678という定数でもダメ。

2011-05-12 06:32:43
なひたふ(内藤竜治) @nahitafu

その原因は、rx-elf-objcopyが.dataセクションのLMA(Load Memory Address)を正しく解釈しないこと。だから--change-section-lma .data=なんてオプションをつけなければならないようである。

2011-05-12 06:35:31