【解決後のコメント】この問題は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と申します。RL78/G14の104GJであれば、const変数は基本は最大でも27.75Kバイトしか取れない筈、ですよ。(RL78のアーキテクチャ&CC-RLの設計思想&GNURL78の設計思想の点では、以下のハードウェアマニュアルの画面コピーのMirrorと書かれた空間を通して使用することになっているからです。)ただし、CC-RLではメモリモデルのオプションのひとつに、「ROMデータをfar領域に配置する」というオプションがありますが、ひょっとして、これを設定していませんでしたか?(とはいえ、私自身は、このオプションを使ったことがないので、設定した場合に生成されるコードの詳細は分かっていません。だいたいの予想はつきますが。)もしそうであれば、GNURL78には同様のオプションが無いようですので、変数宣言をconst farにするしかないと思われます。eokayamaさんのプログラムがGNURL78で動作しない原因は他にもあるかも知れませんが、まず、この点を変更する必要があるのではないかと思います。他方、このようなことに関してさえ、GNURL78ではワーニングが出ませんので、結局、「怖くて使えない」という印象は変わることが無いようにも思います。安心を望むのであれば、もしコードが64KBを超えている原因が巨大なconst変数群にあるのであれば、以下の資料(H8コンパイラ+HEWでの資料ですが)の裏技その2と裏技その3を参考にして、CC-RLで同様の手法で何とかする方法も可能ではないかと思います。(手間と引き換えに安心を取る、ということです。)「今すぐ使える!H8マイコン基板 増補版」第22章 - 無償評価版HEWを最大限に活用する三つの「裏技」toragi.cqpub.co.jp/Portals/0/support/2010/H8/mihon/191_197_(22).pdfRL78/G14 ユーザーズマニュアル ハードウェア編www.renesas.com/jp/ja/search/keyword-search.html#q=r01uh0186r01uh0186jj0330-rl78g14.pdf[追記]なお、以下の画面コピーの通り、CC-RLではconst変数群が溢れた場合にはエラーになります。当方特有の事情でCS+ V8.01 & CC-RL V1.02を使っています[追記その2]あと、CC-RLで「ROMデータをfar領域に配置する」というオプションを使っていなかった場合、CC-RLからGNURL78に移植して暴走した原因として考えられるのは、const変数群が27.75Kバイトぎりぎりに収まっていたのとswitch文では分岐テーブルが使われていなかったのとでCC-RLではエラーにならなかったけれど、GNURL78ではswitch文で分岐テーブルが使われていたのとそれがconstセクションに出力されているのとでMirror空間から溢れてしまった、という可能性です。