チョコさんが以前に指摘されていた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です。

    以前に投稿した、不具合原因のコードから推測した以下の問題点の(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 */
                }
            }
        }
    }

     

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

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

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

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

     

  • チョコです。

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

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

     

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

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

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

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

    通信のことですので、相手側や周辺機器の事情により、オープン・ドレインやオープン・コレクタに出来ないこともありそうです。かふぇルネのスレッドでは、以下のスレッドで、RS485という規格に関連したアプリケーションで切り替え信号で切り替えている事例がありました。(自分が関わったものですが、RL78ではありませんけれど、、、)

    RX231 にてSCIの受信ができません。
    japan.renesasrulz.com/cafe_rene/f/forum5/5604/rx231-sci/31139#31139

    RZ/A2MのDMACについて教えてください
    japan.renesasrulz.com/cafe_rene/f/103__-_forum/5633/rz-a2m-dmac/32971#32971

    また、切り替え信号で切り替えを行う周辺機器の具体例として、以下の周辺機器がありました。

    RS485USB/シリアル変換アダプター
    kondo-robot.com/product/02133
    kondo-robot.com/w/wp-content/uploads/rs485usb_20190327.pdf
    画面コピー (青色枠は私の書き込み)


    ICS変換基板
    kondo-robot.com/product/03121
    kondo-robot.com/w/wp-content/uploads/ICS_adapter_manual.pdf
    画面コピー (青色枠は私の書き込み)


    専用ドライバICの使用例としては、以下の回路図がありました。

    SN75LBC176A 差動バス・トランシーバ
    www.tij.co.jp/product/jp/SN75LBC176A
    www.tij.co.jp/jp/lit/an/jaja179/jaja179.pdf
    画面コピー (青色枠は私の書き込み)

     

  • チョコです。
    RS485ですか。RS422(及びRS423)までは使ったことはあります。差動ドライブは信号を伸ばすときにはよく使いました。(そのころには,RS485は無かったので使ったことはありません。)
    ただ,当然ながら,図9のようなバスではなく,ポイントToポイントで全二重で使っていましたから,切り替え信号は使いませんでした。
    時代の違いですか。

    (提示されているICS変換基板のような回路では,TX_OUTがフローティングになるので怖い気がします。)
  • チョコです。
    バス方式では,通信方向を切り替える信号を使うことは了解です。
    バス方式で半二重通信を行う場合には,送信したデータを受信して正しくデータが送られたかを確認することになるかと思います。そうなると,無理して送信完了の割り込みに変更しなくても,受信完了割り込みが使えるのではないでしょうか。
Reply
  • チョコです。
    バス方式では,通信方向を切り替える信号を使うことは了解です。
    バス方式で半二重通信を行う場合には,送信したデータを受信して正しくデータが送られたかを確認することになるかと思います。そうなると,無理して送信完了の割り込みに変更しなくても,受信完了割り込みが使えるのではないでしょうか。
Children
No Data