自作関数のリエントラント性について

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では上記のような関数はリエントラントにはならないのでしょうか?

Parents
  • mmcopy関数の呼び出し元を全てご確認してはどうでしょうか?
    ソース入力ミスで*d5とか*s5の引数部分に呼出し元のauto変数に&つけて、スタックアドレスを渡してスタック領域を破損させて暴走とか?
  • fujita nozomuさん

    コメントありがとうございます。

    > _stkinit を有効化してスタック領域を初期化するようにした後、領域外への書き込みがあるかを確認することは有効です。

    ありがとうございます。試してみます。

    > 副業不可なので有償でのそれはお受けできません。

    承知致しました。

    のーしゃんさん

    コメントありがとうございます。

    > mmcopy関数の呼び出し元を全てご確認してはどうでしょうか?

    ご指摘について、確かにmmcopyの呼び出し元で引数の扱い方がかなり怪しい部分があります。
    そこを重点的に調べてみます。
  • のーしゃんさん

    ご指摘頂いたauto変数に&をつけているところがありました。

    void Old_MX( _UBYTE pg )
    {
    volatile _UBYTE lp,cf,txsz;
    volatile _UBYTE c1;
    volatile _UBYTE pp;
    volatile _UBYTE bytp,bitp,bitd;
    volatile _UBYTE Dswrty;
    volatile _UBYTE tw[80];
    volatile struct TNKDATA tf; // 変化比較用バッファ
    ~中略~
    mmcopy( (_UBYTE *)&tw[5],(_UBYTE *)"thr=000 -- ",11);


    アセンブルリストを確認したところ、

    00002F1F 8596 .BB@LABEL@23_89: ; if_break_bb349
    00002F1F 8597 .LINE "C:/Users/Ando/Documents/VCD-30/Soft/20190910A_VCD-30G14/VCD-30G14/r_main.c", 2659
    00002F1F 340B00 8598 movw de, #0x000B
    00002F22 320000 8599 movw bc, #SMRLW(.STR@11034)
    00002F25 AEF8 8600 movw ax, sp
    00002F27 041500 8601 addw ax, #0x0015
    00002F2A FC000000 8602 call !!_mmcopy

    となっておりました。axは*d5、bcは*s5、deはnとなっております。アセンブラの読解力が乏しいので正しく理解できておりませんが、このようなコードがスタックアドレスを破壊しているのでしょうか?
    しかしtwは配列のため、&をつけてもも間違いではないと理解しております。

    勉強不足で申し訳ありませんが、上記が問題なのでしょうか?
  • チョコです。

    アセンブラでの動作についてコメントさせてもらいます。

    2F25 AEF8 8600 movw ax, sp

    2F27 041500 8601 addw ax, #0x0015

    でaxはスタック領域のスタックトップから21(0x15)バイト目を指しています。

    axがディスティネーション側(転送先)なら,もろにスタック領域を破壊します。

    (axが転送元で,スタックに積まれているデータを転送するならわからないではないですが。)

     

    以上

Reply
  • チョコです。

    アセンブラでの動作についてコメントさせてもらいます。

    2F25 AEF8 8600 movw ax, sp

    2F27 041500 8601 addw ax, #0x0015

    でaxはスタック領域のスタックトップから21(0x15)バイト目を指しています。

    axがディスティネーション側(転送先)なら,もろにスタック領域を破壊します。

    (axが転送元で,スタックに積まれているデータを転送するならわからないではないですが。)

     

    以上

Children
  • > axがディスティネーション側(転送先)なら,もろにスタック領域を破壊します。
    > (axが転送元で,スタックに積まれているデータを転送するならわからないではないですが。)

    AX は転送先ですが、スタックフレーム上に設けられたローカル変数 _UBYTE tw[80] の 5バイト目のアドレスで問題ない筈です。

    > mmcopy( (_UBYTE *)&tw[5],(_UBYTE *)"thr=000 -- ",11);

    は tw[] に出力したい文字列を作成する処理の一部分なのだと思いますが、「何バイト目から何バイト "~" をコピーして、その後ろに "…" をコピーして、最後に '\0' を書いて、」等やってるとミスも生じ易くなるので、素直に sprintf() とか使われた方が良いでしょう。コードも簡潔になるので保守性も向上します。