RL78/G13で、デュアルブート

RL78/G13と、CubeSuite+を使用して開発しています。

CPUのGPIOにスイッチを設けて、
スイッチ=OFFの場合はプログラムA、
スイッチ=ONの場合にはプログラムB
を、起動するようなやり方は可能なのでしょうか?

プログラムA、プログラムB双方ともRAMを大量に消費する
プログラムで、機能や動作内容が異なるため、
main処理後にプログラムA、プログラムBを選んで
動作をする余裕がありません。

コードサイズ自体はそれぞれ大きくないのでROMには
入りそうなのですが、RAMがどうにもなりません。

発想としては、リセット解除後に、
スイッチを読み込むプログラムが動作して、
その後、スイッチに従ったプログラムA又はBが動作する
ようなことがしたいのですが、
どのようにCubeSuiteで作成すればよいのかわかりません。

ご教授お願いします。
また、上記方法以外にも案がありましたらご提案お願いします。
  • こんにちは、H8/3052とHEWでそのようなプログラムを作っています。
     私の場合は4ビットスイッチで、16通りに分岐できます。

     プログラムAとBをコンパイルするとき、セクションのアドレスを指定して0x10000と0x20000に作ります。
     次にそれらのセレクターとして、次のようなプログラムを作ります。

    #define PRG_A ((void (*)(void)) 0x10000 ) /* プログラムA */
    #define PRG_B ((void (*)(void)) 0x20000 ) /* プログラムB */

    void main
    {
    if ( switch )
    PRG_A() ;
    else PRG_B() ;
    }


     これでMOTファイルが三つできます。MOTファイルはSファイルと言う構造です。
     ルネサスのマニュアルを探せば、Sファイルの構造が書いて有ります。
     内容は次のように3っつの部分で出来ています。

    1.ヘッダー
    2.本体
    3.フッター

     テキストで出来ていますから3っつを結合編集して次のようにして、1本のMOTファイルを作ります。

    セレクターのヘッダー
    セレクターの本体
    プログラムAの本体
    プログラムBの本体
    セレクターのフッター

     これで完成です。もしもROMを部分的に消したり書き込めれば、3本のソフトを別々に書き込めば良い。
     私の自作書き込みソフトは、そのようになっています。
  • RyuKucchanさん、リカルドさん

     まず、リカルドさんの方法でも可能ですが、H8ならば最適化リンカにおけるセクションの複数割り付け機能を使った方が簡単だと思います。
     ROM容量に問題がなく、RAMだけが足りない、しかも2つのプログラムが同時に動くことがないのであれば、プログラムAとプログラムBが使用するRAM領域を同じ番地に配置すれば良いだけです。その機能がH8にはありますから、その機能を使えばプログラムは1本化、ロードモジュールも1つで済みますから、多分ご指摘の方法より簡単だと思います。もっとも、プログラムAとプログラムBで変数の割り付くセクションを分ける必要はありますが。。。

     一方、RyuKucchanさんのRL78の場合、リンクディレクティブにH8と同等の機能があるかと調べてみましたが、私の調べた範囲ではありませんでした(見つかりませんでした)。
     そうなると考えられる方法はプログラムAとプログラムBが使用する外部変数を共用体にするが1つの作戦です。

    例:
    union {
    struct program_A {
      プログラムAが使用する外部変数の宣言
    } A;
    struct program_B {
      プログラムBが使用する外部変数の宣言
    } B;
    } VAL;

     これでプログラムAとプログラムBの外部変数の領域を同一のRAMに割り付けられますが、変数名が長くなり、リストの可読性も悪くなるのが難点です。

     もう1つの作戦は外部変数を全てマクロ名で定義する方法です。例えば、int a;ならば、この宣言の代わりに
    #define a (*(int *)0x....)
    と全て番地を指定して定義する方法です。これでプログラム上は一切変数が存在しないことになりますから、プログラムAとプログラムBで同一番地に変数を配置するだけ、しかも変数宣言以外は何も変える必要なし、となります。

     なお、どちらにしても外部変数に対する初期値の設定は出来ません。初期値は全てプログラムの命令として設定する必要があります。如何でしょうか?
  • ご意見いただき有難うございます。
    また、レスが遅れ申し訳ありません。

    プログラムを分ける方法と、unionの方法で検討してみます。

    出来ましたら、もう少し教えていただきたいのですが、

    プログラムを分ける方法については、
    CubeSuite+のコンパイラを使用する場合には、
    具体的にどのようにすればよいのでしょうか?
    3つ別々のプロジェクトを作成するような形になるのでしょうか?

    unionについてですが、グローバル変数の箇所だけ
    unionでA、Bと分けて書くという認識であっていますでしょうか?
    恥ずかしながら、unionをはじめて知ったもので・・・。
    何か注意点等あれば助言をいただけると助かります。

    よろしくお願いします。
  • RyuKucchanさん

    私も投稿後、少し考えてみたのですが、初期値付きの外部変数だけを注意すれば大丈夫ではないかと思っています。
    まず、ご質問の局所変数は何の問題もありません。static記憶クラスを指定しない限り、大丈夫です。
    また、初期値付きの外部変数はunionの中に入れることができません。初期値なしとして宣言し、プログラムA/Bの各先頭で初期値を代入文で設定するのが一番簡単ではないかと思っています。

    実際に試して頂き、また問題があれば投稿ください。
  • LunaJamといいます。

    unionを使うと多分こんな感じになると思います。
    注意点としては割込処理ルーチンも別な処理になるなら変数アクセスも別になるようにしなくてはいけませんね。

    エビスクラウンさんのいわれる通りstatic記憶クラスは注意した方がよろしいかと。
    ただし各PGMが(パワーオン)リセットしないと切り替わらないならば競合しないので問題無いと思います。


    typedef struct _ST_VAR_PGMA_ {
        int      nData1 ;  //
         必要なだけ変数を定義
      } ST_VAR_PGMA ;

    typedef struct _ST_VAR_PGMB_ {
        int      nData1 ;  //
         必要なだけ変数を定義
      } ST_VAR_PGMB ;

    typedef struct _ST_VAR_PGMC_ {
        int      nData1 ;  //
         必要なだけ変数を定義
      } ST_VAR_PGMC ;

    typedef union _UN_PGM_VAR_ {
        ST_VAR_PGMA  stVarA ;  // PGM-Aの変数
        ST_VAR_PGMB  stVarB ;  // PGM-Bの変数
        ST_VAR_PGMC  stVarC ;  // PGM-Cの変数
      } UN_PGM_VAR ;

    UN_PGM_VAR   unPgmVar ;    // PGM-A\,B\,C共有変数
    char      cPgmNum ;     // プログラム識別


    void pgm_A( void )
    {
     unPgmVar.stVarA.nData1 = 何とか ;
    }

    void main( void )
    {
     // どこかのI/OチェックしてPGM識別 ->cPgmNum
     switch (cPgmNum) {
       case 1 :
        必要なら変数初期値セット
        pgm_A( ) ;        // PGM-Aを処理
        break ;
       case 2 :
        pgm_B( ) ;        // PGM-Bを処理
        break ;
       case 3 :
        pgm_C( ) ;        // PGM-Cを処理
        break ;
       default :
        break ;
     }

    }
  • リカルドです。

    >3つ別々のプロジェクトを作成するような形になるのでしょうか?

     そうです。RL78/G13 のマニュアルを少し読みました。H8と同じようにベクターアドレスが有るようですね。
     ベクターは2バイトで64K迄しかジャンプ出来ないと書いて有りました。

     プログラムAとBを単独に作った場合にベクターも含めて 0x0000 ~ 0x0FFF のサイズだったとしましょう。
     コンパイルするときセクションアドレスの指定を操作して、0x1000 ~ 0x1FFF と 0x2000 ~ 0x2FFF にAとBのプログラムを作ります。

     セレクター用のプログラムでスイッチの状態を見て、0x1000 か 0x2000 にあるベクターアドレスを読み、そこにジャンプすれば良いのです。
     アセンブラで作るならジャンプ命令でいいのです。No1で書いたのは、C言語で何とか処理するための例です。

     割り込みについてもまずセレクター用プログラムにジャンプして、スイッチによって 0x1000~ または 0x2000~ に書いてあるベクターを読み出し、そこにジャンプすれば良いのです。


    >CubeSuite+のコンパイラを使用する場合には、
    >具体的にどのようにすればよいのでしょうか?

     CubeSuite+ も RL78/G13 も使った事は無いので、具体的な事は知りません。
     CubeSuite+ で出力されるファイルが、HEWと同じ形式のファイルかどうかは知りません。

     ヒントと言う事で、後はご自分で調べて工夫して貰うしか無いですね。

     例えばこの方法でROMサイズが足らないとしたら、A,B両方から使える汎用性の有るプログラムCを作るとか。
     そのようなプログラムCは工夫が必要です。パラメータで渡されたデータ以外はアクセス出来ません。
     つまり次のような グローバルデータ b は使えない。

    int SUB(char a)
    {
    a = b;
    }
  • 何度もすいません。

    教えていただいたunionの変数を、
    main以外の別ファイルのモジュールで使用するにはどのようにすればよいでしょうか?

    ヘッダーファイルに、

    union unVAL{
     struct PRG_A {
      //プログラムAが使用する外部変数の宣言
      unsigned char TestBuf1[10000];
      unsigned char TestBuf2[10000];
    };
     struct PRG_B {
      //プログラムBが使用する外部変数の宣言
      unsigned char TestBuf1[10000];
      unsigned char TestBuf2[10000];
    };
     struct PRG_C {
      //プログラムCが使用する外部変数の宣言
      unsigned char TestBuf1[10000];
      unsigned char TestBuf2[10000];
     };
    };

    extern union unVAL gUV;

    上記なように書いてみたのですが、エラーが出まくりです。

    下記のように宣言すると、
    今度はメモリが足りないような下記エラーが発生してしまいます。
    「CC78K0R error E0111: Compiler limit : too much global data defined in file」

    typedef struct _stPRG_A {
     //プログラムAが使用する外部変数の宣言
     unsigned char TestBuf1[10000];
     unsigned char TestBuf2[10000];
    }stPRG_A;

    typedef struct _stPRG_B {
     //プログラムBが使用する外部変数の宣言
     unsigned char TestBuf1[10000];
     unsigned char TestBuf2[10000];
    }stPRG_B;

    typedef struct _stPRG_C {
     //プログラムCが使用する外部変数の宣言
     unsigned char TestBuf1[10000];
     unsigned char TestBuf2[10000];
    }stPRG_C;

    union unVAL{
     stPRG_A PRGA;
     stPRG_B PRGB;
     stPRG_C PRGC;
    } ;

    extern union unVAL gUV;

    どのようにすればよいのかご教授お願いします。
  • LunaJamといいます。

     とてつもない配列サイズですがRAMの容量は足りてますでしょうか。

     モジュールを分割してグローバル変数を共有して使う場合はだいたいこんな感じだと思います。
     ヘッダを共用する場合は変数定義が各モジュールでダブらないよう工夫すればOKです。


    変数定義ヘッダファイル:Header.H
    //---------------------------------------------------
    #ifndef  _DEF_APP_HDR_       // 多重定義対策
     #define  _DEF_APP_HDR_

    // 各プログラム用の構造体型定義

    // 共用体型定義
    typedef union _UN_PGM_VAR_ {
       PRG_A stPRGA;
       PRG_B stPRGB;
       PRG_C stPRGC;
      } UN_PGM_VAR ;

    // 変数定義
    #ifdef _APP_DEF_
      UN_PGM_VAR     gunPgmVar ; // main.c 用
      char        cPgmNum ; // プログラム識別
    #else
    // _APP_DEF_
      extern UN_PGM_VAR  gunPgmVar ; // main.c 以外用
      extern char     cPgmNum ; // プログラム識別
    #endif // _APP_DEF_

    // 関数プロトタイプ
    void pgm_A( void ) ;

    #endif // _DEF_APP_HDR_
    //---------------------------------------------------


    メインモジュール:main.c
    //---------------------------------------------------
    #define _APP_DEF_         // 内部識別
    #include \”Header.h\”        // アプリケーションヘッダ

    void main( void )
    {
     // どこかのI/OチェックしてPGM識別 ->cPgmNum
     switch (cPgmNum) {
       case 1 :
        //必要なら変数初期値セット
        gunPgmVar.stPRGA.TestBuf1[0] = 1 ;
        pgm_A( ) ;        // PGM-Aを処理
        break ;
       case 2 :
        pgm_B( ) ;        // PGM-Bを処理
        break ;
       case 3 :
        pgm_C( ) ;        // PGM-Cを処理
        break ;
       default :
        break ;
     }
    }
    //---------------------------------------------------


    サブモジュール:sub.c
    //---------------------------------------------------
    #include \”Header.h\”        // アプリケーションヘッダ


    void pgm_A( void )
    {
       PRG_A *pstPRGA;

     // PGM-Aのメイン処理
     gunPgmVar.stPRGA.TestBuf1[1] = gunPgmVar.stPRGA.TestBuf1[0] ;
     // 長ったらしいのでポインタ処理する場合有り
     pstPRGA = &(gunPgmVar.stPRGA) ;
     pstPRGA->TestBuf1[1] = pstPRGA->TestBuf1[0] ;
    }
    //---------------------------------------------------
  • ひとつの変数はどのくらいのサイズまで宣言可能なのでしょうか?

    下記のようにunionやstructでコンパイルを行った場合、
    「CC78K0R error E0111: Compiler limit : too much global data defined in file」
    と、エラーが発生してしまいます。

    Bufサイズを小さくすればコンパイルできます。

    typedef struct _stPRG_A {
     //プログラムAが使用する外部変数の宣言
     unsigned char TestBuf1[10000];
     unsigned char TestBuf2[10000];
    }stPRG_A;

    typedef struct _stPRG_B {
     //プログラムBが使用する外部変数の宣言
     unsigned char TestBuf1[10000];
     unsigned char TestBuf2[10000];
    }stPRG_B;

    typedef struct _stPRG_C {
     //プログラムCが使用する外部変数の宣言
     unsigned char TestBuf1[10000];
     unsigned char TestBuf2[10000];
    }stPRG_C;

    union unVAL{
     stPRG_A PRGA;
     stPRG_B PRGB;
     stPRG_C PRGC;
    } ;

    ちなみに、CPUはR5F100LANA、ROM:512KB、RAM:32KBです。
    よろしくお願いします。
  • LunaJamです。

    E0111はヘルプを見ると
    『ファイル内のグローバル変数に割り当てられた領域が64 Kバイトの制限を越えました。』
    とあります。

    モジュール分割しているならダブっている可能性があります。

    宣言の再チェック\,コンパイラのリストファイルを吐かせて良く確認されたらどうでしょう。