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です。

    CGコンポーネントでユーザ記述部だけで割り込み関数先頭での多重割り込み許可を設定する小細工が思い浮かんだので書いておきます。


    CC-RX : コンパイルオプションに -save_acc (割り込み関数でのアキュムレータの退避/復帰を行う)を指定

    ソース例: Config_RIIC0_user.c

    /* Start user code for global. Do not edit comment generated here */

    #undef  VECT
    #define VECT( x , y ) _VECT( _ ## x ## _ ## y ), enable

    /* End user code. Do not edit comment generated here */

     

    #if FAST_INTERRUPT_VECTOR == VECT_RIIC0_TXI0
    #pragma interrupt r_Config_RIIC0_transmit_interrupt(vect=VECT(RIIC0,TXI0),fint)
    #else
    #pragma interrupt r_Config_RIIC0_transmit_interrupt(vect=VECT(RIIC0,TXI0))
    #endif
    static void r_Config_RIIC0_transmit_interrupt(void)
    {
        …途中省略…
    }

     

    #if FAST_INTERRUPT_VECTOR == VECT_RIIC0_RXI0
    #pragma interrupt r_Config_RIIC0_receive_interrupt(vect=VECT(RIIC0,RXI0),fint)
    #else
    #pragma interrupt r_Config_RIIC0_receive_interrupt(vect=VECT(RIIC0,RXI0))
    #endif
    static void r_Config_RIIC0_receive_interrupt(void)
    {
        …途中省略…
    }

     
    リストファイル: アキュムレータが使われない/値が壊れないことを認識してアキュムレータの退避/復帰を省略していますね

    00000001         __$r_Config_RIIC0_transmit_interrupt:
                            .STACK  __$r_Config_RIIC0_transmit_interrupt=24
                            .RVECTOR    53,__$r_Config_RIIC0_transmit_interrupt
    00000001 7FA8           SETPSW I
    00000003 6E14           PUSHM R1-R4

                            …途中省略…

    00000048 6F14           POPM R1-R4
    0000004A 7F95           RTE
                            …途中省略…
    00000061 6F14           POPM R1-R4
    00000063 7F95           RTE
                            …途中省略…
    00000082 6F14           POPM R1-R4
    00000084 7F95           RTE
                            …途中省略…
    000000B2 6F14           POPM R1-R4
    000000B4 7F95           RTE
                            …途中省略…
    000000D8 6F14           POPM R1-R4
    000000DA 7F95           RTE
                            …途中省略…
    000000F4 6F14           POPM R1-R4
    000000F6 7F95           RTE
                            …途中省略…
    00000112 6F14           POPM R1-R4
    00000114 7F95           RTE

     

    00000156         __$r_Config_RIIC0_receive_interrupt:
                            .STACK  __$r_Config_RIIC0_receive_interrupt=32
                            .RVECTOR    52,__$r_Config_RIIC0_receive_interrupt
    00000156 7FA8           SETPSW I
    00000158 6E15           PUSHM R1-R5
                            …1行省略…
    00000160 6040           SUB #04H, R0

                            …途中省略…

    0000025D 6240           ADD #04H, R0
    0000025F 6F15           POPM R1-R5
    00000261 7F95           RTE

     

    ICCRX : コンパイルオプションに --save_acc (割り込み関数でアキュムレータの退避/復帰を行う)を指定

    ソース例: Config_RIIC0_user.c

    /* Start user code for global. Do not edit comment generated here */

    #define __interrupt __interrupt __nested

    /* End user code. Do not edit comment generated here */

     

    #pragma vector = VECT_RIIC0_TXI0
    #if FAST_INTERRUPT_VECTOR == VECT_RIIC0_TXI0
    __fast_interrupt static void r_Config_RIIC0_transmit_interrupt(void)
    #else
    __interrupt static void r_Config_RIIC0_transmit_interrupt(void)
    #endif
    {
        …途中省略…
    }

     

    #pragma vector = VECT_RIIC0_RXI0
    #if FAST_INTERRUPT_VECTOR == VECT_RIIC0_RXI0
    __fast_interrupt static void r_Config_RIIC0_receive_interrupt(void)
    #else
    __interrupt static void r_Config_RIIC0_receive_interrupt(void)
    #endif
    {
        …途中省略…
    }

     
    リストファイル: そもそもバグによりアキュムレータの退避/復帰を行うコードが生成されないみたいですね

       \                                 In section .text, align 1, keep-with-next
       \                     ___interrupt_53:
       \   000000 7F A8        SETPSW    I
       \   000002 7E AE        PUSH.L    R14
       \   000004 6E 16        PUSHM     R1-R6

                               …途中省略…

       \   0000FD 6F 16        POPM      R1-R6
       \   0000FF 7E BE        POP       R14
       \   000101 7F 95        RTE

     

       \                                 In section .text, align 1, keep-with-next
       \                     ___interrupt_52:
       \   000000 7F A8        SETPSW    I
       \   000002 6E EF        PUSHM     R14-R15
       \   000004 6E 16        PUSHM     R1-R6
       \   000006 60 40        SUB       #0x4,SP

                               …途中省略…

       \   000093 62 40        ADD       #0x4,SP
       \   000095 6F 16        POPM      R1-R6
       \   000097 6F EF        POPM      R14-R15
       \   000099 7F 95        RTE

     

    GNURX : コンパイルオプションに -msave-acc-in-interrupts (割り込み関数でアキュムレータの退避/復帰を行う)を指定

    ソース例: Config_RIIC0_user.c

    /* Start user code for global. Do not edit comment generated here */

    void r_Config_RIIC0_transmit_interrupt(void) __attribute__ ((naked));
    void r_Config_RIIC0_transmit_interrupt(void)
    {
        __asm volatile ("SETPSW I");
        __asm volatile ("BRA.S __r_Config_RIIC0_transmit_interrupt"); /* BRA.S is not necessary but it is intended for the safe. */
    }
    void _r_Config_RIIC0_transmit_interrupt(void) __attribute__ ((interrupt, section(".text.r_Config_RIIC0_transmit_interrupt")));
    #define r_Config_RIIC0_transmit_interrupt _r_Config_RIIC0_transmit_interrupt

    void r_Config_RIIC0_receive_interrupt(void) __attribute__ ((naked));
    void r_Config_RIIC0_receive_interrupt(void)
    {
        __asm volatile ("SETPSW I");
        __asm volatile ("BRA.S __r_Config_RIIC0_receive_interrupt"); /* BRA.S is not necessary but it is intended for the safe. */
    }
    void _r_Config_RIIC0_receive_interrupt(void) __attribute__ ((interrupt, section(".text.r_Config_RIIC0_receive_interrupt")));
    #define r_Config_RIIC0_receive_interrupt _r_Config_RIIC0_receive_interrupt

    /* End user code. Do not edit comment generated here */

     

    void r_Config_RIIC0_transmit_interrupt(void)
    {
        …途中省略…
    }

     

    void r_Config_RIIC0_receive_interrupt(void)
    {
        …途中省略…
    }

     
    リストファイル:

       4                     .section .text.r_Config_RIIC0_transmit_interrupt,"ax",@progbits
       5                     .global _r_Config_RIIC0_transmit_interrupt
       7                 _r_Config_RIIC0_transmit_interrupt:
      11                     .global $tableentry$53$.rvectors
      12                 $tableentry$53$.rvectors:
      13                     ; Note: Interrupt Handler
      14                     ; Note: Naked Function
      17 0000 7F A8          SETPSW I
      21 0002 08             BRA.S __r_Config_RIIC0_transmit_interrupt

      27                     .global __r_Config_RIIC0_transmit_interrupt
      29                 __r_Config_RIIC0_transmit_interrupt:
      33 0003 6E 15          pushm   r1-r5
      35 0005 FD 1F 11       mvfaclo #0, A0, r1
      36 0008 FD 1F 02       mvfachi r2
      37 000b 6E 12          pushm   r1-r2
      38 000d FD 1F 31       mvfacgu #0, A0, r1
      39 0010 FD 1F 92       mvfaclo #0, A1, r2
      40 0013 6E 12          pushm   r1-r2
      41 0015 FD 1F 81       mvfachi #0, A1, r1
      42 0018 FD 1F B2       mvfacgu #0, A1, r2
      43 001b 6E 12          pushm   r1-r2

                             …途中省略…

      59 0030 6F 12          popm    r1-r2
      60 0032 FD 17 81       mvtachi r1, A1
      61 0035 FD 17 B2       mvtacgu r2, A1
      62 0038 6F 12          popm    r1-r2
      63 003a FD 17 31       mvtacgu r1, A0
      *** 003d FD 17 92       mvtaclo r2, A1
      65 0040 6F 12          popm    r1-r2
      66 0042 FD 17 11       mvtaclo r1
      67 0045 FD 17 02       mvtachi r2
      68 0048 6F 15          popm    r1-r5
      69 004a 7F 95          rte
                             …途中省略…
     173 00e7 6F 12          popm    r1-r2
     174 00e9 FD 17 81       mvtachi r1, A1
     175 00ec FD 17 B2       mvtacgu r2, A1
     176 00ef 6F 12          popm    r1-r2
     177 00f1 FD 17 31       mvtacgu r1, A0
     178 00f4 FD 17 92       mvtaclo r2, A1
     179 00f7 6F 12          popm    r1-r2
     180 00f9 FD 17 11       mvtaclo r1
     181 00fc FD 17 02       mvtachi r2
     182 00ff 6F 15          popm    r1-r5
     183 0101 7F 95          rte
                             …途中省略…
     213 0133 6F 12          popm    r1-r2
     214 0135 FD 17 81       mvtachi r1, A1
     215 0138 FD 17 B2       mvtacgu r2, A1
     216 013b 6F 12          popm    r1-r2
     217 013d FD 17 31       mvtacgu r1, A0
     218 0140 FD 17 92       mvtaclo r2, A1
     219 0143 6F 12          popm    r1-r2
     220 0145 FD 17 11       mvtaclo r1
     221 0148 FD 17 02       mvtachi r2
     222 014b 6F 15          popm    r1-r5
     223 014d 7F 95          rte

     

     271                     .section .text.r_Config_RIIC0_receive_interrupt,"ax",@progbits
     272                     .global _r_Config_RIIC0_receive_interrupt
     274                 _r_Config_RIIC0_receive_interrupt:
     277                     .global $tableentry$52$.rvectors
     278                 $tableentry$52$.rvectors:
     279                     ; Note: Interrupt Handler
     280                     ; Note: Naked Function
     283 0000 7F A8          SETPSW I
     287 0002 08             BRA.S __r_Config_RIIC0_receive_interrupt

     293                     .global __r_Config_RIIC0_receive_interrupt
     295                 __r_Config_RIIC0_receive_interrupt:
     298                     ; Note: Interrupt Handler
     299 0003 6E EF          pushm   r14-r15
     301 0005 6E 15          pushm   r1-r5
     303 0007 FD 1F 11       mvfaclo #0, A0, r1
     304 000a FD 1F 02       mvfachi r2
     305 000d 7E A1          push.l  r1
     306 000f 7E A2          push.l  r2
     307 0011 FD 1F 31       mvfacgu #0, A0, r1
     308 0014 FD 1F 92       mvfaclo #0, A1, r2
     309 0017 7E A1          push.l  r1
     310 0019 7E A2          push.l  r2
     311 001b FD 1F 81       mvfachi #0, A1, r1
     312 001e FD 1F B2       mvfacgu #0, A1, r2
     313 0021 7E A1          push.l  r1
     314 0023 7E A2          push.l  r2
     315 0025 60 40          sub #4, r0

                             …途中省略…

     378 0070 62 40          add #4, r0
     379 0072 7E B2          pop r2
     380 0074 7E B1          pop r1
     381 0076 FD 17 81       mvtachi r1, A1
     382 0079 FD 17 B2       mvtacgu r2, A1
     383 007c 7E B2          pop r2
     384 007e 7E B1          pop r1
     385 0080 FD 17 31       mvtacgu r1, A0
     386 0083 FD 17 92       mvtaclo r2, A1
     387 0086 7E B2          pop r2
     388 0088 7E B1          pop r1
     389 008a FD 17 11       mvtaclo r1
     390 008d FD 17 02       mvtachi r2
     391 0090 6F 15          popm    r1-r5
     392 0092 6F EF          popm    r14-r15
     393 0094 7F 95          rte

     

  • NoMay さんこんにちは。

    今回の話題とは少し違いますが、「多重割り込み」について思うところがあります。

    そもそも、多重割り込みが必要なケースは、どんな場合があるでしょうか?

    大抵は、割り込み内から行う処理は、最小限にして、直ぐに割り込みを抜けるようにするので、割り込み内で、長時間処理を行う必要性がある場合は限られるのでは無いでしょうか?

    ※ハードウェアーのフラグが変化するまで待機するとかは論外と思います。

    少なくとも、SCI、I2C、SPI、A/D変換、どれも、多重割り込みが必要なケースを思い浮かびません。

    RXマイコンのペリフェラル系は、殆どがその事に留意して設計されており、割り込み内では、単純にレジスターを読み込んでバッファーにストアするだけで大抵は完了します。

    もちろん、多重割り込みが全く必要無いという事にはなりません。

    また、割り込み内で時間がかかりそうな処理があるなら、少し工夫すれば、追い出してメイン側で行う事は出来ると思います。

    多重割り込みを可能にする方法を提供する事は重要ですが、割り込み内処理が短く、必要性が薄いのなら、プロファイルとして、「多重割り込み不可」とすれば良いように思います。

    自分は、多重割り込みを必要とするケースはかなり低いと考えています。

