チョコさんが以前に指摘されていたRL78コード生成機能によるCSI連続送信の終了の割り込みコードの問題を調べています

チョコさん、こんにちは。NoMaYです。

すみません、掲題の件、下記のスレッドでの話題ですが、コード生成されたソースの以下のコードのことでしょうか?

r_cg_serial_user.c

static void __near r_csi00_interrupt(void)
{
    if (g_csi00_tx_count > 0U)
    {
        SIO00 = *gp_csi00_tx_address;
        gp_csi00_tx_address++;
        g_csi00_tx_count--;
    }
    else
    {
        if ((SSR00 & _0040_SAU_UNDER_EXECUTE) == 0U)
        {
            r_csi00_callback_sendend();    /* complete send */
        }
        else
        {
            SMR00 &= ~_0001_SAU_BUFFER_EMPTY;
        }
    }
}

RL78/G14のEEPROMのI2C通信について
japan.renesasrulz.com/cafe_rene/f/002-2095199602/5962/rl78-g14-eeprom-i2c/33068#33068

チョコです。
鈴木さん,MAX7219をCSIで制御してLED表示を行っていて,問題を見つけました。
CSIの連続送信で最後のデータを書き込んだ後で,割り込みタイミングを書き換えてますが,転送速度とプログラムの実行速度の関係で,最後の割り込みが発生しない可能性があります。


RL78/G13 CSIのマスタ連続送受信でオーバーランエラーが発生する
japan.renesasrulz.com/cafe_rene/f/002-2095199602/5972/rl78-g13-csi/33137#33137

チョコです。
この現象については,「RL78/G14のEEPROMのI2C通信について」で少し触れていますが,次のような動作になっていると考えられます。
①最後のデータを書き込むための割り込みが発生します。
②CSIは最後のデータを送信します。
③CPUは割り込みを受け付けると,最後のデータの送信中かチェックして,最後のデータなら割り込みタイミングを転送完了に書き換えます。
ところが,③で割り込みタイミングを書き換える前に送信が完了してしまっていると,書き換えた時点では,送信完了割り込みの発生タイミングを終了しているので,期待した最後の割り込みが発生しません。
そのため,通信処理を終えることができなくなってしまいます。


なお、以下のCS+ V8.03の画面コピーは先程のソースを生成させた時のコード生成機能の設定内容です。



 

Parents
  • チョコさん、こんにちは。NoMaYです。

    リプライ有難う御座いました。やはり、この部分なのですね。(実は、UARTでも同じコードが使われていて、何かあやうい感じ、がしていました。UART+DTCのプログラムを作っていた時に、自分なりに修正案も考えて(現象未確認ながら)修正案を実装したりしていました。) それで、RL78/G14 Fast Prototyping Boardの単体とRenesas RL78 Simulatorの両方で現象を再現させるプログラムが出来ましたので、添付しました。(当方特有の事情で、コード生成はCS+ V8.03、シミュレータはCS+ V8.01、ビルドはCC-RL V1.02、を使用しています。)

    プロジェクトのファイル一式:
    issue_20200228.zip

    現象を再現させるにあたって、CPU動作周波数を24MHz、CSIボーレートを4Mbps、タイミングを合わせる為に割り込みルーチンにNOPを複数挿入、といったことをしています。挿入したNOPに関しては、「他の割り込みやDI/EIにより、くだんの割り込みの受付が遅延して、まさに危険な区間で送信終了した(シフトレジスタから送出終了した)」という状況のアナロジーとして行いました。

    その結果、以下の赤文字のコードにした場合に、期待した割り込みが発生しなくなりました。(本来は LED1==ON にならないといけないのに、LED1==OFF のままになってしまいました。)

    r_cg_serial_user.c

    static void __near r_csi00_interrupt(void)
    {
        if (g_csi00_tx_count > 0U)
        {
            SIO00 = *gp_csi00_tx_address;
            gp_csi00_tx_address++;
            g_csi00_tx_count--;
        }
        else
        {
    #if 0
            /* LED0 == ON,  LED1 == ON     --> OK */
            /* nothing */
    #elif 1
            /* LED0 == ON,  LED1 == OFF!!! --> NG!!! */
            nop(); 8回繰り返し nop();
    #elif 0
            /* LED0 == OFF, LED1 == ON     --> OK */
            nop(); 8回繰り返し nop();
            nop(); 8回繰り返し nop();
            nop(); 8回繰り返し nop();
    #endif

            if ((SSR00 & _0040_SAU_UNDER_EXECUTE) == 0U)
            {
                r_csi00_callback_sendend();    /* complete send */
                LED1 = LED_ON;
            }
            else
            {
                SMR00 &= ~_0001_SAU_BUFFER_EMPTY;
                LED0 = LED_ON;
            }
        }
    }

    以下、CS+ V8.03で今回のコードを生成させた時のコード生成機能の設定内容の画面コピーです。





    以下、CS+ V8.01のRenesas RL78 Simulatorで実行させた時の画面コピーです。

    送信終了待ちループを抜けた箇所にブレークポイントを設定したものの送信終了しても何時までも経ってもブレークしない


    何時までも経ってもブレークしないのでマニュアルブレークすると送信終了待ちループの中でブレークする(抜けていない)


    なお、Renesas RL78 Simulatorのシリアルウィンドウ上でCSI通信の送受信をする方法は以下のスレッドの通りです。

    CSIのシミュレーション方法
    japan.renesasrulz.com/cafe_rene/f/forum18/5834/csi
     

