【解決後のコメント】この問題はRL78の nearアドレッシング可能領域外にコンパイラがnearアドレッシング定数を配置してしまうことで起きる暴走でした。単純化したコードでは、定数のサイズを加減して原因調査し、Rsply3までに解決しました。コンパイル後のMAPファイルで(.rodata)セクション(nearアドレッシング)のサイズがRL78のミラー領域を超えていないか、確認することで異常動作を防止できます。しかし定数エリアのサイズがそれほど大きくないにもかかわらず、プログラムコードのサイズが大きくなると暴走します。4番目のreply で説明していますが、プログラムコードのサイズが大きくなると nearアドレッシング可能なROM領域をプログラムコードがつぶしてしまうため、メモリーマッピング的に失敗していました。結局のところリンカーファイルを手直しで編集して、 nearアドレッシング可能領域を確保する必要がありました。
-------------------------------
GCC for Renesas RL78の不具合と思われる現象で困っています。e2studioで使うコンパイラのツールチェーンは「GCC for Renesas RL78」バージョン4.9.2.201902です。
単純化したので、プロジェクトを新規作成してすぐ再現できます。事の発端はCS+とCCRLコンパイラの組み合わせででは問題なく動いていたプログラムを、GCC RL78の開発環境へ移したら暴走したことです。GCC RL78の環境に変える理由は、CCRLコンパイラの無償評価期間が過ぎて64KB以上のプログラムを開発できなくなったためです。CPUはRL78/G14 ROMサイズが256KBの104GJ で、エミュレータE1を接続してデバッグしています。暴走するのはCのプログラムですが、調べると switch文 のところで暴走します。動かない原因を探るためにコードをどんどん落としていくと、コードサイズが二十数KB程度のプログラムなら問題なく動くことが分かりました。どうもコードサイズに関係する不具合のようなので、さらに単純化しました。割り込み、周辺機能は一切使用せずハードウェアデバッグ機能のみ使用する。調査に使用するソースは単純なCのソース一本だけ。異常を確認するソース "r_main.c" は次のような簡単なものになっています。
const long Array1[2048] = {1, 1, 0, 0, 0, 0, 0 ... 略}; // 配列定数(1行でROM領域8Kバイト)const long Array2[2048] = {1, 1, 2, 0, 0, 0, 0 ... 略};const long Array3[2048] = {1, 1, 0, 2, 0, 0, 0 ... 略};const long Array4[2048] = {1, 1, 0, 0, 5, 0, 0 ... 略};const long Array5[2048] = {1, 1, 0, 0, 0, 10, 0 ... 略};char c;unsigned short i;long lwk1, lwk2, lwk3, lwk4, lwk5;char SwtchTest(char ac);void R_MAIN_UserInit(void);/************************************************************************************************************************ メイン関数***********************************************************************************************************************/void main(void){ R_MAIN_UserInit(); lwk1 = 0; lwk2 = 0; lwk3 = 0; lwk4 = 0; lwk5 = 0; for(i = 0; i<2; i++){ lwk1 += Array1[i]; lwk2 += Array2[i]; lwk3 += Array3[i]; lwk4 += Array4[i]; // 行をコメント化するとROM定数エリアが8Kバイト減る lwk5 += Array5[i]; <--------- ※1. Array5[0] にとんでもない大きな数値が代入される } lwk1 = lwk1 + lwk2 +lwk3 + lwk4 + lwk5; while (1U) { // test switch case c = 1; c = SwtchTest(c); <--------- ※2. swich文に入ったとたんに暴走してプログラムカウンタが 0 になる(0番地へジャンプする) }}/************************************************************************************************************************ Function Name: R_MAIN_UserInit***********************************************************************************************************************/void R_MAIN_UserInit(void){ EI();}char SwtchTest(char ac) <--------- ※ swich文の関数{ char ret; switch(ac) { case 0: ret = ac +1; break; case 1: ret = ac +2; break; case 2: ret = ac +3; break; case 3: ret = ac +4; break; case 4: ret = ac +5; break; default: return -1; } return ret;}以上説明異常現象は上記ソース中にコメントしたように下記2点です※1. Array5[0] にとんでもない大きな数値が代入される※2. swich文に入ったとたんに暴走してプログラムカウンタが 0 になる(0番地へジャンプする)使用する配列定数(const Array1[])が3つまでなら、ROMサイズは24KB程度でプログラムは正常に動きます。(ROMサイズが24KB 、プログラムサイズは828バイト)使用する配列を4つにすると、swich文で暴走します。(ROMサイズが32KB 、プログラムサイズは896バイト)使用する配列を5つにすると、swich文で暴走するほか、※1.の配列の参照値がとんでもない値になります。(ROMサイズが41KB 、プログラムサイズは978バイト)ROMサイズの調整は、ソース中の lwk4 += Array4[i]; といった1行をコメント化すると1行当たり8Kバイト分のROM定数エリアを使わなくなります。(これはconst Array4[... で定義した定数配列が使われないのでコンパイラが定数として実体化させないため)単純化したので、プロジェクトを新規作成してすぐ再現できます。このように明らかにROMサイズと関係して不具合が発生しています。(今回はROM定数エリアでサイズを調整しましたが、プログラムコードサイズでも同じことが起こるようです)
対策としては、switch文を全て if文に変えても、定数の扱いでおかしな現象が残ってしまうため、GCCが怖くて使えない状態で困っております。
--2019年8月11日 追記--
ハードウェアがない環境でRL78 Simulatorを使用したデバッグでも同様の現象を確認出来ます。またGCCのバージョン4.9.2.201801でも同じ、Cの言語仕様は、Defaultの"GNU ISO C90" に加えて"GNU ISO C99"、"GNU ISO C11" で試しても同様でした。switch文のcase分岐数を減らすと暴走しなくなります。(逆アセンブラのコードもかなり変化します)
eokayamaさん、こんにちは。NoMaYです。今回の件が発端で、以下を投稿しました。(C++の話やリンカスクリプトエディタの話も入ってますが、、、) リンカスクリプトでASSERT()を利用してconst領域とMirror領域の関係が適切かどうかチェック出来るようにしてみました。(もう読まれたかも知れませんが、、、)GNURL78でconst領域/Mirror領域をちょっと安全に使えるようにlinker scriptのASSERT()で小技(TIPS)を考えてみたjapan.renesasrulz.com/cafe_rene/f/forum21/5917/gnurl78-const-mirror-linker-script-assert-tips