これまでCS+において違和感があったのですが、ようやくわかりました。
リンク・ディレクティブのデフォルトが規定されていないんですね。
HEW(High-perfomance Embedded Workshop)においてはファイル単位での未指定のセクションは自動的にP(プログラム)、C(固定データ)、D(初期値ありデータ)、R(初期値ありデータの初期値)、B(初期値なしデータ)の各領域に割り振られるのですが、CS+では内部で定義されるROM、RAMアドレスに振られるようです。
R5F100GE(RL78/G13 ROM:64KB)の初期リンク・ディレクティブにSTACKというメモリ領域を追加してみました。
;MEMORY MEMORY ROM : ( 00000000H, 00010000H ) / REGULAR MEMORY RAM : ( 000ff000H, 00000800H ) / REGULAR MEMORY STACK : ( 000ff800H, 00000400H ) / REGULAR
デフォルト状態でコード生成した後にr_main()関数内にstatic変数を宣言しました。(固定アドレスに割り付けるという意味ではグローバル変数でもOKです)
void main(void) { static int total=0; R_MAIN_UserInit(); /* Start user code. Do not edit comment generated here */ while (1U) { ; } /* End user code. Do not edit comment generated here */ }
この状態でビルドすると次のmapファイルが得られました。(一部抜粋)
*** Local symbol list *** MODULE ATTR VALUE NAME r_main MOD r_main ADDR FF0BAH _total
続いてリンク・ディレクティブの内容をSTACK領域とRAM領域で入れ替えます。
;MEMORY MEMORY ROM : ( 00000000H, 00010000H ) / REGULAR MEMORY STACK : ( 000ff000H, 00000400H ) / REGULAR MEMORY RAM : ( 000ff400H, 00000800H ) / REGULAR
この状態でビルドすると次のmapファイルが得られました。(一部抜粋)
*** Local symbol list *** MODULE ATTR VALUE NAME r_main ADDR FF0BAH _total
メモリ領域の配置を変更しても変数の配置が変わらないことから詳細にリンク・ディレクティブを指定しないとCPUに依存したROM、RAMの先頭から順次配置されることを示唆しています。
こちらを解決するにはメモリ領域にセグメントを指定する必要があります。
;MEMORY MEMORY ROM : ( 00000000H, 00010000H ) / REGULAR MEMORY STACK : ( 000ff000H, 00000400H ) / REGULAR MEMORY RAM : ( 000ff400H, 00000800H ) / REGULAR ;SEGMENT MERGE @@INIT : = RAM / REGULAR
上記のようにリンク・ディレクティブを指定すると「RAM領域に@@INITセグメント(初期値ありデータ near領域)を割り付けます」という意味になります。
*** Local symbol list *** MODULE ATTR VALUE NAME r_main ADDR FF400H _total
本例ではこの状態でビルドするとRAM領域(0xFF400~)に初期値ありデータを割り付けることができました。
リンク・ディレクティブの指定はファイル毎に個別指定をしたり、ヘッダファイルと#define~#ifdefなどを活用することによって半自動指定が可能です。しかし、これは知っている者のみが可能なことで、マイコン初心者やCS+初心者には分かりにくい領域ですね。