Reply
  • チョコさん、こんにちは。NoMaYです。

    リプライ有難う御座いました。やはり、この部分なのですね。(実は、UARTでも同じコードが使われていて、何かあやうい感じ、がしていました。UART+DTCのプログラムを作っていた時に、自分なりに修正案も考えて(現象未確認ながら)修正案を実装したりしていました。) それで、RL78/G14 Fast Prototyping Boardの単体とRenesas RL78 Simulatorの両方で現象を再現させるプログラムが出来ましたので、添付しました。(当方特有の事情で、コード生成はCS+ V8.03、シミュレータはCS+ V8.01、ビルドはCC-RL V1.02、を使用しています。)

    プロジェクトのファイル一式:
    issue_20200228.zip

    現象を再現させるにあたって、CPU動作周波数を24MHz、CSIボーレートを4Mbps、タイミングを合わせる為に割り込みルーチンにNOPを複数挿入、といったことをしています。挿入したNOPに関しては、「他の割り込みやDI/EIにより、くだんの割り込みの受付が遅延して、まさに危険な区間で送信終了した(シフトレジスタから送出終了した)」という状況のアナロジーとして行いました。

    その結果、以下の赤文字のコードにした場合に、期待した割り込みが発生しなくなりました。(本来は LED1==ON にならないといけないのに、LED1==OFF のままになってしまいました。)

    r_cg_serial_user.c

    static void __near r_csi00_interrupt(void)
    {
        if (g_csi00_tx_count > 0U)
        {
            SIO00 = *gp_csi00_tx_address;
            gp_csi00_tx_address++;
            g_csi00_tx_count--;
        }
        else
        {
    #if 0
            /* LED0 == ON,  LED1 == ON     --> OK */
            /* nothing */
    #elif 1
            /* LED0 == ON,  LED1 == OFF!!! --> NG!!! */
            nop(); 8回繰り返し nop();
    #elif 0
            /* LED0 == OFF, LED1 == ON     --> OK */
            nop(); 8回繰り返し nop();
            nop(); 8回繰り返し nop();
            nop(); 8回繰り返し nop();
    #endif

            if ((SSR00 & _0040_SAU_UNDER_EXECUTE) == 0U)
            {
                r_csi00_callback_sendend();    /* complete send */
                LED1 = LED_ON;
            }
            else
            {
                SMR00 &= ~_0001_SAU_BUFFER_EMPTY;
                LED0 = LED_ON;
            }
        }
    }

    以下、CS+ V8.03で今回のコードを生成させた時のコード生成機能の設定内容の画面コピーです。





    以下、CS+ V8.01のRenesas RL78 Simulatorで実行させた時の画面コピーです。

    送信終了待ちループを抜けた箇所にブレークポイントを設定したものの送信終了しても何時までも経ってもブレークしない


    何時までも経ってもブレークしないのでマニュアルブレークすると送信終了待ちループの中でブレークする(抜けていない)


    なお、Renesas RL78 Simulatorのシリアルウィンドウ上でCSI通信の送受信をする方法は以下のスレッドの通りです。

    CSIのシミュレーション方法
    japan.renesasrulz.com/cafe_rene/f/forum18/5834/csi
     

Children
No Data