こんにちは。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%高速化します。」
こんにちは。NoMaYです。またちょっと脱線しますけれども、RA6T2の先日のアプリケーションノートのサンプルプログラムの最適化オプションが-O0でしたので、ふとした思い付きですけれども、ちょっと好奇心から1つ前の投稿と同じ関数を最適化レベルを最低にしてCC-RX/ICCRX/GNURX/GNUARMでコンパイルしてリストファイルを出力させてみました。興味深いことに、ICCRX以外は(デバッガのウォッチ機能にとって都合が良いので)レジスタ渡しされた引数をスタック上に置き直しているのですが、ICCRXだけは置き直すことをしていませんでしたね。また、ICCRXでは、そのことに加え、実行速度優先最適化をしないことにしたことで、CISC命令セットとしてRXコアはコードサイズがコンパクトになるという性質が優勢に立ったのか、1つ前の投稿の時よりも関数のサイズが小さくなっていましたね。ちょっと珍しいことではないかなぁ、と思われます。(ICCRXのコード生成の指針が実際にそうなのであれば、目から鱗が落ちた、ような思いです。それでもデバッガのウォッチ機能にとって不都合が無いですので。[追記] 置き直すことをせずに済むのはリーフ関数の場合だけかも知れないかな。それ以外の関数においてはデバッガのスタックトレース機能の変数/引数の内容表示機能に支障が出そうだからです。)各コンパイラでの関数のサイズです。
(参) 1つ前の投稿の時の各コンパイラでの関数のサイズです。
試したソースは省略します。(1つ前の投稿と同じです。)CC-RXでのリストファイル
00000000 _rot_2:00000000 7100E0 ADD #0FFFFFFE0H, R000000003 A101 MOV.L R1, 10H[R0]00000005 A08A MOV.L R2, 0CH[R0]00000007 A083 MOV.L R3, 08H[R0]00000009 E5000407 MOV.L 10H[R0], 1CH[R0]0000000D 710104 ADD #04H, R0, R100000010 A181 MOV.L R1, 18H[R0]00000012 EF01 MOV.L R0, R100000014 A109 MOV.L R1, 14H[R0]00000016 FB1E101408 MOV.L #00081410H, R10000001B A90A MOV.L 14H[R0], R20000001D A983 MOV.L 18H[R0], R30000001F E5010701 MOV.L 1CH[R0], 04H[R1]00000023 E11301 MOV.L 04H[R1], [R3]00000026 E012 MOV.L [R1], [R2]00000028 A889 MOV.L 0CH[R0], R10000002A EC1E MOV.L [R1], R140000002C FC8C0E FMUL [R0].L, R140000002F A819 MOV.L 04H[R1], R100000031 FC8D0101 FMUL 04H[R0].L, R100000035 FC831E FSUB R1, R1400000038 A881 MOV.L 08H[R0], R10000003A E31E MOV.L R14, [R1]0000003C A889 MOV.L 0CH[R0], R10000003E EC12 MOV.L [R1], R200000040 FC8D0201 FMUL 04H[R0].L, R200000044 A819 MOV.L 04H[R1], R100000046 FC8C01 FMUL [R0].L, R100000049 FC8B12 FADD R1, R20000004C A881 MOV.L 08H[R0], R10000004E A01A MOV.L R2, 04H[R1]00000050 6708 RTSD #20H00000052
ICCRXでのリストファイル
\ _rot_2: \ 000000 60 80 SUB #0x8,SP \ 000002 FB 4E 10 14 MOV.L #0x81410,R4 \ 08 \ 000007 A0 49 MOV.L R1,0x4[R4] \ 000009 E5 40 01 01 MOV.L 0x4[R4],0x4[SP] \ 00000D E0 40 MOV.L [R4],[SP] \ 00000F A8 0C MOV.L 0x4[SP],R4 \ 000011 FD FF F4 BNOT #0x1f,R4 \ 000014 FC 8D 24 01 FMUL 0x4[R2].L,R4 \ 000018 EC 05 MOV.L [SP],R5 \ 00001A FC 8C 25 FMUL [R2].L,R5 \ 00001D FC 8B 54 FADD R5,R4 \ 000020 E3 34 MOV.L R4,[R3] \ 000022 A8 0C MOV.L 0x4[SP],R4 \ 000024 FC 8C 24 FMUL [R2].L,R4 \ 000027 EC 05 MOV.L [SP],R5 \ 000029 FC 8D 25 01 FMUL 0x4[R2].L,R5 \ 00002D FC 8B 54 FADD R5,R4 \ 000030 A0 3C MOV.L R4,0x4[R3] \ 000032 67 02 RTSD #0x8 000034
GNURXでのリストファイル(RXv3のDPFPUを有効にしているとDPFPUのレジスタを使う変なクセがありますね)
791 _rot_2: 794 0000 7E AA push.l r10 796 0002 75 B0 01 dpushm.d dr0-dr1 798 0005 71 0A EC add #-20, r0, r10 800 0008 EF A0 mov.L r10, r0 801 000a E7 A1 02 mov.L r1, 8[r10] 802 000d E7 A2 03 mov.L r2, 12[r10] 803 0010 E7 A3 04 mov.L r3, 16[r10] 805 0013 71 A4 04 add #4, r10, r4 806 0016 ED A3 02 mov.L 8[r10], r3 807 0019 FB 5E 10 14 08 mov.L #0x81410, r5 808 001e A0 5B mov.L r3, 4[r5] 809 0020 A8 5B mov.L 4[r5], r3 810 0022 E3 A3 mov.L r3, [r10] 811 0024 EC 55 mov.L [r5], r5 812 0026 E3 45 mov.L r5, [r4] 814 0028 EC A5 mov.L [r10], r5 815 002a FD 77 85 0A ftod r5, dr0 816 002e 76 90 0C 02 dneg dr0, dr0 817 0032 76 90 0D 1C dtof dr0, dr1 818 0036 FD 75 85 10 dmov.L drl1, r5 820 003a ED A4 03 mov.L 12[r10], r4 821 003d A8 4C mov.L 4[r4], r4 823 003f FC 8F 54 fmul r5, r4 825 0042 ED A5 03 mov.L 12[r10], r5 826 0045 EC 53 mov.L [r5], r3 828 0047 ED A5 01 mov.L 4[r10], r5 829 004a FC 8F 35 fmul r3, r5 831 004d FC 8B 54 fadd r5, r4 833 0050 ED A5 04 mov.L 16[r10], r5 834 0053 E3 54 mov.L r4, [r5] 836 0055 ED A5 03 mov.L 12[r10], r5 837 0058 EC 54 mov.L [r5], r4 839 005a EC A5 mov.L [r10], r5 840 005c FC 8F 54 fmul r5, r4 842 005f ED A5 03 mov.L 12[r10], r5 843 0062 A8 5B mov.L 4[r5], r3 845 0064 ED A5 01 mov.L 4[r10], r5 846 0067 FC 8F 35 fmul r3, r5 848 006a FC 8B 54 fadd r5, r4 850 006d ED A5 04 mov.L 16[r10], r5 851 0070 A0 5C mov.L r4, 4[r5] 853 0072 03 nop 854 0073 71 00 14 add #20, r0 855 0076 75 B8 01 dpopm.d dr0-dr1 856 0079 7E BA pop r10 857 007b 02 rts 007c
GNUARMでのリストファイル
159 rot_2: 166 0000 80B4 push {r7} 169 0002 8BB0 sub sp, sp, #44 171 0004 00AF add r7, sp, #0 173 0006 87ED030A vstr.32 s0, [r7, #12] 174 000a B860 str r0, [r7, #8] 175 000c 7960 str r1, [r7, #4] 176 000e FB68 ldr r3, [r7, #12] @ float 177 0010 7B62 str r3, [r7, #36] @ float 178 0012 07F11803 add r3, r7, #24 179 0016 3B62 str r3, [r7, #32] 180 0018 07F11403 add r3, r7, #20 181 001c FB61 str r3, [r7, #28] 185 001e 1D4A ldr r2, .L9 187 0020 7B6A ldr r3, [r7, #36] @ float 188 0022 5361 str r3, [r2, #20] @ float 190 0024 1B4B ldr r3, .L9 191 0026 5A69 ldr r2, [r3, #20] @ float 193 0028 3B6A ldr r3, [r7, #32] 194 002a 1A60 str r2, [r3] @ float 196 002c 194B ldr r3, .L9 197 002e 1A69 ldr r2, [r3, #16] @ float 199 0030 FB69 ldr r3, [r7, #28] 200 0032 1A60 str r2, [r3] @ float 202 0034 00BF nop 206 0036 D7ED067A vldr.32 s15, [r7, #24] 207 003a B1EE677A vneg.f32 s14, s15 209 003e BB68 ldr r3, [r7, #8] 210 0040 D3ED017A vldr.32 s15, [r3, #4] 212 0044 27EE277A vmul.f32 s14, s14, s15 214 0048 BB68 ldr r3, [r7, #8] 215 004a D3ED006A vldr.32 s13, [r3] 217 004e D7ED057A vldr.32 s15, [r7, #20] 218 0052 66EEA77A vmul.f32 s15, s13, s15 220 0056 77EE277A vadd.f32 s15, s14, s15 222 005a 7B68 ldr r3, [r7, #4] 223 005c C3ED007A vstr.32 s15, [r3] 225 0060 BB68 ldr r3, [r7, #8] 226 0062 93ED007A vldr.32 s14, [r3] 228 0066 D7ED067A vldr.32 s15, [r7, #24] 229 006a 27EE277A vmul.f32 s14, s14, s15 231 006e BB68 ldr r3, [r7, #8] 232 0070 D3ED016A vldr.32 s13, [r3, #4] 234 0074 D7ED057A vldr.32 s15, [r7, #20] 235 0078 66EEA77A vmul.f32 s15, s13, s15 237 007c 77EE277A vadd.f32 s15, s14, s15 239 0080 7B68 ldr r3, [r7, #4] 240 0082 C3ED017A vstr.32 s15, [r3, #4] 242 0086 00BF nop 243 0088 2C37 adds r7, r7, #44 245 008a BD46 mov sp, r7 248 008c 5DF8047B ldr r7, [sp], #4 251 0090 7047 bx lr 252 .L10: 253 0092 00BF .align 2 254 .L9: 255 0094 00100240 .word 1073876992 ⇒ 0x40021000 0098
こんにちは。NoMaYです。ちょっと話を戻しますが、三角関数演算器での演算時間が14クロックほどだと知ってからは、もう気にしても仕方無いかな、と考えるようになりましたけれども、それより以前、CC-RXに -nouse_div_inst というコンパイルオプションがあったことを知ってから暫くの間は、昔に私がFreeRTOSカーネルのRXv3のDPFPU対応をした時に入れた以下の命令とか、そもそもそれ以前から入っていた以下の命令とか、それらを割り込み応答時間の改善の観点から3~4命令ぐらいに分割しておいた方が良かったのかな、とか考えていました。現状:
DPUSHM.D DR0-DR15DPOPM.D DR0-DR15PUSHM R1-R14POPM R1-R15
暫くの間だけ考えていた分割案:
DPUSHM.D DR12-DR15DPUSHM.D DR8-DR11DPUSHM.D DR4-DR7DPUSHM.D DR0-DR3DPOPM.D DR0-DR3DPOPM.D DR4-DR7DPOPM.D DR8-DR11DPOPM.D DR12-DR15PUSHM R11-R14PUSHM R6-R10PUSHM R1-R5POPM R1-R5POPM R6-R10POPM R11-R15
それと、CC-RXのC言語拡張文法の事情で以下のようにアセンブラソースとCソースに分割している箇所でのSETPSW Iは分岐命令の後では無くて分岐命令の前で実行するようにしておいた方が良かったのかな、とかも考えていました。現状:
.SECTION P,CODE_vSoftwareInterruptEntry: BRA _vSoftwareInterruptISR .RVECTOR 27, _vSoftwareInterruptEntry
void vSoftwareInterruptISR( void ){ prvYieldHandler();}#pragma inline_asm prvYieldHandlerstatic void prvYieldHandler( void ){ #ifndef __CDT_PARSER__/* *INDENT-OFF* */ /* Re-enable interrupts. */ SETPSW I /* Move the data that was automatically pushed onto the interrupt stack when * the interrupt occurred from the interrupt stack to the user stack. * * R15 is saved before it is clobbered. */ PUSH.L R15
暫くの間だけ考えていた変更案:
.SECTION P,CODE_vSoftwareInterruptEntry: ; Re-enable interrupts. SETPSW I BRA _vSoftwareInterruptISR .RVECTOR 27, _vSoftwareInterruptEntry
void vSoftwareInterruptISR( void ){ prvYieldHandler();}#pragma inline_asm prvYieldHandlerstatic void prvYieldHandler( void ){ #ifndef __CDT_PARSER__/* *INDENT-OFF* */ /* Move the data that was automatically pushed onto the interrupt stack when * the interrupt occurred from the interrupt stack to the user stack. * * R15 is saved before it is clobbered. */ PUSH.L R15
こんにちは。NoMaYです。そういえば、RH850(というか元々はV850)に、割り込み応答時間の改善の為の、ちょっと風変わりな命令動作があったことを思い出して、RH850のドキュメントをちょっと見てみました。(1) 複数レジスタのPUSH中に割り込み要求があったらPUSH動作を途中で中止して割り込みへ飛ぶ(2) 複数レジスタのPOP中に割り込み要求があったらPOP動作を途中で中止して割り込みへ飛ぶ(3) 除算命令の実行中に割り込み要求があったら除算動作を途中で中止して割り込みへ飛ぶ※ PUSH命令、POP命令、除算命令、などは、もちろん命令のバリエーションが幾つかあります。以下の画面コピーは、そのうちの幾つかの例です。RH850G3KH ユーザーズマニュアル ソフトウェア編R01US0165JJ0120 Rev.1.20 Pages 367 2016.12.22www.renesas.com/jp/ja/document/mas/rh850g3kh-users-manual-software [追記]浮動小数点演算命令(単精度)にも以下の画面コピーの通り命令実行時間が長いものがあるのですけれども、演算動作を途中で中止して割り込みへ飛ぶ、ということはしないようです。(少なくともドキュメントには記載が無かったです。)
こんにちは。NoMaYです。以下の画面コピーの警告で気付いたのですけれども、CGコンポーネントにコンポーネント内で違う割り込み優先順位を指定しなければならないものがあったのですね。こういうコンポーネントは気安く多重割り込みを許可してしまうのは危なそうです、、、(他方、同じ内蔵周辺機能でも、以下の画面コピーのとおり、FITモジュールでは同じ割り込み優先順位を指定しても構わないようでした、、、実装の詳細に依存することだと思いますので、どちらかがおかしいのではないか?、とまでは何とも言えないのですけれども、でも直感として何だか怪しい気はしているのですけれども、、、)以下、e2 studioのRXスマートコンフィグレータの画面コピーです。CGFIT
こんにちは。NoMaYです。FITもCGも多重割り込み許可にはしていないのに、RXスマートコンフィグレータで割り込み優先順位を指定させることに何の意味があるかというと、たぶん以下の4つではないだろうか、と思われます。ただ、以下の(1)を本当にしても良いのかと問われると、FITモジュールやCGコンポーネントの個々の実装次第だろう、と思われます、といった逃げた返事を私はするだろう、と思います、、、(1) コールバック関数内でユーザが多重割り込み許可にした場合のため(2) まさに同時に2つ以上の割り込みが発生した時のため(3) 他の割り込みの処理中にトータルで2つ以上の割り込みが発生していて、他の割り込みが終了して次の割り込みがまさに受け付けられる時のため(4) FreeRTOSやNORTiなどカーネル内の割り込み禁止区間でも高優先度割り込みを許可するようになっているRTOSを使う場合のため(4') ちなみに、FreeRTOSでも、RXコア向けやCortexコア向けには該当機能があるが、(少なくとも数年前は)78K/RL78/V850コア向けには無いです(4'') それから、AzureRTOSでは、RXコア向けには該当機能が無いが、Cortexコア向けには該当機能があるようです
こんにちは。NoMaYです。FITの割り込み処理で割り込み関数先頭での多重割り込み許可を設定する手はないかと小細工を考えていて、ひとつ思い浮かんだのですけれども、以前の投稿に書いていた、FITのBSPモジュールの3種類コンパイラ対応の為のマクロ定義部に手を入れるやり方なのですけれども、マクロ定義部を以下のようにしてみるというのがあります。各コンパイラが生成した割り込み関数のコード(アキュムレータの退避/復帰を行うオプションを指定しています)は以下のリストファイルのようになりました。(なお、昨日の夜に気付いたことに関しては、どうしたものかなぁ、とは思っているところです。)思い浮かんだ小細工:r_bsp/mcu/all/r_rx_compiler.h (もちろん無条件に置き換えるのではなく必要に応じて切り替えるのですけれども)
#if defined(__CCRX__)#define R_BSP_PRAGMA_STATIC_INTERRUPT(function_name, vector) static void function_name(void);\ R_BSP_PRAGMA(interrupt _##function_name(vect=vector, enable))\ static void _##function_name(void);\ static void _##function_name(void)\ {\ if(BSP_CFG_FIT_IPL_MAX > (((R_BSP_GET_PSW()) >> 24) & 0xF))\ {\ R_BSP_SET_IPL(BSP_CFG_FIT_IPL_MAX);\ }\ function_name();\ }#define R_BSP_ATTRIB_STATIC_INTERRUPT static
#elif defined(__GNUC__)#define R_BSP_PRAGMA_STATIC_INTERRUPT(function_name, vector) static void function_name(void);\ static void _##function_name(void) __attribute__((interrupt, section(".text." #function_name), used));\ static void __##function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector), naked, section(".text." #function_name), used));\ static void __##function_name(void)\ {\ __asm__ volatile ("SETPSW I");\ __asm__ volatile ("BRA.W __" #function_name);\ }\ static void _##function_name(void)\ {\ if(BSP_CFG_FIT_IPL_MAX > (((R_BSP_GET_PSW()) >> 24) & 0xF))\ {\ R_BSP_SET_IPL(BSP_CFG_FIT_IPL_MAX);\ }\ function_name();\ }#define R_BSP_ATTRIB_STATIC_INTERRUPT static
#elif defined(__ICCRX__)#define R_BSP_PRAGMA_STATIC_INTERRUPT(function_name, vect) static void function_name(void);\ R_BSP_PRAGMA(vector=vect)\ static __interrupt __nested void _##function_name(void);\ static __interrupt __nested void _##function_name(void)\ {\ if(BSP_CFG_FIT_IPL_MAX > (((R_BSP_GET_PSW()) >> 24) & 0xF))\ {\ R_BSP_SET_IPL(BSP_CFG_FIT_IPL_MAX);\ }\ function_name();\ }#define R_BSP_ATTRIB_STATIC_INTERRUPT static#endif
r_config/r_bsp_config.h (既存のマクロ定義を以下の値にしています(この値のみに限られているわけではありません))
/* For some BSP functions, it is necessary to ensure that, while these functions are executing, interrupts from other FIT modules do not occur. By controlling the IPL, these functions disable interrupts that are at or below the specified interrupt priority level. This macro sets the IPL. Range is 0x0 - 0xF. Please set this macro more than IPR for other FIT module interrupts. The default value is 0xF (maximum value). Don't change if there is no special processing with higher priority than all fit modules.*/#define BSP_CFG_FIT_IPL_MAX (0xB)
ソース例:src\smc_gen\r_riic_rx\src\targets\rx66n/r_iic_rx66n.cから抜粋したもの
/******************************************************************************* * Function Name: riic1_txi_isr * Description : Interrupt TXI handler for channel 1. * Types of interrupt requests transmission data empty. * Arguments : None * Return Value : None*******************************************************************************/R_BSP_PRAGMA_STATIC_INTERRUPT(riic1_txi_isr, VECT(RIIC1,TXI1))R_BSP_ATTRIB_STATIC_INTERRUPT void riic1_txi_isr (void){ riic1_txi_sub();} /* End of function riic1_txi_isr() */
リストファイル:CC-RX : コンパイルオプションに -save_acc (割り込み関数でのアキュムレータの退避/復帰を行う)を指定
000002E4 __$_riic1_txi_isr: .RVECTOR 51,__$_riic1_txi_isr000002E4 7FA8 SETPSW I ⇒ 多重割り込み許可000002E6 6EEF PUSHM R14-R15000002E8 6E45 PUSHM R4-R5000002EA 7EA3 PUSH.L R3000002EC FD1FB3 MVFACGU #00H, A1, R3000002EF 7EA2 PUSH.L R2000002F1 FD1F82 MVFACHI #00H, A1, R2000002F4 7EA1 PUSH.L R1000002F6 FD1F91 MVFACLO #00H, A1, R1000002F9 7EA3 PUSH.L R3000002FB FD1F33 MVFACGU #00H, A0, R3000002FE 7EA2 PUSH.L R200000300 FD1F02 MVFACHI #00H, A0, R200000303 7EA1 PUSH.L R100000305 FD1F11 MVFACLO #00H, A0, R100000308 6E13 PUSHM R1-R30000030A FD6A01 MVFC PSW, R10000030D FC5A110810 BFMOVZ #18H, #00H, #04H, R1, R100000312 61A1 CMP #0AH, R100000314 24rr BGTU L6400000316 L63: ; if_then_bb00000316 75700B MVTIPL #0BH00000319 L64: ; if_break_bb00000319 39rrrr W BSR __$riic1_txi_isr0000031C 7EB1 POP R10000031E 7EB2 POP R200000320 7EB3 POP R300000322 FD1711 MVTACLO R1, A000000325 FD1702 MVTACHI R2, A000000328 7EB1 POP R10000032A FD1733 MVTACGU R3, A00000032D 7EB2 POP R20000032F 7EB3 POP R300000331 FD1791 MVTACLO R1, A100000334 FD1782 MVTACHI R2, A100000337 FD17B3 MVTACGU R3, A10000033A 6F15 POPM R1-R50000033C 6FEF POPM R14-R150000033E 7F95 RTE
ICCRX : コンパイルオプションに --save_acc (割り込み関数でアキュムレータの退避/復帰を行う)を指定(しかしながらバグによりアキュムレータの退避/復帰を行うコードが生成されないみたいですね)
\ __riic1_txi_isr: \ ___interrupt_51: \ 000000 7F A8 SETPSW I ⇒ 多重割り込み許可 \ 000002 6E EF PUSHM R14-R15 \ 000004 6E 15 PUSHM R1-R5 \ 000006 FD 6A 01 MVFC PSW,R1 \ 000009 FC 5A 11 08 BFMOVZ #0x18,#0x0,#0x4,R1,R1 \ 10 \ 00000E 61 B1 CMP #0xb,R1 \ 000010 22 05 BGEU ??_riic1_txi_isr_0 \ 000012 75 70 0B MVTIPL #0xb \ ??_riic1_txi_isr_0: \ 000015 05 ..'.... BSR.A _riic1_txi_sub \ 000019 6F 15 POPM R1-R5 \ 00001B 6F EF POPM R14-R15 \ 00001D 7F 95 RTE
GNURX : コンパイルオプションに -msave-acc-in-interrupts (割り込み関数でアキュムレータの退避/復帰を行う)を指定
936 __riic1_txi_isr: 939 ; Note: Interrupt Handler 940 0000 6E EF pushm r14-r15 942 0002 6E 15 pushm r1-r5 944 0004 FD 1F 11 mvfaclo #0, A0, r1 945 0007 FD 1F 02 mvfachi r2 946 000a 7E A1 push.l r1 947 000c 7E A2 push.l r2 948 000e FD 1F 31 mvfacgu #0, A0, r1 949 0011 FD 1F 92 mvfaclo #0, A1, r2 950 0014 7E A1 push.l r1 951 0016 7E A2 push.l r2 952 0018 FD 1F 81 mvfachi #0, A1, r1 953 001b FD 1F B2 mvfacgu #0, A1, r2 954 001e 7E A1 push.l r1 955 0020 7E A2 push.l r2 957 0022 FD 6A 05 mvfc psw, r5 958 0025 69 85 shlr #24, r5 959 0027 64 F5 and #15, r5 960 0029 61 A5 cmp #10, r5 961 002b 24 05 bgtu .L65 963 002d 75 70 0B mvtipl #11 964 .balign 8,3,3 965 .L65: 972 0030 05 00 00 00 bsr _riic1_txi_sub 977 0034 7E B2 pop r2 978 0036 7E B1 pop r1 979 0038 FD 17 81 mvtachi r1, A1 980 003b FD 17 B2 mvtacgu r2, A1 981 003e 7E B2 pop r2 982 0040 7E B1 pop r1 983 0042 FD 17 31 mvtacgu r1, A0 984 0045 FD 17 92 mvtaclo r2, A1 985 0048 7E B2 pop r2 986 004a 7E B1 pop r1 987 004c FD 17 11 mvtaclo r1 988 004f FD 17 02 mvtachi r2 989 0052 6F 15 popm r1-r5 990 0054 6F EF popm r14-r15 991 0056 7F 95 rte 995 ___riic1_txi_isr: 998 .global $tableentry$51$.rvectors 999 $tableentry$51$.rvectors: 1000 ; Note: Interrupt Handler 1001 ; Note: Naked Function 1004 0058 7F A8 SETPSW I ⇒ 多重割り込み許可 1008 005a 38 A6 FF BRA.W __riic1_txi_isr
割り込みハンドラには最低限の処理しか入れないように作っている限り多重割り込みが必要な場面はほとんどないはず(受信割り込みとか自分の努力だけではどうにもならない場合はありますが)、というのが昔の非力なマイコンを使っていた世代には当たり前の認識だったのですが今は違うみたいですね。
ほや さん、こんにちは。NoMaYです。リプライありがとうございます。ほやさんも以下のhirakuni45さんのリプライと同じ勘違いをされていると思うのです、、、(たぶん、ほやさんもhirakuni45さんも、脊髄反射的に`多重割り込み`というキーワードに反応されたのかなぁ、と思うのですけれども、、、)hirakuni45さんのリプライcommunity-ja.renesas.com/cafe_rene/forums-groups/mcu-mpu/rx/f/forum5/9572/rxv3-register-bank-save-function-usage/46854#46854hirakuni45さんのリプライへの私のリプライcommunity-ja.renesas.com/cafe_rene/forums-groups/mcu-mpu/rx/f/forum5/9572/rxv3-register-bank-save-function-usage/46861#46861今のところの本スレッドの話の流れは、以下のようなものなのです、、、メイン:● RXv3コアのレジスタ一括退避機能を使わないといけないほど割り込み応答性にシビアなプログラムで最大限の効果を発揮させるには?(1) この機能を使う割り込み処理に着目するだけでは駄目で、そもそも他の割り込み処理が全て多重割り込み許可になってないと効果が無いのでは?(2) しかし、そもそもRXマイコン向けソフトウェア開発フレームワーク(RXスマートコンフィグレータ)で現状は(将来も?)多重割り込みを効率的に使えない(3) そんな状況だから(そんな状況だからこそ)、セールスポイントの1つであるレジスタ一括退避機能の使い方が今ひとつピンと来ません(4) どう使うのが良いのかなぁ?、、、(恐らく小細工を考えないといけないのだろうなぁ?、、、)あと、(うすうす感付かれている人もおられると思いますけれども、) もうひとつの話の流れもあります、、、サブ:● RXv3コアのレジスタ一括退避機能って大して役に立たないのかなぁ?(シリコンというかトランジスタというかの無駄遣いなのかなぁ?)(1) RXマイコン向けソフトウェア開発フレームワーク(RXスマートコンフィグレータ)で現状は(将来も?)多重割り込みを効率的に使えないのだから(2) もしかしたら、CPUコアを開発している人達は、自分達の会社のソフトウェア開発フレームワークが多重割り込みを効率的に使えないものだった、とは思ってなかった?(3) その他にも、そもそもRXマイコンの命令の中に命令実行クロック数が有意に長いものが幾つか存在していて割り込み応答性の悪化(ゆらぎ)要因になってますよね(4) あとそれから、CPUコアを開発している人達は、Cコンパイラが割り込み応答性の向上の為に既にかなり工夫していた、ことに気付いてなかった?と書いたものの、実は、そこまで割り込み応答性にシビアなプログラムの開発をしたことがありませんけれども、、、[追記]> 今は違うみたいですね。思うに、「今は」ということでなくて、ほやさんも私同様に「そこまで割り込み応答性にシビアなプログラムの開発をしたことが無かった」だけではないかなぁ、とも思います。RXマイコンには昔から高速割り込みなる機能がありますが、この機能の場合も、「この機能を使う割り込み処理に着目するだけでは駄目で、そもそも他の割り込み処理が全て多重割り込み許可になってないと効果が無いのでは?」と思われるのです。そして、この機能の起源は、RXマイコンよりも昔のM16CやM32CやR32Cの高速割り込み機能ですかね。以下、M16CやM32CやR32Cのアプリケーションノートの画面コピーです。M16C/80、M16C/64Aグループ M16C/80とM16C/64Aとの相違点www.renesas.com/us/ja/document/apn/917626?language=ja#page=24M32C/87B、R32C/116グループ M32C/87BとR32C/116との相違点(144pin版)www.renesas.com/us/ja/document/apn/815361?language=ja#page=8
> 「そこまで割り込み応答性にシビアなプログラムの開発をしたことが無かった」だけではないかなぁ、それは本来の使い方なので問題ないのですが、「どうすれば多重割り込みを有効にできますか」と聞いて来られる方の中で例えば「受信割り込みの中で応答送信待ちをした結果オーバーランエラーを食らった」みたいな、根本的な設計に問題があるのに多重割り込みで逃げを打とうとするケースを見かけることが以前より多い気がするのでちょっとグチってみただけです。気にしないでください。
ほや さん、こんにちは。NoMaYです。リプライありがとうございます。ナルホド! RXスマートコンフィグレータで、FITにしろCGにしろ、ユーザさんが多重割り込みを自前で使用している事例として、割り込み応答性にシビアなプログラムでは無いものでは、そういうことは可能性が高そうですね。hirakuni45さんが仰っていた話もそういう事例についてだったのかな、と今になってようやく気付いたのでした。コールバック関数が呼ばれるのは、スーパーループの通常のmainのコンテキストでは無くて、割り込みコンテキストである、ということがうまく認識出来ていなかった結末として多重割り込みに手を出す、という感じなのでしょうかね。どうなんでしょう。古くからのマイコンユーザとしては、コールバック関数が割り込みコンテキストであることは当然という感覚ですけれども、インターネット時代の、若くして汎用OS上での色々なフレームワークに触れることも少なく無い、今の若いユーザさんには、何でコールバック関数でそんなことも出来ないのさ?という感覚だったりして、、、ふと思い出したのですけれども、私はといえば、若かりし頃、ごちゃごちゃスタックを操作して、コールバック関数をスーパーループのmainのコンテキストで呼び出す小技を考えようとしたことがあったような気がします。(記憶の捏造では無くて、そんなことを考えようとしたことがあったような記憶が確かにある、といったところですけれども、、、)[追記]FreeRTOSでも、FreeRTOS上に構築された何かのフレームワークにおいて、何かのコールバック関数が、通常のタスクのコンテキストでは無くて、タイマタスクという最高優先度のタスクのコンテキストで呼ばれていたことから、その中で他タスクからの反応を待つも、いつまで経っても反応が無い、という事例があるかも知れないとか思い浮かびました。