Top Page [◀◀]  2   3   4   5   6   7   8   9   ... [▶▶Last Page

チョコさんが以前に指摘されていた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の画面コピーは先程のソースを生成させた時のコード生成機能の設定内容です。



 

  • チョコです。

    NoMaYさん,半年くらい前のものですね。

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

    はい,そうです。

    問題は,「if ((SSR00 & _0040_SAU_UNDER_EXECUTE) == 0U)」の段階では,まだ送信中でこのif文は不成立で,elseの「SMR00 &= ~_0001_SAU_BUFFER_EMPTY;」で割り込みタイミングを変更する前に転送が完了したときです。この場合には,割り込みのタイミングを転送完了に変更した段階ではすでに割り込みのトリガになる転送完了は終わっているので,割り込みタイミングを変更しても新たな割り込みは発生しません。

    この現象は,転送スピードを速くしないと出てきません。

  • チョコさん、こんにちは。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
     

  • こんにちは。NoMaYです。#スレッドのタイトルを少し変えました。

    今度は以下により現象を再現させるプログラムを作成しました。(RL78/G14 Fast Prototyping Boardの単体とRenesas RL78 Simulatorの両方で現象を再現させることが出来ました。)

    ・ CPU動作周波数は32MHz
    ・ CSIボーレートを2Mbps
    ・ 通常処理側で、DI+狙った数のNOP+EIにより、くだんの割り込みの受付を遅延させて、まさに危険な区間で送信終了する(シフトレジスタから送出終了する)ようにした

    以下にプロジェクトのファイル一式を添付します。(当方特有の事情で、コード生成はCS+ V8.03、シミュレータはCS+ V8.01、ビルドはCC-RL V1.02、を使用しています。)上記のCPU動作周波数とCSIボーレートの変更の他に、P1のb2, b1, b0を出力ポートに変更しています。今回は通常処理側でのDI/EIによる割り込み禁止区間が分かるようにb0(のみ)を0→1→0と変化させています。(なお、P1のb2, b1, b0はRL78/G14 Fast Prototyping BoardのArduinoソケットからでも観測可能です。)

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

    今回、通常処理ルーチン側を以下の通りとしました。

    r_main.c

    void main(void)
    {
        R_MAIN_UserInit();
        /* Start user code. Do not edit comment generated here */
        {
            uint8_t tx[5];
            EI();
            R_CSI00_Start();
            tx[0] = 0;
            tx[1] = 1;
            tx[2] = 2;
            tx[3] = 3;
            tx[4] = 4;
            R_CSI00_Send(tx, 5);

    #if 0 /* Renesas RL78 Simulator */
    #define SIM if(1)
    #define _x_
    #define FPB else if(0)
    #elif 1 /* RL78/G14 Fast Prototyping Board */
    #define SIM if(0)
    #define _x_
    #define FPB else if(1)
    #endif

            /* Note that total clocks of below line are clocks of NOPs + clocks in ISR. */
            SIM{ NOP300();NOP5(); } _x_ FPB{ NOP300();NOP10();NOP5(); }
    #if 0
            /* LED0 == ON,  LED1 == ON     --> OK */
            /* nothing */
    #elif 0
            /* LED0 == ON,  LED1 == ON     --> OK */
            DI();
            P1 = 1;
            SIM{ NOP80();NOP3(); } _x_ FPB{ NOP70();NOP9(); }
            P1 = 0;
            EI();
    #elif 1
            /* LED0 == ON,  LED1 == OFF!!! --> NG!!! */
            DI();
            P1 = 1;
            SIM{ NOP80();NOP4(); } _x_ FPB{ NOP80();        }
            P1 = 0;
            EI();
    #elif 0
            /* LED0 == ON,  LED1 == OFF!!! --> NG!!! */
            DI();
            P1 = 1;
            SIM{ NOP90();NOP5(); } _x_ FPB{ NOP90();NOP3(); }
            P1 = 0;
            EI();
    #elif 0
            /* LED0 == OFF, LED1 == ON     --> OK */
            DI();
            P1 = 1;
            SIM{ NOP90();NOP6(); } _x_ FPB{ NOP90();NOP4(); }
            P1 = 0;
            EI();
    #endif
            NOP();

            while (false == g_csi00_tx_ready_flag)
            {
                NOP();
            }
        }
        END();

        while (1U)
        {
            NOP();
        }
        /* End user code. Do not edit comment generated here */
    }

    他方、割り込み処理ルーチン側は以下の通りです。

    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 */
                LED1 = LED_ON;
            }
            else
            {
                SMR00 &= ~_0001_SAU_BUFFER_EMPTY;
                LED0 = LED_ON;
            }
        }
    }

    なお、上記の割り込み処理ルーチンのリストファイルは以下の通りです。(デフォルト最適化でコンパイルしています。) SSR00からの読み出し箇所とSMR00への書き込み箇所を赤文字にしています。

        。。。途中省略。。。

        ;***       85 :         if ((SSR00 & _0040_SAU_UNDER_EXECUTE) == 0U)
        movw ax, !0x0100
        mov a, x
        bt a.6, $.BB@LABEL@1_3
    .BB@LABEL@1_2:  ; if_then_bb14
        ;***       86 :         {
        ;***       87 :             r_csi00_callback_sendend();    /* complete send */
        call !!_r_csi00_callback_sendend@1
        ;***       88 :             LED1 = LED_ON;
        clr1 0xFFF04.4
        br $.BB@LABEL@1_4
    .BB@LABEL@1_3:  ; if_else_bb18
        movw de, #0x0110
        ;***       89 :         }
        ;***       90 :         else
        ;***       91 :         {
        ;***       92 :             SMR00 &= ~_0001_SAU_BUFFER_EMPTY;
        movw ax, [de]
        xch a, x
        and a, #0xFE
        xch a, x
        movw [de], ax
        ;***       93 :             LED0 = LED_ON;
        clr1 0xFFF04.3

        。。。以後省略。。。

    以下、Renesas RL78 Simulatorでの実行結果です。

    /* LED0 == ON,  LED1 == ON     --> OK */
    /* nothing */
    /* LED0 == ON,  LED1 == ON     --> OK */
    DI();
    P1 = 1;
    SIM{ NOP80();NOP3(); } _x_ FPB{ NOP70();NOP9(); }
    P1 = 0;
    EI();
    /* LED0 == ON,  LED1 == OFF!!! --> NG!!! */
    DI();
    P1 = 1;
    SIM{ NOP80();NOP4(); } _x_ FPB{ NOP80();        }
    P1 = 0;
    EI();
    /* LED0 == OFF, LED1 == ON     --> OK */
    DI();
    P1 = 1;
    SIM{ NOP90();NOP6(); } _x_ FPB{ NOP90();NOP4(); }
    P1 = 0;
    EI();

     

  • こんにちは。NoMaYです。

    対処方法を考えてみたのですが、まず、今回の割り込みコードの問題は、見え方として、以下の2つのタイプに見えるのかな、と思います。

    (1) CPU動作周波数(MHz)とCSIボーレート(Mbps)の比が4:1ぐらいの場合(例えば24MHz:6Mbpsとか32MHz:8Mbpsとか)には、コンパイラの種類とかバージョンとか最適化レベルとか(或いはコード生成されたコードを改造した内容とか)のバランス次第では、(常に)送信終了のコールバック関数呼び出しがスッポ抜ける(コールバック関数が呼び出されない)

    (2) 上記の(1)の場合よりCSIボーレートが低い場合でも、割り込み禁止区間(他の割り込みや明示的なDI/EIによるもの等)が絶妙なタイミングでくだんの割り込み要求の発生とオーバーラップしてしまった時には、送信終了のコールバック関数呼び出しがスッポ抜ける(コールバック関数が呼び出されない)

    RL78/G14 ユーザーズマニュアル ハードウェア編の記載は、以下の画面コピーの通りなのですが、文面からイメージする対処方法はこんな感じなのかな、と思います。ですが、せっかくコード生成されたコードにはユーザーズマニュアルに記載されていないアイデアが盛り込まれていますので、それを継承した対処方法を試してみました。(もっとも、製品に適用する場合には、ルネサスさんにNOPを挿入して時間稼ぎする必要がある箇所がないかどうか確認した方が良いと思いますが、、、)

    ユーザーズマニュアルの文面からイメージする対処方法:
    (1) ⇒ 諦める(連続送信モードを諦めてシングル送信モードを使う)
    (2) ⇒ 多重割り込みを使って何とかする or 諦める(連続送信モードを諦めてシングル送信モードを使う)

    RL78/G14 ユーザーズマニュアル ハードウェア編 画面コピー
    www.renesas.com/jp/ja/search/keyword-search.html#genre=document&q=r01uh0186
    r01uh0186jj0330-rl78g14.pdf



    コード生成されたコードのアイデアを継承した対処方法: (桃色文字の行はデバッグ用なのでデバッグ時以外は削除)

    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
        {

            SMR00 &= ~_0001_SAU_BUFFER_EMPTY;
            if ((SSR00 & _0040_SAU_UNDER_EXECUTE) == 0U)
            {
                CSIMK00 = 1U;    /* disable INTCSI00 interrupt */
                CSIIF00 = 0U;    /* clear INTCSI00 interrupt flag */
                r_csi00_callback_sendend();    /* complete send */
                LED1 = LED_ON;
            }
            else
            {
                LED0 = LED_ON;
            }
        }
    }

    なお、上記の割り込み処理ルーチンのリストファイルは以下の通りです。(デフォルト最適化でコンパイルしています。) SMR00への書き込み箇所とSSR00からの読み出し箇所を赤文字にしています。(なお、以下の場合、SMR00への書き込みとSSR00からの読み出しが連続していますが、コンパイラの種類とかバージョンとか最適化レベルとか次第では連続せずに間が開く可能性もあると思っていて、その場合、その区間で送信終了した(シフトレジスタから送出終了した)時には、そこで割り込み要求が発生してしまい、コールバック関数呼出し後にもう1回割り込みが受け付けられて、そこでまたコールバック関数呼出しが行われてしまいますので、それを防止する為、緑文字のコードを追加しています。)

        。。。途中省略。。。

        ;***       85 :         SMR00 &= ~_0001_SAU_BUFFER_EMPTY;
        movw ax, [de+0x10]
        xch a, x
        and a, #0xFE
        xch a, x
        movw [de+0x10], ax
        ;***       86 :         if ((SSR00 & _0040_SAU_UNDER_EXECUTE) == 0U)
        movw ax, [de]
        mov a, x
        bt a.6, $.BB@LABEL@1_3
    .BB@LABEL@1_2:  ; if_then_bb16
        ;***       87 :         {
        ;***       88 :             CSIMK00 = 1U;    /* disable INTCSI00 interrupt */
        set1 0xFFFE5.5
        ;***       89 :             CSIIF00 = 0U;    /* clear INTCSI00 interrupt flag */
        clr1 0xFFFE1.5
        ;***       90 :             r_csi00_callback_sendend();    /* complete send */
        call !!_r_csi00_callback_sendend@1
        ;***       91 :             LED1 = LED_ON;
        clr1 0xFFF04.4
        br $.BB@LABEL@1_4
    .BB@LABEL@1_3:  ; if_else_bb26
        ;***       92 :         }
        ;***       93 :         else
        ;***       94 :         {
        ;***       95 :             LED0 = LED_ON;
        clr1 0xFFF04.3

        。。。以後省略。。。

    以下にプロジェクトのファイル一式を添付します。(当方特有の事情で、コード生成はCS+ V8.03、シミュレータはCS+ V8.01、ビルドはCC-RL V1.02、を使用しています。)

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

    今回、通常処理ルーチン側を以下の通りとしました。

    r_main.c

    void main(void)
    {
        R_MAIN_UserInit();
        /* Start user code. Do not edit comment generated here */
        {
            uint8_t tx[5];
            EI();
            R_CSI00_Start();
            tx[0] = 0;
            tx[1] = 1;
            tx[2] = 2;
            tx[3] = 3;
            tx[4] = 4;
            R_CSI00_Send(tx, 5);

    #if 0 /* Renesas RL78 Simulator */
    #define SIM if(1)
    #define _x_
    #define FPB else if(0)
    #elif 1 /* RL78/G14 Fast Prototyping Board */
    #define SIM if(0)
    #define _x_
    #define FPB else if(1)
    #endif

            /* Note that total clocks of below line are clocks of NOPs + clocks in ISR. */
            SIM{ NOP300();NOP00();NOP5(); } _x_ FPB{ NOP300();NOP10();NOP5(); }
    #if 0
            /* LED0 == ON,  LED1 == ON     --> OK */
            /* nothing */
    #elif 0
            /* LED0 == ON, LED1 == ON     --> OK */
            DI();
            P1 = 1;
            SIM{ NOP80();NOP9(); } _x_ FPB{ NOP80();NOP6(); }
            P1 = 0;
            EI();
    #elif 1
            /* LED0 == OFF, LED1 == ON     --> OK */
            DI();
            P1 = 1;
            SIM{ NOP90();NOP0(); } _x_ FPB{ NOP80();NOP7(); }
            P1 = 0;
            EI();
    #elif 0
            /* LED0 == ON, LED1 == ON     --> OK */
            NOP1();
            DI();
            P1 = 1;
            SIM{ NOP90();NOP0(); } _x_ FPB{ NOP80();NOP7(); }
            P1 = 0;
            EI();
    #endif
            NOP();

            while (false == g_csi00_tx_ready_flag)
            {
                NOP();
            }
        }
        END();

        while (1U)
        {
            NOP();
        }
        /* End user code. Do not edit comment generated here */
    }

    以下、Renesas RL78 Simulatorでの実行結果です。

    /* LED0 == ON,  LED1 == ON     --> OK */
    /* nothing */
    /* LED0 == ON, LED1 == ON     --> OK */
    DI();
    P1 = 1;
    SIM{ NOP80();NOP9(); } _x_ FPB{ NOP80();NOP6(); }
    P1 = 0;
    EI();
    /* LED0 == OFF, LED1 == ON     --> OK */
    DI();
    P1 = 1;
    SIM{ NOP90();NOP0(); } _x_ FPB{ NOP80();NOP7(); }
    P1 = 0;
    EI();
    /* LED0 == ON, LED1 == ON     --> OK */
    NOP1();
    DI();
    P1 = 1;
    SIM{ NOP90();NOP0(); } _x_ FPB{ NOP80();NOP7(); }
    P1 = 0;
    EI();

     

  • こんにちは。NoMaYです。

    今回の割り込みコードの問題はCSI連続送信でしたが、他のタイプの連続転送に関しても、コードを生成させて、生成コードを確認してみました。不具合原因のコードから推測すると、問題点の(2)の該当/非該当は以下の表のようになると思います。なお、問題点の(1)は、コードの複雑さとボーレートの上限から推測すると、CSI連続送信しか該当しないのではないかと思います。←[訂正] 再検討中です。

    問題点(再掲):

    (1) CPU動作周波数(MHz)とCSIボーレート(Mbps)の比が4:1ぐらいの場合(例えば24MHz:6Mbpsとか32MHz:8Mbpsとか)には、コンパイラの種類とかバージョンとか最適化レベルとか(或いはコード生成されたコードを改造した内容とか)のバランス次第では、(常に)送信終了のコールバック関数呼び出しがスッポ抜ける(コールバック関数が呼び出されない)

    (2) 上記の(1)の場合よりCSIボーレートが低い場合でも、割り込み禁止区間(他の割り込みや明示的なDI/EIによるもの等)が絶妙なタイミングでくだんの割り込み要求の発生とオーバーラップしてしまった時には、送信終了のコールバック関数呼び出しがスッポ抜ける(コールバック関数が呼び出されない)

    問題点の(2)の該当/非該当の推測:

    SAU CSI連続送信モード 該当(此処までの本スレッドの案件)
    SAU CSI連続受信モード 該当?
    SAU CSI連続送受信モード 該当?
    SAU UART受信 非該当(連続転送モード自体が無い)
    SAU UART連続送信モード(繰り返し送信モード) 該当?
    SAU 簡易IIC 非該当(連続転送モード自体が無い)
    IICA 非該当(連続転送モード自体が無い)

    以下にプロジェクトのファイル一式を添付します。(CS+ V8.03でコード生成しています。なお、今回はビルドをしていません。)

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

    r_cg_serial_user.c

    SAU CSI連続送信モード(此処までの本スレッドの案件)

    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;
            }
        }
    }

    SAU CSI連続受信モード

    static void __near r_csi10_interrupt(void)
    {
        volatile uint8_t err_type;

        err_type = (uint8_t)(SSR02 & _0001_SAU_OVERRUN_ERROR);
        SIR02 = (uint16_t)err_type;

        if (1U == err_type)
        {
            r_csi10_callback_error(err_type);    /* overrun error occurs */
        }
        else
        {
            if (0U == g_csi10_rx_count)
            {
                SIO10 = 0xFFU;    /* write dummy */
                g_csi10_rx_count++;
            }
            else
            {
                if (g_csi10_rx_count < (g_csi10_rx_length - 1U))
                {
                    *gp_csi10_rx_address = SIO10;
                    gp_csi10_rx_address++;
                    g_csi10_rx_count++;
                    SIO10 = 0xFFU;    /* write dummy */
                }
                else
                {
                    if ((SMR02 & _0001_SAU_BUFFER_EMPTY) == 0x0001U)
                    {
                        *gp_csi10_rx_address = SIO10;
                        gp_csi10_rx_address++;
                        g_csi10_rx_count++;

                        if ((SSR02 & _0040_SAU_UNDER_EXECUTE) == 0U)
                        {
                            *gp_csi10_rx_address = SIO10;
                            r_csi10_callback_receiveend();    /* complete receive */
                        }
                        else
                        {
                            SMR02 &= ~_0001_SAU_BUFFER_EMPTY;
                        }
                    }
                    else
                    {
                        *gp_csi10_rx_address = SIO10;
                        r_csi10_callback_receiveend();    /* complete receive */
                    }
                }
            }
        }
    }

    SAU CSI連続送受信モード

    static void __near r_csi20_interrupt(void)
    {
        volatile uint8_t err_type;

        err_type = (uint8_t)(SSR10 & _0001_SAU_OVERRUN_ERROR);
        SIR10 = (uint16_t)err_type;

        if (1U == err_type)
        {
            r_csi20_callback_error(err_type);    /* overrun error occurs */
        }
        else
        {
            if (g_csi20_tx_count > 0U)
            {
                if (g_csi20_tx_count != (g_csi20_send_length - 1U))
                {
                    *gp_csi20_rx_address = SIO20;
                    gp_csi20_rx_address++;
                }
                
                SIO20 = *gp_csi20_tx_address;
                gp_csi20_tx_address++;
                g_csi20_tx_count--;
            }
            else
            {
                if ((SMR10 & _0001_SAU_BUFFER_EMPTY) == 1U)
                {
                    r_csi20_callback_sendend();    /* complete send */
                    *gp_csi20_rx_address = SIO20;
                    gp_csi20_rx_address++;    
                    
                    if ((SSR10 & _0040_SAU_UNDER_EXECUTE) == 0U)
                    {
                        *gp_csi20_rx_address = SIO20;
                        r_csi20_callback_receiveend();    /* complete receive */
                    }
                    else
                    {
                        SMR10 &= ~_0001_SAU_BUFFER_EMPTY;
                    }
                }
                else
                {
                    *gp_csi20_rx_address = SIO20;
                    r_csi20_callback_receiveend();    /* complete receive */
                }
            }
        }
    }

    SAU UART連続送信モード(繰り返し送信モード)

    static void __near r_uart3_interrupt_send(void)
    {
        if (g_uart3_tx_count > 0U)
        {
            TXD3 = *gp_uart3_tx_address;
            gp_uart3_tx_address++;
            g_uart3_tx_count--;
        }
        else
        {

            if ((SSR12 & _0040_SAU_UNDER_EXECUTE) == 0U)
            {
                r_uart3_callback_sendend();
            }
            else
            {
                SMR12 &= ~_0001_SAU_BUFFER_EMPTY;
            }
        }
    }

     

  • In reply to NoMaY:

    チョコです。

    NoMaYさん,
    SAU CSI連続受信モードはあり得ないですね。
    連続するかどうかは送信側の処理の問題で,受信側はきたものを受信して受信完了したら,割り込みを発生するだけです。割り込みのタイミングを変更するような処理はないので,非該当です。
    スレーブの場合に,処理が遅れた時には,オーバーラン・エラーになるだけです。
  • In reply to チョコ:

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

    リプライ有難う御座います。

    > SAU CSI連続受信モードはあり得ないですね。
    。。。
    > 割り込みのタイミングを変更するような処理はないので,非該当です。

    生成コードを確認すると、ソース上には、割り込みのタイミングを変更する、以下の行(赤字箇所)が存在していますので、後で動作を追い掛けてみます。(何だろう、、、) どうも有難う御座いました。

    SAU CSI連続受信モード

    r_cg_serial.c

    MD_STATUS R_CSI10_Receive(uint8_t * const rx_buf, uint16_t rx_num)
    {
        MD_STATUS status = MD_OK;

        if (rx_num < 1U)
        {
            status = MD_ARGERROR;
        }
        else
        {
            if (1U == rx_num)
            {
                SMR02 &= (~_0001_SAU_BUFFER_EMPTY);
            }
            else
            {
                SMR02 |= _0001_SAU_BUFFER_EMPTY;
            }

            g_csi10_rx_length = rx_num;    /* receive data length */
            g_csi10_rx_count = 0U;         /* receive data count */
            gp_csi10_rx_address = rx_buf;  /* receive buffer pointer */
            SIO10 = 0xFFU;    /* start receive by dummy write */
        }

        return (status);
    }

    r_cg_serial_user.c

    static void __near r_csi10_interrupt(void)
    {
        volatile uint8_t err_type;

        err_type = (uint8_t)(SSR02 & _0001_SAU_OVERRUN_ERROR);
        SIR02 = (uint16_t)err_type;

        if (1U == err_type)
        {
            r_csi10_callback_error(err_type);    /* overrun error occurs */
        }
        else
        {
            if (0U == g_csi10_rx_count)
            {
                SIO10 = 0xFFU;    /* write dummy */
                g_csi10_rx_count++;
            }
            else
            {
                if (g_csi10_rx_count < (g_csi10_rx_length - 1U))
                {
                    *gp_csi10_rx_address = SIO10;
                    gp_csi10_rx_address++;
                    g_csi10_rx_count++;
                    SIO10 = 0xFFU;    /* write dummy */
                }
                else
                {
                    if ((SMR02 & _0001_SAU_BUFFER_EMPTY) == 0x0001U)
                    {
                        *gp_csi10_rx_address = SIO10;
                        gp_csi10_rx_address++;
                        g_csi10_rx_count++;

                        if ((SSR02 & _0040_SAU_UNDER_EXECUTE) == 0U)
                        {
                            *gp_csi10_rx_address = SIO10;
                            r_csi10_callback_receiveend();    /* complete receive */
                        }
                        else
                        {
                            SMR02 &= ~_0001_SAU_BUFFER_EMPTY;
                        }
                    }
                    else
                    {
                        *gp_csi10_rx_address = SIO10;
                        r_csi10_callback_receiveend();    /* complete receive */
                    }
                }
            }
        }
    }

     

  • In reply to NoMaY:

    チョコです。
    意味不明ですね。
    デバイスのマニュアルにも,受信動作時には,レジスタ設定は明確に,「0:転送完了割り込み」と記載されています。
    ここらが,私がシリアル関係のコード生成されたコードを使わない理由でもあります。
  • こんにちは。NoMaYです。

    SAU CSI連続受信モードですが、まず、そもそもの私の認識不足としてスレーブモードにシングル転送モードと連続転送モードの区別があるとは思っていなかった(マスタモードにしかないと思っていた)ので、マスタモードかスレーブモードかを明記していなかったという拙い点があった、と思います。

    そこで、デバイス(RL78/G13とRL78/G14)のユーザーズマニュアルを確認すると、スレーブモードでは、CSI連続送信モードとCSI連続送受信モードはあれど、CSI連続受信モードは無いのですね、、、

    そこで、スレーブモードでコード生成させようとしたところ、コード生成機能のGUI上では無いはずのCSI連続受信モードが設定出来てしまうのですね、、、

    以下、これを表にしたものです。

      マスタモード スレーブモード
    CSI送信モード 連続転送モード 有 連続転送モード 有
    CSI受信モード 連続転送モード 有 連続転送モード 無(しかしコード生成機能では設定出来てしまう)
    CSI送受信モード 連続転送モード 有 連続転送モード 有

    以下、RL78/G14のユーザーズマニュアルの画面コピーとCS+ V8.03のコード生成機能の画面コピーです。

    RL78/G14 ユーザーズマニュアル ハードウェア編
    www.renesas.com/jp/ja/search/keyword-search.html#genre=document&q=r01uh0186
    r01uh0186jj0330-rl78g14.pdf

    CSIマスタモードシングル受信モード


    CSIマスタモード連続受信モード



    CSIスレーブモードシングル受信モード (なお、CSIスレーブモード連続受信モードはありませんでした)



    コード生成機能ではCSI受信のスレーブモードでも連続転送モードが設定出来てしまいました



    [余談]

    なお、以下のスレッドでのことですが、CSIのマスタ連続送受信の開始時にも何かがあるようです。

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

  • In reply to NoMaY:

    チョコです。

    マスタには,連続受信が存在していたんですね。これは,割り込みは通信起動用のダミーデータの書込みのタイミング用ですね。(決して受信用のタイミングじゃないです。受信に関してはタイミング的に半クロック分遅れるので余裕がなくなるはずですが,マスタなので,関係はないですが。)

    私はスレーブ受信を眺めていました。

    それにしてもスレーブで連続受信はあり得ません。単に,全部の組み合わせをやっただけ?

    基本的にスレーブはマスターからのクロックに対して動作するだけですから,常にマスタのタイミングに従うだけです。

  • In reply to チョコ:

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

    > それにしてもスレーブで連続受信はあり得ません。単に,全部の組み合わせをやっただけ?

    推測ですが、意図してやった、というのではなくて、その場合だけ無いことに気付かなくてグレーにする処理がコード生成機能のGUIに入っていない(CSI受信で外部クロック選択時は連続転送モードをグレーにして選択出来ないようにする処理を入れ忘れた)のだろうと思うのです。(スレーブモードにシングル転送モードと連続転送モードの区別があるとは思っていなかった私がそう言うのも気まずいところがありますが、、、)

  • こんにちは。NoMaYです。

    以前に投稿した、不具合原因のコードから推測した以下の問題点の(2)の該当/非該当の表を、CSIのマスタ/スレーブを明記するように修正しました。(問題点の(1)に関しての表がどうなるかは検討中です。)

    問題点(再掲):

    (1) CPU動作周波数(MHz)とCSIボーレート(Mbps)の比が4:1ぐらいの場合(例えば24MHz:6Mbpsとか32MHz:8Mbpsとか)には、コンパイラの種類とかバージョンとか最適化レベルとか(或いはコード生成されたコードを改造した内容とか)のバランス次第では、(常に)送信終了のコールバック関数呼び出しがスッポ抜ける(コールバック関数が呼び出されない)

    (2) 上記の(1)の場合よりCSIボーレートが低い場合でも、割り込み禁止区間(他の割り込みや明示的なDI/EIによるもの等)が絶妙なタイミングでくだんの割り込み要求の発生とオーバーラップしてしまった時には、送信終了のコールバック関数呼び出しがスッポ抜ける(コールバック関数が呼び出されない)

    問題点の(2)の該当/非該当の推測:

    SAU CSIマスタ連続送信モード 該当(此処までの本スレッドの案件)
    SAU CSIマスタ連続受信モード 該当?
    SAU CSIマスタ連続送受信モード 該当?
    SAU CSIスレーブ連続送信モード 該当?
    SAU CSIスレーブ受信モード 非該当(連続転送モード自体が無い *1)
    SAU CSIスレーブ連続送受信モード 該当?
    SAU UART受信 非該当(連続転送モード自体が無い)
    SAU UART連続送信モード(繰り返し送信モード) 該当?
    SAU 簡易IIC 非該当(連続転送モード自体が無い)
    IICA 非該当(連続転送モード自体が無い)

    *1: デバイスのユーザーズマニュアルではCSIスレーブ受信モードに連続転送モードは無いのですが、コード生成機能のGUI上は設定出来てしまう不具合があります。

    以下にSAU CSIスレーブモードのソースを生成させたプロジェクトのファイル一式を添付します。(CS+ V8.03でコード生成しています。なお、今回はビルドをしていません。)

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

    r_cg_serial_user.c

    SAU CSIスレーブ連続送信モード

    static void __near r_csi00_interrupt(void)
    {
        volatile uint8_t err_type;

        err_type = (uint8_t)(SSR00 & _0001_SAU_OVERRUN_ERROR);
        SIR00 = (uint16_t)err_type;

        if (1U == err_type)
        {
            r_csi00_callback_error(err_type);    /* overrun error occurs */
        }
        else
        {
            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;
                }
            }
        }
    }

    SAU CSIスレーブ連続送受信モード

    static void __near r_csi20_interrupt(void)
    {
        volatile uint8_t err_type;

        err_type = (uint8_t)(SSR10 & _0001_SAU_OVERRUN_ERROR);
        SIR10 = (uint16_t)err_type;

        if (1U == err_type)
        {
            r_csi20_callback_error(err_type);    /* overrun error occurs */
        }
        else
        {
            if (g_csi20_tx_count > 0U)
            {
                if (g_csi20_tx_count != (g_csi20_send_length - 1U))
                {
                    *gp_csi20_rx_address = SIO20;
                    gp_csi20_rx_address++;
                }
                
                SIO20 = *gp_csi20_tx_address;
                gp_csi20_tx_address++;
                g_csi20_tx_count--;
            }
            else
            {
                if ((SMR10 & _0001_SAU_BUFFER_EMPTY) == 1U)
                {
                    r_csi20_callback_sendend();    /* complete send */
                    *gp_csi20_rx_address = SIO20;
                    gp_csi20_rx_address++;    
                    
                    if ((SSR10 & _0040_SAU_UNDER_EXECUTE) == 0U)
                    {
                        *gp_csi20_rx_address = SIO20;
                        r_csi20_callback_receiveend();    /* complete receive */
                    }
                    else
                    {
                        SMR10 &= ~_0001_SAU_BUFFER_EMPTY;
                    }
                }
                else
                {
                    *gp_csi20_rx_address = SIO20;
                    r_csi20_callback_receiveend();    /* complete receive */
                }
            }
        }
    }

     

  • In reply to NoMaY:

    チョコです。
    UARTを使おうとしたので,UARTの連続送信を検討したのですが,UARTの連続送信で,最後のデータに対して転送完了割り込みに変更する必要はないのではないかと考えています。
    CSI(SPI)では,転送完了でCS信号を制御する必要があるので,転送完了を知るために割り込みタイミングを切り替えることは理解できますが。
  • In reply to チョコ:

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

    UARTですが、(N-chオープンドレインタイプではなく)ポート出力を1本併用して外部のドライバICで送信と受信を切り替えるタイプの単線UARTがありますけれど、その場合に都合が良いということで、(デバイスのユーザーズマニュアルも同じく)最後のデータに対して割り込みタイミングを切り替えるようになっているのではないだろうか、という気がします。(加えて、以下の画面コピーのような、もっと確実なタイミングで切り替えることも出来るのではないだろうか、という気もします、、、)

    以下、別スレッドに投稿した時のものですが、デバイスのユーザーズマニュアルの画面コピーです。

    www.renesas.com/jp/ja/search/keyword-search.html#genre=document&q=r01uh0186
    r01uh0186jj0330-rl78g14.pdf

     

  • In reply to NoMaY:

    チョコです。

    殆どの場合に,調歩同期通信は殆ど(全二重の)無手順で使っていることがほとんどのようです。

    半二重通信の場合には,通信完了のタイミングは必要でしょうが,私は切り替え信号で外部のドライバを使ってまで切り替えることはしないですね。ワイヤード・オア可能なオープン・ドレインやオープン・コレクタでないと,相手側でも,同じタイミングで切り替える必要があります。そのため,信号線を1本に削減したのに制御信号で1本増えてしまい,結局2本の信号線が必要になります。(あまり意味がない。素直に2本の信号線使うべきでしょうね。)

     

    デバイスのマニュアルは,レジスタ設定があるので,あるものは全て説明しているだけかもしれません。決して使い方を理解して書いているとも思えませんが。それを全部まねして使う必要もないのですが。(マニュアルでおかしいと思われるのが,「フレーミング・エラー発生時の処理手順」で「スタートがずれているためにフレーミング・エラーが起きたと考えられるため,通信相手との同期を取り直して通信を再開する」と書かれていますが,これでは,あまりに抽象的で,具体的にどうすればいいかがわからないのではないでしょうか。私が話をした範囲では,初期設定からやり直すと考えている人がほとんどでした。やるべきことは,単純で,送信側に対して1キャラクタ分以上の時間送信しないように要求するだけです。)

    また,CSIと違って,UART として使う場合には,ボーレートの16倍以上の内部クロックでないとボーレート誤差が気になるので,あまり処理スピードが問題になる可能性は低いと考えています。昔は,Xtalで伝送周波数に合わせたクロック周波数(4.9152MHz等)を使っていたので,ボーレート誤差は殆どなかったのですが。いつの間にか,逆に,誤差がいくつまでボーレートに対応できるになってしまっていますね。

    と言うことで,書いてあることは一応疑ってかかるチョコでした。

Top Page [◀◀]  2   3   4   5   6   7   8   9   ... [▶▶Last Page