RXv3コアのレジスタ一括退避機能の使い方(Register Bank Save Function Usage)を調べてみるスレッド

こんにちは。NoMaYです。

RXv3コア搭載の120MH動作のRXマイコンも、RX66T以降、RX671、RX66N、RX660と品種が増えてきましたが、RXv3コアのセールスポイントの1つであるレジスタ一括退避機能の使い方が今ひとつピンと来ません。そこで、いつものように、ちょっと好奇心からスレッドを立ててみました。(注: RX66Tは、160MHz動作、レジスタ一括退避機能未搭載、です。) いつものように、ぼちぼちと続きます。

ホワイトペーパー
卓越したMCU性能と電力効率を実現するRXv3コア
2019年10月
www.renesas.com/jp/ja/document/whp/introducing-rxv3-core-superior-performance-excellent-power-efficiency#page=6

割り込み応答時間の改善

モータ制御システムなどは、高速な割り込み処理によるリアルタイム性能が必要となってきます。

RXv3コアには、割り込み処理時にレジスタを高速退避/復帰するために、オプション機能として、レジスタ退避バンクと呼ばれる専用メモリを実装しています。図6に示すように、レジスタ退避バンクを使用することで割り込み応答時間を短縮でき、割り込み処理全体の時間を短縮することができます。 割り込み処理ルーチンの中で、SAVE命令を使用すると汎用レジスタとアキュムレータを1クロックで専用メモリに保存できます。RSTR命令は、保存されたレジスタを3~6cycleで復元します。レジスタ退避バンクは専用メモリを複数面持っており、多重割り込みにも対応することが可能です。

図6.割り込み応答時間の改善

レジスタ退避バンクは、割り込みハンドラだけでなく、RTOSコンテキスト切り替えにも使用できます。 RTOSコンテキスト切り替え時間は、レジスタバンク保存機能により最大20%高速化します。


Parents
  • NoMay さんこんにちは。

    RX66TとRX72Tの違いは、動作周波数くらいだと思っていましたが、この命令郡をサポートしていないとは知りませんでした・・

    ---

    GNU-RX 8.3.0 で、具体的にどのように使うか実験してみました。

    元のコードでは、gcc の割り込み関数アトリビュートを使っていましたが、アセンブラ命令を追加して、以下のように修正しました。

    ```

    //      static INTERRUPT_FUNC void i_task_()
            static void i_task_()
            {
                asm("save #0");
                ++counter_;
                task_();
                asm("rstr #0");
                asm("rte");
            }

    ```

    コンパイルされたアセンブラ命令:

    ```

    fff81c38 <__ZN6device7cmt_mgrINS_5cmt_tILm557058ELNS_10peripheralE41ENS_6icuc_tIvE6VECTORELS5_28EEEN5utils9null_taskEE7i_task_Ev>:
    fff81c38: fd 76 e0 00 save #0
    fff81c3c: fb 42 58 05 00 00 mov.l #0x558, r4
    fff81c42: ec 45 mov.l [r4], r5
    fff81c44: 62 15 add #1, r5
    fff81c46: e3 45 mov.l r5, [r4]
    fff81c48: fd 76 f0 00 rstr #0
    fff81c4c: 7f 95 rte
    fff81c4e: 02 rts

    ```

    RX72T で動作確認をして、問題無いようです。

    GNU-RX 8.3.0 では、「-mcpu=rx66T」がありますが、このオプションを指定しても、「save、rstr」はエラーになりません・・

    ※RX66T では、当然動作しません・・

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

    情報どうもありがとうございます。それで、ソースと生成コードをしばらく見ていたら、ん?、っと思ったのですが、ひょっとして task_() は中身が空の関数で且つインライン展開された結果としてサブルーチン呼び出しを含め跡形も無く消えている状況ではないでしょうか?そして、インライン展開ということで、ちょっと気になることがあります。

    後で自分も試してみますが、記憶では、以下のようなことになるのでは無かったかなぁ、という気がするのです。

    (1) インライン展開された結果のコードでR6~R13が使われていると先頭と末尾でPUSH/POPが生成されるような気がします

    (2) それを抑止するために naked アトリビュートを使う必要があった気がします

    あるいは

    (3) インライン展開されないように呼び出される関数を以下のようにしたりとか

    (3-1) もし同じファイルにあるなら呼び出される関数に noinline アトリビュートを使う
    (3-2) あるいは呼び出される関数を別のファイルに記述する

    ただ、その場合、、、

    (3-3) JSR/RTSのオーバーヘッド(少なくとも3+5=8クロック)が追加されてしまいます、、、

    [追記]

    あっ、naked アトリビュートを使っても駄目かも知れません。自動変数の分のスタックの確保も行われなくなるような、、、

Reply
  • hirakuni45さん、こんにちは。NoMaYです。

    情報どうもありがとうございます。それで、ソースと生成コードをしばらく見ていたら、ん?、っと思ったのですが、ひょっとして task_() は中身が空の関数で且つインライン展開された結果としてサブルーチン呼び出しを含め跡形も無く消えている状況ではないでしょうか?そして、インライン展開ということで、ちょっと気になることがあります。

    後で自分も試してみますが、記憶では、以下のようなことになるのでは無かったかなぁ、という気がするのです。

    (1) インライン展開された結果のコードでR6~R13が使われていると先頭と末尾でPUSH/POPが生成されるような気がします

    (2) それを抑止するために naked アトリビュートを使う必要があった気がします

    あるいは

    (3) インライン展開されないように呼び出される関数を以下のようにしたりとか

    (3-1) もし同じファイルにあるなら呼び出される関数に noinline アトリビュートを使う
    (3-2) あるいは呼び出される関数を別のファイルに記述する

    ただ、その場合、、、

    (3-3) JSR/RTSのオーバーヘッド(少なくとも3+5=8クロック)が追加されてしまいます、、、

    [追記]

    あっ、naked アトリビュートを使っても駄目かも知れません。自動変数の分のスタックの確保も行われなくなるような、、、

Children
No Data