RX631のメモリプロテクションユニットの件

IKUZOと申します、RX631のメモリプロテクションユニットの使用方法がわかりません、サンプルコードも探したのですが該当が無いようです、アドバイスをいただけませんでしょうか?

Parents
  • IKUZOさん、こんにちは。NoMaYです。

    RX62N,RX621グループ用の資料がありますが、RX63N,RX631グループでも参考になりそうな気がします。(すみません、検索して見つかったものをチラ見した程度ですが、、、)

    Renesasキーワード検索: メモリプロテクションユニット
    www.renesas.com/ja-jp/search/keyword-search.html#q=メモリプロテクションユニット

    ドキュメント: RX62N、RX621グループ メモリプロテクションユニットの設定例
    www.renesas.com/ja-jp/doc/products/mpumcu/apn/rx/001/r01an1078jj0100_rx62n.pdf

    サンプルプログラム: RX62N、RX621グループ メモリプロテクションユニットの設定例
    www.renesas.com/ja-jp/software/D3014498.html

  • NoMaYさん
    いつもお世話になっております、有益な資料をお教えいただき感謝します、早速調べまして活用するようにいたします、良い結果が出ましたらまたご報告いたします。
  • こんにちは。circleです。
    いまひとつIKUZOさんが何をしたくて、
    現状、何が問題なのかが分からないのですが、
    整理してまとめていただけませんでしょうか?

    ハードウェアマニュアルの「表17.1 メモリプロテクションの仕様」に

    "スーパバイザモード時はメモリ保護なし"という記載と関係しているのではないでしょうか?

  • circleさん
    お世話になります、ここでひとまず以前使用していた、YRDKRX63N評価ボードに最初から設定してみたいと思います
    1.intprg_.srcを作成->_Excep_AccessInst
    2.intprg_.srcをプロジェクトに追加
    3.intprg.c のExcep_AccessInst(void){/* brk(); */}をコメントアウト
    4.mpu.cにvoid Access_Inst(void)アクセス例外処理追加
    5.mpu.cにvoid Change_PSW_PM_to_UserMode(void)処理追加
    6.mpu.cにvoid mpu_init(void)処理追加
    7.com.cのコマンドに"T"コマンドからmpu_init(void)を呼び出すように処理追加
    そこでまず、void Change_PSW_PM_to_UserMode(void)のユザーモード設定処理の中の
    OR #00100000h,R1のコードをコメントアウトします、
    8."T"コマンドでmpu_init(void)処理開始
    T
    RSPAGE0=0x00000000
    REPAGE0=0x0000000E
    RSPAGE1=0x00000000
    REPAGE1=0x0000000E
    RSPAGE2=0x00000000
    REPAGE3=0x0000000E
    RSPAGE3=0x00000000
    REPAGE3=0x0000000E
    RSPAGE4=0x00000000
    REPAGE4=0x0000000E
    RSPAGE5=0x00000000
    REPAGE5=0x0000000E
    RSPAGE6=0x00000000
    REPAGE6=0x0000000E
    MPBAC =0x0000000E
    設定成功
    正常にリターンしました.
    Ok
    上記表示はprintfで表示させております
    9.OR #00100000h,R1のコードを有効にして、"T"コマンド
    T
    RSPAGE0=0x00000000
    REPAGE0=0x0000000E
    RSPAGE1=0x00000000
    REPAGE1=0x0000000E
    RSPAGE2=0x00000000
    REPAGE3=0x0000000E
    RSPAGE3=0x00000000
    REPAGE3=0x0000000E
    RSPAGE4=0x00000000
    REPAGE4=0x0000000E
    RSPAGE5=0x00000000
    REPAGE5=0x0000000E
    RSPAGE6=0x00000000
    REPAGE6=0x0000000E
    MPBAC =0x0000000E
    設定成功←関数の最後まで到達しています
    ←関数がリターンしておりません(メインループ停滞)
    デバッグ用の処理
    int cmd_test(char *str)
    {
    mpu_init();
    printf("正常にリターンしました.\r");
    return CMD_OK;
    }
    10.MPU.MPBAC.BIT.UBAC=0;に変更して、"T"コマンド
    T
    RSPAGE0=0x00000000
    REPAGE0=0x0000000E
    RSPAGE1=0x00000000
    REPAGE1=0x0000000E
    RSPAGE2=0x00000000
    REPAGE3=0x0000000E
    RSPAGE3=0x00000000
    REPAGE3=0x0000000E
    RSPAGE4=0x00000000
    REPAGE4=0x0000000E
    RSPAGE5=0x00000000
    REPAGE5=0x0000000E
    RSPAGE6=0x00000000
    REPAGE6=0x0000000E
    MPBAC =0x00000000
    *******************************←Access_Inst(void)アクセス例外処理を何度も呼び出します
    アクセス例外の処理
    uint32_t g_mpu_err_instruction_adrs;
    void Access_Inst(void)
    {
    sci2_put('*');
    MPU.MPECLR.BIT.CLR=1;
    }
    質問:
    9. の段階でのリターンしない原因(例外要因は無し)
    10.例外処理を何度も呼び出す原因(スパーバイザーになるので1度のみのはず)
    よろしくお願いいたします。
  • この折にE1エミュレータ [R0E000010KCE00]の見積もりを販売店にお願いしました。
  • こんにちは。circleです。
    ありがとうございます。

    御認識している部分も含まれているかと思いますが、
    その部分は読み飛ばしてください。

    (ハードウェアマニュアル 17.3.3を参照ください)
    まず、以下は認識されていますよね?
    メモリプロテクションユニット関連レジスタへは、スーパバイザモードでのみアクセスすることができます。ユーザモードでCPU のオペランドアクセスでメモリプロテクションユニット関連レジスタへのアクセスを行った場合には、
    メモリプロテクション機能が有効かどうかに関わらずデータメモリプロテクションエラーが発生します。


    9.に関しては、
    先日も書き込みしましたが、
    "スーパバイザモード時はメモリ保護なし"であり、スーパバイザモード時にアクセス例外は発生しないと考えられます。
    "ユーザモード"のみの事象であれば、
    範囲外へのアクセスが発生していると考えるのが自然かと思います。
    (文面を見る限り、アクセス例外の発生有無は確認されていないのではないかと)

    RSPAGEx=0x00000000;
    REPAGEx=0x0000000E;
    となっており、下位4ビットは設定できませんので、
    0x00000000 ~ 0x0000000F がアクセス制御領域となっており、
    それ以外がバックグラウンド領域になっているのではないかと思います。
    ユーザモードで0x00000000 ~ 0x0000000F にアクセスしてはいないでしょうか?
    領域設定有効にして動作に変化はないか、確認してみてはいかがでしょうか?

    10. に関しては、
    (ハードウェアマニュアル 2.3.4を参照ください)
    アクセス例外発生
     ↓
    ユーザモードで割り込みが発生した場合は、スーパバイザモードに移行しますが、
    割り込み処理が終了後は、退避されたPSWが設定されるため、
    ユーザモードに移行すると考えられます。
     ↓
    その後、再びアクセス例外発生が発生する。
    という形で、繰り返し例外処理を何度も呼び出す動作になっているのではないでしょうか?
    (ソースコードがC言語で記述されているようですので、
     エミュレータがあれば逆アセンブラで確認できると思います。
     なければ、コンパイルされたアセンブラを出力する設定をし、出力されたファイルを確認する方法があると思います)
  • circleさん
    アドバイス、ありがたく思います、
    9.に関して「
    RSPAGEx=0x00000000;
    REPAGEx=0x0000000E;
    となっており、下位4ビットは設定できませんので、
    0x00000000~0x0000000F がアクセス制御領域となっており」
    「下位4ビットは設定できません」でしたか?
    下位4ビットですがスーパバイザモード時に
    R:Enable,W:Enable,X:Enable,Area_Valid:V=1110 (アクセス許可:無効)
    で設定できませんでしたでしょうか?
    mpu_init();を実行する前はMPUにはタッチしていませんのでスーパバイザモード
    と考えております、この点はサンプルソフトと異なりまして
    resetprg.cにはmpu_init();の部分は除いております。

    10. に関しては
    「割り込み処理が終了後は、退避されたPSWが設定される」ということで
    納得いたしました。
  • 0x00000000~0x0000000F がアクセス制御領域
    つまり規定の個所でこれは設定できず、MPUを有効にすると
    この個所はレジスターで無効に設定することができず、0x00000000~0x0000000F のアクセスがあると
    必ずなにかしらの例外が発生する、ということなのでしょうか?
    それにしても、Access_Inst(void)アクセス例外処理には飛んで無いような感じですが?
  • すみません。
    言葉が足りませんでした。

    領域開始ページ番号の
    RSPAGEnのRSPN[27:0]が28ビットしかないため、
    アドレス空間でいう下位4ビットという意味です。
    領域終了ページ番号の
    REPAGEnのREPN[27:0]も同様です。
    このため、以下の設定ですと、
    RSPAGEnのRSPN[27:0]=0;
    REPAGEnのREPN[27:0]=0;
    アクセス制御領域が0x00000000~0x0000000F となっているのではないかということです。

  • circleさん
    回答ありがとうございます、「
    RSPAGEnのRSPN[27:0]=0;
    REPAGEnのREPN[27:0]=0;」
    は「0x00000000~0x0000000F」ですよね
    つまり16Byteページアドレスというわけですよね、
    でもどんなページアドレスが設定されていても、
    下位4ビットですがスーパバイザモード時に
    R:Enable,W:Enable,X:Enable,Area_Valid:V=1110 (アクセス許可:無効)
    の設定であれば上記ページアドレスは無効ではないかと思うのですが?
  • マップを調整しまして、
    SRAMの部分を0x00000020から使用するように変更いたしましたが
    9.の状況は変化ございませんでした、アドバイスがありましたら
    よろしくお願いいたします
  • 結局、9においてアクセス例外の発生有無は確認したのですか?
    RSPAGE7、REPAGE7はどうなっているのですか?
    マニュアルを見て分からなければ、実際に動作させてみて
    自分の認識と違いがないかを確認すればよいと思いますが?
