RL78/G14(R5F104LLAFB#V0)で、C言語の自作関数を使用しておりますが、この関数をメインルーチンと割り込みルーチンの両方で使用しております。
関数内ではグローバル変数を使用しておらず、リエントラントになっていると考えております。
void mmcopy( _UBYTE *d5, _UBYTE *s5, _UWORD n){ _UWORD i; for(i=0;i<n;i++) *(d5+i) = *(s5+i);}
この関数がメインと割り込みで競合した場合、カウンタiはスタック退避されて戻れると認識しておりますが、E1エミュレータを接続し、連続運転していると
RESF=10hのリセットが発生します。OCDトレースを見るとこの関数で無限ループに陥っているように見えます。
RL78では上記のような関数はリエントラントにはならないのでしょうか?
fujita nozomuさん
コメントありがとうございます。
リンク先参照させて頂きます。
先般のトレースで起きていたRESFは02H(IAWRF)です。
WDTRFが起きていた時のトレースは
_mmcopy;0 N_LIB.C#69 for(i=0;i<n;i++)0 00x9ba6 +39 BC $_mmcopy+0xf1 N_LIB.C#69 for(i=0;i<n;i++)1 00x9ba6 +39 BC $_mmcopy+0xf...223 N_LIB.C#69 for(i=0;i<n;i++)223 00x9ba6 +39 BC $_mmcopy+0xf224 N_LIB.C#69 for(i=0;i<n;i++)224 00x9ba6 +39 BC $_mmcopy+0xf225 0x00000 CMP0 X
256 cstart.asm#62 MOVW SP,#LOWW(__STACK_ADDR_START)256 0x000d8 +0 MOVW SP,#0FE20H
でした。
但し、OCDトレースが採取できたのはIAWRF、WDTRF各1回のみです。
それ以前はG13(R5F100LGDFB#30)を使用していたため、トレースが採取出来ておりません。
リンク先の
>・内蔵RAMのトレースRAM領域をプログラム(カーネル側&アプリケーション側)で使用してしまっていないか?(MAPファイルを見れば分かるかと思います。)
ですが、mapファイル上はそのようなことにはなっていないようです。
*** Mapping List ***
SECTION START END SIZE ALIGN.vect 00000000 0000007f 80 0.constf 00000080 00000080 0 2.data 00000080 00000080 0 2.sdata 00000080 00000080 0 2.option_byte 000000c0 000000c3 4 1.security_id 000000c4 000000cd a 1.monitor1 000000ce 000000d7 a 1.text 000000d8 0000031f 248 1.RLIB 00000320 00000462 143 1.SLIB 00000463 00000469 7 1.const 00003000 0000318e 18f 2.textf 0000318f 0000ad70 7be2 1.monitor2 0007fe00 0007ffff 200 1.dataR 000f3f00 000f3f00 0 2.bss 000f4700 000f6032 1933 2.sbss 000ffe20 000ffe20 0 2.sdataR 000ffe20 000ffe20 0 2
また、スタック領域ですが、
__RAM_ADDR_START 000f3f00 __s.bss 000f4700 __e.bss 000f6033 __STACK_ADDR_END 000f6034 __s.sbss 000ffe20 __e.sbss 000ffe20 __s.sdataR 000ffe20 __e.sdataR 000ffe20 __STACK_ADDR_START 000ffe20 0001(000000da:.text) __RAM_ADDR_END 000ffee0
となっております。
Call Walkerでスタック使用量を見積もると、
VCD-30G14.cal(272)
となっております。動的な使用量は考慮されておりませんが、十分なスタック領域があると考えております。
問題となっている事象について整理させて頂きますが、
①現場で発生しているのはRESF=02H(IAWRF)のみです。平均すると7回/月の頻度で起きておりますが、最長で28日間発生しなかったこともあります。現場ではG13(R5F100LGDFB#30)を使用しております。
②社内検証環境で発生したのはRESF=02H、RESF=10H(WDTRF)で、RESF=10Hはこれまでに2回発生しており、E1エミュレータ接続時のみに確認されております。RESF=02Hは確認している限りでは6回程度発生しております。OCDトレースを採取することで原因究明の一助となると考え、3/12からG14(R5F104LLAFB#V0)を搭載し、検証を継続したところ、3/13にRESF=10Hが発生しました。その時のトレース結果が上記のものです。その後3/21にRESF=02Hが発生し、それが昨日投稿したトレースです。日付については以前申し上げたのと若干異なっておりますが、先日は勘違でログファイルの開始日を記載してしまいました。以降現時点までリセットは発生しておりません。
③静電気試験で10kVの静電気をかけるとRESF=80H、RESF=04H、RESF=02Hが発生することがあります。毎回発生するわけではなく、何か特定のタイミングで発生するようです。
現状はリセットが発生しても即復旧してシステム上は影響が出ないよう処置を施しております。稼働(2019/5)から約1年経過しており、今のところ致命的な問題は発生しておりませんが、リセットが発生するタイミングによっては重大な被害を及ぼす可能性があります。
最初の投稿の主旨とは変わってしまっておりますが、最も解決したい問題は①の現場で発生しているIAWRFです。もちろんWDTRFが何故発生したのかも疑問ではありますが、これまで一度も現場では発生しておらず、E1エミュレータを接続したことによる副次的な問題と考えます。
これ以上の原因究明のためにはIECUBEを使用するしかないのかと考えております。
有償でコンサルして頂くことは可能でしょうか?
可能であればお願い致します。
投稿した後で気づいたのですが、3/13のRESF=10Hの時にメモリの内容を確認した際に、スタックエンドアドレス付近までデータが埋まっておりました。
一方mapファイルから、スタックエンド付近は
0010 r_cg_serial SECTION=.textf
~中略~
SECTION=.bss _gp_uart0_tx_address 000f601e 0010(0000a819:.textf)
~中略~_g_uart1_rx_count 000f602e 0010(0000a946:.textf) 0011(0000020e:.text) 0011(0000021d:.text) 0011(00000223:.text) _g_uart1_rx_length 000f6030 0010(0000a94b:.textf) 0011(0000020b:.text) 0011(00000220:.text)
スタックオーバーフローが発生しているのでしょうか?
Hosさん、こんにちは。
スタック見積ツールCall Walkerでの使用量は(272)となっております。一方、mapファイルからは40,428Byteのスタック領域が確保されております。Call Walkerでは静的な最大量しか考慮されていないので、多重割り込みなどによる動的な最大量は考慮されておりませんが、約150倍の領域が確保されているので十分と考えました。
しかし、RESF=10Hの発生時に採取したスタック領域の内容を見ると、UART経由で出力しているデバッグ用モニターポートの出力情報が判読できる形で残っております。
プログラム上の何らかのバグでスタック領域がポップされないまま浸食され続けているのではないかと考えられます。
何とか少しヒントが得られたような気がします。
コメント頂いた皆様ありがとうございました。