Reply
  • NoMay さんこんにちは。

    今回の話題とは少し違いますが、「多重割り込み」について思うところがあります。

    そもそも、多重割り込みが必要なケースは、どんな場合があるでしょうか?

    大抵は、割り込み内から行う処理は、最小限にして、直ぐに割り込みを抜けるようにするので、割り込み内で、長時間処理を行う必要性がある場合は限られるのでは無いでしょうか?

    ※ハードウェアーのフラグが変化するまで待機するとかは論外と思います。

    少なくとも、SCI、I2C、SPI、A/D変換、どれも、多重割り込みが必要なケースを思い浮かびません。

    RXマイコンのペリフェラル系は、殆どがその事に留意して設計されており、割り込み内では、単純にレジスターを読み込んでバッファーにストアするだけで大抵は完了します。

    もちろん、多重割り込みが全く必要無いという事にはなりません。

    また、割り込み内で時間がかかりそうな処理があるなら、少し工夫すれば、追い出してメイン側で行う事は出来ると思います。

    多重割り込みを可能にする方法を提供する事は重要ですが、割り込み内処理が短く、必要性が薄いのなら、プロファイルとして、「多重割り込み不可」とすれば良いように思います。

    自分は、多重割り込みを必要とするケースはかなり低いと考えています。

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

    リプライありがとうございます。多重割り込みの小細工の件は、このスレッドの主題に因るところが大きいです。実は、私はといえば、たとえ10ms掛かるような割り込み処理があるプログラム(かつ多重割り込みさえ使っていないもの)でも、業務発注元からの要求仕様を満たしつつ、半年とか1年とか連続稼動するプログラムであれば、そういうのでも構わないと思っていたりします。(もっとも、それで済むようなプログラム開発業務はとても稀な業務だとは思いますけれども。)

    その一方で、このスレッドでは、私は、こんな風に考えるようになっています。(10クロックは寧ろ15クロックとすべき、とか、20クロックは寧ろ30クロックとすべき、とか、突っ込みはあるでしょうけれども。)


    (1) レジスタ一括退避機能を使用して割り込み応答性を改善出来るといっても、5クロックとか、10クロックとか、20クロックとか、ぐらいである

    (1') アキュムレータを使わないようなプログラムでは、5クロックとか、10クロックとか、そんなぐらいである

    (1'') 10クロックとか改善されるケースを想像してみると、そもそも大量にレジスタを使う複雑な処理なのだから、応答性だけ改善する意義は少ないかと


    (2) 他方で、割り込み処理をシンプルにすれば良いといっても、さすがに、多くの割り込み処理が数クロックで終わる、ことも無いと思う

    (2') カウンタをインクリメントする程度の処理なら、それくらいでしょうけれども

    (2'') 例えば、昨日の投稿で例に使ったConfig_RIIC0_user.cの割り込み処理も、下の方に添付したように、数クロックで終わるものでも無いです

    (2''') ちなみに、サブルーチン呼び出しのオーバーヘッドは3+5=8クロックだったり、内蔵周辺I/Oレジスタアクセスには数クロックウェイトが入ったりします


    (3) 例えば100クロックとか多重割り込み不可の期間があっても動作し続けるプログラムなら、レジスタ一括退避機能で5クロック改善する必要も無いかと

    (3') もっとも、割り込み発生タイミングが重ならないことが保証されているなら、そこまでは言いませんけれども


    (4) 例えば、hirakuni45さんの文面を借りれば、そもそも私は、割り込み応答性を5クロック改善することが必須であるようなケースが思い浮かびません

    (4') ましてや、100クロックとか多重割り込み不可の期間が存在していても構わないのに、かつ、5クロック改善することが必須であるとか、想像出来ません

    (4'') もっとも、割り込み発生タイミングが重ならないことが保証されているなら、そこまでは言いませんけれども


    (5) 逆に、レジスタ一括退避機能で5クロック改善することが必須であるような案件では、100クロックとか多重割り込み不可の期間は良くないのでは

    (5') 例えば、再度、hirakuni45さんの文面を借りれば、レジスタ一括退避機能で5クロック改善することが必須であるような案件というのは、「もちろん、多重割り込みが全く必要無いという事にはなりません。」ということに該当する案件なのではないかなと思うのです


    補足:

    上の文を読み返していて、説明不足だと思ったのですが、以下の説明が上の文では欠落しているような気がしました。


    (A) 高い割り込み優先度の自前の割り込み処理でレジスタ一括退避機能で割り込み応答性を改善しようとしている、ということを想定している

    (A') FIT/CGの出来合いの割り込み処理については割り込み優先度を低く設定している、ということを想定している

    (A'') 決して、低い割り込み優先度を設定しているFIT/CGの出来合いの割り込み処理にて、レジスタ一括退避機能を使おうとしているのでは無いです


    (B) 一旦、低い割り込み優先度の割り込み処理へ入ってしまうと、多重割り込み不可では、高い割り込み優先度であっても割り込みは受け付けられない

    (B') 低い割り込み優先度の割り込み処理が終わるまで、多重割り込み不可では、高い割り込み優先度の割り込みの受け付けは遅延してしまう

    (B'') 多重割り込み不可というのは、そういう遅延が発生する状況(そういう遅延が発生してしまうかも知れない可能性がある状況)のことである


    以下、昨日の投稿で例に使ったConfig_RIIC0_user.cの割り込み処理の全体のソース(CGコンポーネントのGNURX版)です。(if文で大きく排他的なブロックに分けられた構造ですので、ぱっと見た印象より、割り込み処理の正味の実行クロック数は少ないですけれども。)

    void r_Config_RIIC0_transmit_interrupt(void)
    {
        if (_0D_IIC_MASTER_TRANSMIT == g_riic0_mode_flag)
        {
            if (_01_IIC_MASTER_SENDS_ADR_7_W == g_riic0_state)
            {
                RIIC0.ICDRT = (uint8_t)(g_riic0_slave_address << 1U);
                g_riic0_state = _05_IIC_MASTER_SENDS_DATA;
            }
            else if (_02_IIC_MASTER_SENDS_ADR_10A_W == g_riic0_state)
            {
                RIIC0.ICDRT = (uint8_t)(((g_riic0_slave_address & 0x0300U) >> 7U) | 0x00F0U);
                g_riic0_state = _04_IIC_MASTER_SENDS_ADR_10B;
            }
            else if (_04_IIC_MASTER_SENDS_ADR_10B == g_riic0_state)
            {
                RIIC0.ICDRT = (uint8_t)(g_riic0_slave_address & 0x00FFU);
                g_riic0_state = _05_IIC_MASTER_SENDS_DATA;
            }
            else if (_05_IIC_MASTER_SENDS_DATA == g_riic0_state)
            {
                if (0U < g_riic0_tx_count)
                {
                    RIIC0.ICDRT = *gp_riic0_tx_address;
                    gp_riic0_tx_address++;
                    g_riic0_tx_count--;
                }
                else
                {
                    g_riic0_state = _06_IIC_MASTER_SENDS_END;
                }
            }
            else
            {
                 /* Do nothing */
            }
        }
        else if (_0C_IIC_MASTER_RECEIVE == g_riic0_mode_flag)
        {
            if (_00_IIC_MASTER_SENDS_ADR_7_R == g_riic0_state)
            {
                RIIC0.ICDRT = (uint8_t)((g_riic0_slave_address << 1U) | 0x0001U);
                g_riic0_state = _08_IIC_MASTER_RECEIVES_START;
            }
            else if (_02_IIC_MASTER_SENDS_ADR_10A_W == g_riic0_state)
            {
                RIIC0.ICDRT = (uint8_t)(((g_riic0_slave_address & 0x0300U) >> 7U) | 0x00F0U);
                g_riic0_state = _04_IIC_MASTER_SENDS_ADR_10B;
            }
            else if (_04_IIC_MASTER_SENDS_ADR_10B == g_riic0_state)
            {
                RIIC0.ICDRT = (uint8_t)(g_riic0_slave_address & 0x00FFU);
                g_riic0_state = _0E_IIC_MASTER_RECEIVES_RESTART;
            }
            else if (_03_IIC_MASTER_SENDS_ADR_10A_R == g_riic0_state)
            {
                RIIC0.ICDRT = (uint8_t)(((g_riic0_slave_address & 0x0300U) >> 7U) | 0x00F1U);
                g_riic0_state = _08_IIC_MASTER_RECEIVES_START;
            }
            else
            {
                 /* Do nothing */
            }
        }
        else
        {
             /* Do nothing */
        }
    }

     

    void r_Config_RIIC0_receive_interrupt(void)
    {
        volatile uint8_t dummy;

        if (_08_IIC_MASTER_RECEIVES_START == g_riic0_state)
        {
            if ((2U == g_riic0_rx_length) || (1U == g_riic0_rx_length))
            {
                RIIC0.ICMR3.BIT.WAIT = 1U;
            }

            if (1U == g_riic0_rx_length)
            {
                RIIC0.ICMR3.BIT.ACKWP = 1U;
                RIIC0.ICMR3.BIT.ACKBT = 1U;
            }

            /* Dummy read to release SCL */
            dummy = RIIC0.ICDRR;

            g_riic0_state = _09_IIC_MASTER_RECEIVES_DATA;

            if (1U == g_riic0_rx_length)
            {
                g_riic0_state = _0A_IIC_MASTER_RECEIVES_STOPPING;
            }
        }
        else if (_09_IIC_MASTER_RECEIVES_DATA == g_riic0_state)
        {
            if (g_riic0_rx_count < g_riic0_rx_length)
            {
                if (g_riic0_rx_count == (g_riic0_rx_length - 3))
                {
                    RIIC0.ICMR3.BIT.WAIT = 1U;

                    *gp_riic0_rx_address = RIIC0.ICDRR;
                    gp_riic0_rx_address++;
                    g_riic0_rx_count++;
                }
                else if (g_riic0_rx_count == (g_riic0_rx_length - 2))
                {
                    RIIC0.ICMR3.BIT.ACKWP = 1U;
                    RIIC0.ICMR3.BIT.ACKBT = 1U;

                    *gp_riic0_rx_address = RIIC0.ICDRR;
                    gp_riic0_rx_address++;
                    g_riic0_rx_count++;

                    g_riic0_state = _0A_IIC_MASTER_RECEIVES_STOPPING;
                }
                else
                {
                    *gp_riic0_rx_address = RIIC0.ICDRR;
                    gp_riic0_rx_address++;
                    g_riic0_rx_count++;
                }
            }
        }
        else if (_0A_IIC_MASTER_RECEIVES_STOPPING == g_riic0_state)
        {
            RIIC0.ICSR2.BIT.STOP = 0U;
            RIIC0.ICCR2.BIT.SP = 1U;

            *gp_riic0_rx_address = RIIC0.ICDRR;
            gp_riic0_rx_address++;
            g_riic0_rx_count++;

            RIIC0.ICMR3.BIT.WAIT = 0U;
            g_riic0_state = _0B_IIC_MASTER_RECEIVES_STOP;
        }
        else
        {
             /* Do nothing */
        }
    }

     
    [追記]

    逆に、ぱっと見た印象より、ずっと長い割り込み禁止となっていると思われる割り込み関数として気になっているのが、BSPモジュールの以下の割り込み関数です。(同様なif文の塊のような構造の割り込み関数は他にもあります。) if文の比較処理の1回あたりが例えば5クロックぐらいしか掛からなかったとしても、if文を20個も30個も並べたら100クロックだの150クロックだの掛かってしまうよね、と思われるのです。

    R_BSP_ATTRIB_STATIC_INTERRUPT void group_bl0_handler_isr (void)
    {
        /* BL0 IS1 */
        if (1 == ICU.GRPBL0.BIT.IS1)
        {
            /* BSP_INT_SRC_BL0_SCI0_ERI0 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI0_ERI0, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS0 */
        if (1 == ICU.GRPBL0.BIT.IS0)
        {
            /* BSP_INT_SRC_BL0_SCI0_TEI0 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI0_TEI0, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS3 */
        if (1 == ICU.GRPBL0.BIT.IS3)
        {
            /* BSP_INT_SRC_BL0_SCI1_ERI1 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI1_ERI1, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS2 */
        if (1 == ICU.GRPBL0.BIT.IS2)
        {
            /* BSP_INT_SRC_BL0_SCI1_TEI1 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI1_TEI1, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS5 */
        if (1 == ICU.GRPBL0.BIT.IS5)
        {
            /* BSP_INT_SRC_BL0_SCI2_ERI2 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI2_ERI2, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS4 */
        if (1 == ICU.GRPBL0.BIT.IS4)
        {
            /* BSP_INT_SRC_BL0_SCI2_TEI2 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI2_TEI2, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS7 */
        if (1 == ICU.GRPBL0.BIT.IS7)
        {
            /* BSP_INT_SRC_BL0_SCI3_ERI3 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI3_ERI3, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS6 */
        if (1 == ICU.GRPBL0.BIT.IS6)
        {
            /* BSP_INT_SRC_BL0_SCI3_TEI3 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI3_TEI3, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS9 */
        if (1 == ICU.GRPBL0.BIT.IS9)
        {
            /* BSP_INT_SRC_BL0_SCI4_ERI4 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI4_ERI4, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS8 */
        if (1 == ICU.GRPBL0.BIT.IS8)
        {
            /* BSP_INT_SRC_BL0_SCI4_TEI4 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI4_TEI4, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS11 */
        if (1 == ICU.GRPBL0.BIT.IS11)
        {
            /* BSP_INT_SRC_BL0_SCI5_ERI5 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI5_ERI5, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS10 */
        if (1 == ICU.GRPBL0.BIT.IS10)
        {
            /* BSP_INT_SRC_BL0_SCI5_TEI5 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI5_TEI5, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS13 */
        if (1 == ICU.GRPBL0.BIT.IS13)
        {
            /* BSP_INT_SRC_BL0_SCI6_ERI6 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI6_ERI6, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS12 */
        if (1 == ICU.GRPBL0.BIT.IS12)
        {
            /* BSP_INT_SRC_BL0_SCI6_TEI6 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI6_TEI6, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS17 */
        if (1 == ICU.GRPBL0.BIT.IS17)
        {
            /* BSP_INT_SRC_BL0_SCI12_ERI12 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI12_ERI12, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS16 */
        if (1 == ICU.GRPBL0.BIT.IS16)
        {
            /* BSP_INT_SRC_BL0_SCI12_TEI12 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI12_TEI12, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS18 */
        if (1 == ICU.GRPBL0.BIT.IS18)
        {
            /* BSP_INT_SRC_BL0_SCI12_SCIX0 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI12_SCIX0, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS19 */
        if (1 == ICU.GRPBL0.BIT.IS19)
        {
            /* BSP_INT_SRC_BL0_SCI12_SCIX1 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI12_SCIX1, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS20 */
        if (1 == ICU.GRPBL0.BIT.IS20)
        {
            /* BSP_INT_SRC_BL0_SCI12_SCIX2 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI12_SCIX2, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS21 */
        if (1 == ICU.GRPBL0.BIT.IS21)
        {
            /* BSP_INT_SRC_BL0_SCI12_SCIX3 */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_SCI12_SCIX3, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS24 */
        if (1 == ICU.GRPBL0.BIT.IS24)
        {
            /* BSP_INT_SRC_BL0_QSPI_QSPSSLI */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_QSPI_QSPSSLI, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS26 */
        if (1 == ICU.GRPBL0.BIT.IS26)
        {
            /* BSP_INT_SRC_BL0_CAC_FERRI */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_CAC_FERRI, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS27 */
        if (1 == ICU.GRPBL0.BIT.IS27)
        {
            /* BSP_INT_SRC_BL0_CAC_MENDI */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_CAC_MENDI, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS28 */
        if (1 == ICU.GRPBL0.BIT.IS28)
        {
            /* BSP_INT_SRC_BL0_CAC_OVFI */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_CAC_OVFI, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS29 */
        if (1 == ICU.GRPBL0.BIT.IS29)
        {
            /* BSP_INT_SRC_BL0_DOC_DOPCI */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_DOC_DOPCI, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS31 */
        if (1 == ICU.GRPBL0.BIT.IS31)
        {
            /* BSP_INT_SRC_BL0_PDC_PCERI */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_PDC_PCERI, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }

        /* BL0 IS30 */
        if (1 == ICU.GRPBL0.BIT.IS30)
        {
            /* BSP_INT_SRC_BL0_PDC_PCFEI */
            R_BSP_InterruptControl(BSP_INT_SRC_BL0_PDC_PCFEI, BSP_INT_CMD_CALL_CALLBACK, FIT_NO_PTR);
        }
    } /* End of function group_bl0_handler_isr() */