Reply
  • 結局、9においてアクセス例外の発生有無は確認したのですか?
    RSPAGE7、REPAGE7はどうなっているのですか?
    マニュアルを見て分からなければ、実際に動作させてみて
    自分の認識と違いがないかを確認すればよいと思いますが?
Children
  • circleさん
    回答ありがとうございます、詳しいことが解りましたら、問題ございません
    現状の状態でございますが、ターミナルモニターからは
    -------------------------------------------------------
    T←"T"コマンドでmpu_init();が実行されます(スパーバイザーモード)
    RSPAGE0=0x00000000←MPUレジスタ設定後にprintfでレジスターをダンプしております
    REPAGE0=0x0000000E←REPAGE0のレジスター値
    RSPAGE1=0x00000000←RSPAGE1のレジスター値
    REPAGE1=0x0000000E←REPAGE1のレジスター値
    RSPAGE2=0x00000000←RSPAGE2のレジスター値
    REPAGE3=0x0000000E←REPAGE3のレジスター値
    RSPAGE3=0x00000000←RSPAGE3のレジスター値
    REPAGE3=0x0000000E←REPAGE3のレジスター値
    RSPAGE4=0x00000000←RSPAGE4のレジスター値
    REPAGE4=0x0000000E←REPAGE4のレジスター値
    RSPAGE5=0x00000000←RSPAGE5のレジスター値
    REPAGE5=0x0000000E←REPAGE5のレジスター値
    RSPAGE6=0x00000000←RSPAGE6のレジスター値
    REPAGE6=0x0000000E←REPAGE6のレジスター値
    MPBAC =0x0000000E←MPBACのレジスター値
    設定成功←関数の最後まで到達しています(MPU.MPEN.LONG=(long)1;の後)
    ←関数がリターンしておりません
    -------------------------------------------------------
    アクセス例外では'*'を表示されるはずと思うので、多分アクセス例外には来ていないのでは
    ないかと思います、pingコマンドとか、ウエブサーバー等は普通に使用できますので
    どこかの割り込みを占有しているということはなさそうです、ここが不思議です
    メインループのみが停止しているような現象に見えます、
    エミュレータで確認しないと、このようなものはprintfではデバックがしにくいですね
    なにか簡単に確かめる方法がありましたら、ご教示お願いできれば幸せです
  • circleさん
    失礼しました
    RSPAGE7、REPAGE7がありましたね、どうも、どうも、早速テストしてみます。
  • circleさん
    早速足らないところ、修正いたしました、結果は同じでした
    -------------------------------------------------------
    T
    RSPAGE0=0x00000000
    REPAGE0=0x0000000E
    RSPAGE1=0x00000000
    REPAGE1=0x0000000E
    RSPAGE2=0x00000000
    REPAGE3=0x0000000E
    RSPAGE3=0x00000000
    REPAGE3=0x0000000E
    RSPAGE4=0x00000000
    REPAGE4=0x0000000E
    RSPAGE5=0x00000000
    REPAGE5=0x0000000E
    RSPAGE6=0x00000000
    REPAGE6=0x0000000E
    RSPAGE7=0x00000000←修正
    REPAGE7=0x0000000E←修正
    MPBAC =0x0000000E
    設定成功
    -------------------------------------------------------
  • リトルエンディアン/ビッグエンディアンは関係ないのだろうとは思っておりますが
    サンプルコードはリトルエンディアンでした
    この実験ボードはビッグエンディアンで使用しております。
  • でしたら、
    9.と10.で何を変えたのか、
    MPUの処理を全てコメントアウトして動作が変わるか、
    Change_PSW_PM_to_UserMode関数の前後で
    汎用レジスタ等が正しいか等、
    1つ1つ(再)確認していくしかないと思います。
    投稿されている情報だけでは何とも言えないです。
  • triangleさん
    御心配かけまして、どうも
    「9.と10.で何を変えたのか」
    9.でございますが
    MPBAC =0x0000000E としています
    10.でございますが
    MPBAC =0x00000000 としています
    「Change_PSW_PM_to_UserMode関数の前後で
    汎用レジスタ等が正しいか等、
    1つ1つ(再)確認していくしかないと思います。」そうですよね
    サンプルがRX62n用のものなのでRX631とレジスター構成等が同じかどうか
    基本的に調べないとならないかな、というように感じます
    サンプルではnop();が1個入っていまして、最初動作しなかったように思います
    このnop();を増やしまして、動作できるようになったと記憶します
    スタックサイズ(ワード/ダブルワード)等もどうだろうか?と思います
    互換性がすっきしないという印象です
  • ここで一応mpu.cのソースを開示します
    ///////////////////////////////////////////////////////////////////////
    //アクセス例外
    ///////////////////////////////////////////////////////////////////////
    uint32_t g_mpu_err_instruction_adrs;
    void Access_Inst(void)
    {
    sci2_put('*');
    MPU.MPECLR.BIT.CLR=1;
    }
    ///////////////////////////////////////////////////////////////////////
    //アクセス例外
    ///////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////
    //スーパバイザモードからユーザモードに変更
    ///////////////////////////////////////////////////////////////////////
    void Change_PSW_PM_to_UserMode(void)
    {
    MVFC PSW,R1
    OR #00100000h,R1←ユザーモードフラグ(コメントアウトするとスパーバイザー)
    PUSH.L R1
    MVFC PC,R1
    ADD #10,R1
    PUSH.L R1
    RTE
    NOP
    NOP
    NOP
    NOP
    NOP
    NOP
    }
    ///////////////////////////////////////////////////////////////////////
    //スーパバイザモードからユーザモードに変更
    ///////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////
    //MPUの初期化
    ///////////////////////////////////////////////////////////////////////
    void mpu_init(void)
    {
    MPU.RSPAGE0.LONG=0;
    MPU.REPAGE0.BIT.REPN=0;
    MPU.REPAGE0.BIT.UAC=7;
    MPU.REPAGE0.BIT.V=0;
    MPU.RSPAGE1.LONG=0;
    MPU.REPAGE1.BIT.REPN=0;
    MPU.REPAGE1.BIT.UAC=7;
    MPU.REPAGE1.BIT.V=0;
    MPU.RSPAGE2.LONG=0;
    MPU.REPAGE2.BIT.REPN=0;
    MPU.REPAGE2.BIT.UAC=7;
    MPU.REPAGE2.BIT.V=0;
    MPU.RSPAGE3.LONG=0;
    MPU.REPAGE3.BIT.REPN=0;
    MPU.REPAGE3.BIT.UAC=7;
    MPU.REPAGE3.BIT.V=0;
    MPU.RSPAGE4.LONG=0;
    MPU.REPAGE4.BIT.REPN=0;
    MPU.REPAGE4.BIT.UAC=7;
    MPU.REPAGE4.BIT.V=0;
    MPU.RSPAGE5.LONG=0;
    MPU.REPAGE5.BIT.REPN=0;
    MPU.REPAGE5.BIT.UAC=7;
    MPU.REPAGE5.BIT.V=0;
    MPU.RSPAGE6.LONG=0;
    MPU.REPAGE6.BIT.REPN=0;
    MPU.REPAGE6.BIT.UAC=7;
    MPU.REPAGE6.BIT.V=0;
    MPU.RSPAGE7.LONG=0;
    MPU.REPAGE7.BIT.REPN=0;
    MPU.REPAGE7.BIT.UAC=7;
    MPU.REPAGE7.BIT.V=0;
    MPU.MPBAC.BIT.UBAC=7;//111←その他の保護領域(0にすると例外発生します)
    printf("RSPAGE0=0x%08lX\r",MPU.RSPAGE0.LONG );
    printf("REPAGE0=0x%08lX\r",MPU.REPAGE0.LONG );
    printf("RSPAGE1=0x%08lX\r",MPU.RSPAGE1.LONG );
    printf("REPAGE1=0x%08lX\r",MPU.REPAGE1.LONG );
    printf("RSPAGE2=0x%08lX\r",MPU.RSPAGE2.LONG );
    printf("REPAGE3=0x%08lX\r",MPU.REPAGE2.LONG );
    printf("RSPAGE3=0x%08lX\r",MPU.RSPAGE3.LONG );
    printf("REPAGE3=0x%08lX\r",MPU.REPAGE3.LONG );
    printf("RSPAGE4=0x%08lX\r",MPU.RSPAGE4.LONG );
    printf("REPAGE4=0x%08lX\r",MPU.REPAGE4.LONG );
    printf("RSPAGE5=0x%08lX\r",MPU.RSPAGE5.LONG );
    printf("REPAGE5=0x%08lX\r",MPU.REPAGE5.LONG );
    printf("RSPAGE6=0x%08lX\r",MPU.RSPAGE6.LONG );
    printf("REPAGE6=0x%08lX\r",MPU.REPAGE6.LONG );
    printf("RSPAGE7=0x%08lX\r",MPU.RSPAGE7.LONG );
    printf("REPAGE7=0x%08lX\r",MPU.REPAGE7.LONG );
    printf("MPBAC =0x%08lX\r",MPU.MPBAC.LONG );
    MPU.MPEN.LONG=(long)1;//メモリプロテクション機能を有効
    Change_PSW_PM_to_UserMode();//ユザーモードに
    nop();
    nop();
    nop();
    nop();
    nop();
    nop();
    nop();
    nop();
    nop();
    nop();
    nop();
    nop();
    printf("設定成功\r");←ここまではOK
    }
    ///////////////////////////////////////////////////////////////////////
    //MPUの初期化
    ///////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////
    //デバックテスト用
    ///////////////////////////////////////////////////////////////////////
    int cmd_test(char *str)
    {
    mpu_init();
    printf("正常にリターンしました.\r");←保護ONでは例外なし、ここまで来ず
    return CMD_OK;
    }
    ///////////////////////////////////////////////////////////////////////
    //デバックテスト用
    ///////////////////////////////////////////////////////////////////////

  • この折にE1エミュレータ [R0E000010KCE00]販売店にお願いしました。

  • お願いしていたE1エミュレータ [R0E000010KCE00]が今到着しました。
  • とりあえず、

    E1エミュレータをRX631に接続したいのですが

    E1エミュレータ接続は今すぐできませんということでして
    シミュレータ等でできるのかもしれないことを伺いましたので
    その方向で行ければと思います