RX用FITのUSBドライバをCS+6環境でコンパイル最適化レベル2以上にしたときの不具合

■経緯について
 CS+4環境で開発済みであり安定動作できているRX71M用FWプログラムがあります。
 このFWを最新のCS+6環境に置き換えるための作業過程で、USBホストドライバで
 不具合事象が発生しました。

■不具合事象
 CS+6(V6.01.00)/ビルドツールCC-RX V2.08.00環境でビルドしたFWでは、
 USBメモリの認識ができなくなってしまったことが判明。再現率100%

■調査状況について
 ・再現率100%のため、切り分け調査を開始
 ・切り分け調査した結果、USBホストドライバの一部ソースコードの最適化
  コンパイルが影響していることが判明。

■確認済み環境
 CS+4(V4.00.00)/ビルドツールCC-RX V2.05.00:問題なし
 CS+6(V6.00.00)/ビルドツールCC-RX V2.07.00:不具合事象あり
 CS+6(V6.01.00)/ビルドツールCC-RX V2.08.00:不具合事象あり

■USBHドライバの対象ソースコード
 \rx_fit\FITModules\r_usb_basic\src\hw
  - r_usb_creg_access.c
  - r_usb_hreg_access.c

■最適化レベル毎の再現性
 最適化レベル2(-optimize=2) コード・サイズ重視の最適化(-size) : NG(不具合再現)
 最適化レベル2(-optimize=2) 実行性能重視の最適化(-speed)   : NG(不具合再現)
 最適化レベル1(-optimize=1) コード・サイズ重視の最適化(-size) : OK
 最適化レベル1(-optimize=1) 実行性能重視の最適化(-speed)   : OK
 最適化レベル1(-optimize=1) コード・サイズ重視の最適化(-size) : OK
 最適化レベル0(-optimize=0)                                             : OK

■不具合の出るコードの例と暫定対策の例
 \rx_fit\FITModules\r_usb_basic\src\hw
  - r_usb_hreg_access.c
  void hw_usb_hset_rwupe (usb_utr_t *ptr, uint16_t port)
  {
      if (USB_PORT0 == port)
      {
      #if 0 // ★NG 元のコード
          ptr->ipp->DVSTCTR0.WORD |= USB_RWUPE;
          #else // ★OK こちらの書き方なら問題なし
          ptr->ipp->DVSTCTR0.WORD = ptr->ipp->DVSTCTR0.WORD | USB_RWUPE;
          #enfif
      }
  }

■今後の調査について
 引き続き、根本原因を究明し、対策の検討を進めたいと考えています。
 ・コンパイラのエラッタ確認(既知なのかどうか)
 ・ルネサスが公開している最新ドライバ(FITモジュール)の確認
 ・最適化によるアセンブラコードの違いを確認
 ・場合によってはソースコードを修正して対応する
 ・その他全てのドライバの確認(共通問題の可能性が高い)

何か情報お持ちの方がいましたら教えていただきたく、よろしくお願いいたします。

以上

Parents
  • ふじさん、こんにちは。NoMaYです。

    >iTRON向けにドライバの改造や性能チューニングを要所要所で施している
    その状況であれば、私は以下の対処案が有効かと思います。(余談ですが、おそらく、以下のスレッドの自作(というか移植というか)のiTORN(というかμITRON)のオープンソース実装のTOPPERS/ASPベースのプログラムは、動作しない、もしくは、何かしら問題が発生する、のでは無いだろうかと思っていて、また自己フォローを投稿しなければ、と思っているところです、、、)

    RX62NのUSBデバイスドライバについて
    japan.renesasrulz.com/cafe_rene/f/forum5/4314/rx62n-usb/28297#28297

    対処案を検討する前に、、、

    (1) 旧USBドライバの本件の該当箇所に__evenacessを記述してコードが想定通りに変化するか調べる
    (1a) 変化しなければ別の要因があると思われる
    (1b) 変化して期待したコードになれば対処案を検討する

    対処案

    (1) 最新のUSBドライバのソースの__evenacessの記述箇所を調べて旧ソースに反映する方法を検討する

    あと、少し気になっているのですが、CS+ 6で旧コンパイラを使用することは出来ます。ですので、以下の案もあるのではないだろうかと思います。(実際、私はCS+ 6でCC-RX V2.03を使用しています、、、)

    (2) お客様が望まれているのがCC-RXを最新にすることなのかCS+のIDEを最新にすることなのか確認する
    (2a) CC-RX V2.08の強い要望が無ければ、CS+ 6でCC-RXの旧コンパイラを使用する方法を提案する
    (2b) CC-RX V2.08を強く望まれるならば、コンパイラバージョンアップには相応の評価が避けられない点を理解して頂く

    余談ですが、上に書いたスレッドのTOPPERS/ASPのソースコードでは、__evenaccessへのケアがソースごとに違っているような印象でした。

    __evenaccessへのケアが有るソース例 (ただしuint8_tに対して__evenaccessは過剰な気もしますが)

    arch\rx630_ccrx\rx630_config.c

    /*
     *  割込み要因プライオリティレジスタアドレステーブル
     */
    volatile uint8_t __evenaccess * const ipr_reg_addr[ INHNO_MAX ] = {

        ICU_IPR000_ADDR,                /* No.16  バスエラー BUSERR */

    };

    /*
     *  割込み要求許可レジスタアドレステーブル
     */
    const IER_INFO ier_reg_addr[ INHNO_MAX ] = { (以下の構造体定義を参照 by NoMaY)

        { ICU_IER02_ADDR, ICU_IEN0_BIT },   /* No.16  バスエラー BUSERR */

    };

    arch\rx630_ccrx\rx630_config.h

    /*
     *  割込み制御用型定義
     */
    typedef struct ier_info {
        volatile uint8_t __evenaccess   *addr;
                 uint8_t                offset;
    } IER_INFO;

    __evenaccessへのケアが無いソース例 (少なくともvolatile uint32_t *mstpcrreg;に__evenaccessが無い)

    pdic\rx600\rx630_uart.c

    /*
     *  シリアルI/Oポート初期化ブロックの定義
     */
    typedef struct sio_port_initialization_block {
        volatile uint8_t    *ctlreg;        /* シリアルコントロールレジスタ(SCR) */
        volatile uint8_t    *modereg;       /* シリアルモードレジスタ(SMR) */
        volatile uint8_t    *extmodereg;    /* シリアル拡張モードレジスタ(SEMR) */
        volatile uint8_t    *statusreg;     /* シリアルステータスレジスタ(SSR) */
        volatile uint8_t    *tdreg;         /* トランスミットデータレジスタ(TDR)*/
        volatile uint8_t    *rdreg;         /* レシーブデータレジスタ(RDR) */
        volatile uint8_t    *bitratereg;    /* ビットレートレジスタ(BRR) */
        volatile uint32_t   *mstpcrreg;     /* モジュールストップコントロールレジスタ(MSTPCR) */
        volatile uint8_t    *ssrreg;        /* ステータスレジスタ */
        volatile uint8_t    *rxiirreg;      /* RXI用割込み要求レジスタ */
        uint8_t             tx_intno;       /* 送信(データエンプティ)割り込み番号 */
        uint8_t             rx_intno;       /* 受信(データフル)割り込み番号 */
        uint8_t             te_intno;       /* 送信(終了)割り込み番号 */
        uint8_t             sci_no;         /* SCIの番号(SCI0~SCI6) */
        uint32_t            mstpcr_offset;  /* MSTPCRの対応するビットオフセット */
    } SIOPINIB;

    もっとも、mstpcrregへの書き込みが以下のスタイルですので、TOPPERS/ASPの慣習では、(たまたま?)大丈夫そうですが、、、([追記] なお、sil_rew_mem()やsil_wrw_mem()のコードに__evenaccessが無いのは、将来のCC-RXのバージョンアップに対するリスク要因である、ような気がして来ましたが、、、)

    pdic\rx600\rx630_uart.c

    /*
     *  SIOドライバのシリアルモードレジスタ(SMR)
     */
    static void
    rx630_uart_setmode(const SIOPINIB *p_siopinib, uint8_t bitrate, uint8_t clksrc)
    {

        /*
         *  モジュールストップ機能の設定
         */
        sil_wrh_mem((uint16_t *)SYSTEM_PRCR_ADDR, (uint16_t)0xA502);    /* 書込み許可 */
        sil_wrw_mem((uint32_t *)p_siopinib->mstpcrreg,
            sil_rew_mem((uint32_t *)p_siopinib->mstpcrreg) & ~p_siopinib->mstpcr_offset);
        sil_wrh_mem((uint16_t *)SYSTEM_PRCR_ADDR, (uint16_t)0xA500);    /* 書込み禁止 */

    }

    include\sil.h ([追記] これでは呼び出し元の方に__evenaccessが有っても効かないような気がして来ました、、、)

    Inline uint32_t
    sil_rew_mem(const uint32_t *mem)
    {
        uint32_t    data;

        data = *((const volatile uint32_t *) mem); ←ここに__evenaccessが無いのはリスク要因な気が、、、
        return(data);
    }

    Inline void
    sil_wrw_mem(uint32_t *mem, uint32_t data)
    {
        *((volatile uint32_t *) mem) = data; ←ここに__evenaccessが無いのはリスク要因な気が、、、
    }

     

Reply
  • ふじさん、こんにちは。NoMaYです。

    >iTRON向けにドライバの改造や性能チューニングを要所要所で施している
    その状況であれば、私は以下の対処案が有効かと思います。(余談ですが、おそらく、以下のスレッドの自作(というか移植というか)のiTORN(というかμITRON)のオープンソース実装のTOPPERS/ASPベースのプログラムは、動作しない、もしくは、何かしら問題が発生する、のでは無いだろうかと思っていて、また自己フォローを投稿しなければ、と思っているところです、、、)

    RX62NのUSBデバイスドライバについて
    japan.renesasrulz.com/cafe_rene/f/forum5/4314/rx62n-usb/28297#28297

    対処案を検討する前に、、、

    (1) 旧USBドライバの本件の該当箇所に__evenacessを記述してコードが想定通りに変化するか調べる
    (1a) 変化しなければ別の要因があると思われる
    (1b) 変化して期待したコードになれば対処案を検討する

    対処案

    (1) 最新のUSBドライバのソースの__evenacessの記述箇所を調べて旧ソースに反映する方法を検討する

    あと、少し気になっているのですが、CS+ 6で旧コンパイラを使用することは出来ます。ですので、以下の案もあるのではないだろうかと思います。(実際、私はCS+ 6でCC-RX V2.03を使用しています、、、)

    (2) お客様が望まれているのがCC-RXを最新にすることなのかCS+のIDEを最新にすることなのか確認する
    (2a) CC-RX V2.08の強い要望が無ければ、CS+ 6でCC-RXの旧コンパイラを使用する方法を提案する
    (2b) CC-RX V2.08を強く望まれるならば、コンパイラバージョンアップには相応の評価が避けられない点を理解して頂く

    余談ですが、上に書いたスレッドのTOPPERS/ASPのソースコードでは、__evenaccessへのケアがソースごとに違っているような印象でした。

    __evenaccessへのケアが有るソース例 (ただしuint8_tに対して__evenaccessは過剰な気もしますが)

    arch\rx630_ccrx\rx630_config.c

    /*
     *  割込み要因プライオリティレジスタアドレステーブル
     */
    volatile uint8_t __evenaccess * const ipr_reg_addr[ INHNO_MAX ] = {

        ICU_IPR000_ADDR,                /* No.16  バスエラー BUSERR */

    };

    /*
     *  割込み要求許可レジスタアドレステーブル
     */
    const IER_INFO ier_reg_addr[ INHNO_MAX ] = { (以下の構造体定義を参照 by NoMaY)

        { ICU_IER02_ADDR, ICU_IEN0_BIT },   /* No.16  バスエラー BUSERR */

    };

    arch\rx630_ccrx\rx630_config.h

    /*
     *  割込み制御用型定義
     */
    typedef struct ier_info {
        volatile uint8_t __evenaccess   *addr;
                 uint8_t                offset;
    } IER_INFO;

    __evenaccessへのケアが無いソース例 (少なくともvolatile uint32_t *mstpcrreg;に__evenaccessが無い)

    pdic\rx600\rx630_uart.c

    /*
     *  シリアルI/Oポート初期化ブロックの定義
     */
    typedef struct sio_port_initialization_block {
        volatile uint8_t    *ctlreg;        /* シリアルコントロールレジスタ(SCR) */
        volatile uint8_t    *modereg;       /* シリアルモードレジスタ(SMR) */
        volatile uint8_t    *extmodereg;    /* シリアル拡張モードレジスタ(SEMR) */
        volatile uint8_t    *statusreg;     /* シリアルステータスレジスタ(SSR) */
        volatile uint8_t    *tdreg;         /* トランスミットデータレジスタ(TDR)*/
        volatile uint8_t    *rdreg;         /* レシーブデータレジスタ(RDR) */
        volatile uint8_t    *bitratereg;    /* ビットレートレジスタ(BRR) */
        volatile uint32_t   *mstpcrreg;     /* モジュールストップコントロールレジスタ(MSTPCR) */
        volatile uint8_t    *ssrreg;        /* ステータスレジスタ */
        volatile uint8_t    *rxiirreg;      /* RXI用割込み要求レジスタ */
        uint8_t             tx_intno;       /* 送信(データエンプティ)割り込み番号 */
        uint8_t             rx_intno;       /* 受信(データフル)割り込み番号 */
        uint8_t             te_intno;       /* 送信(終了)割り込み番号 */
        uint8_t             sci_no;         /* SCIの番号(SCI0~SCI6) */
        uint32_t            mstpcr_offset;  /* MSTPCRの対応するビットオフセット */
    } SIOPINIB;

    もっとも、mstpcrregへの書き込みが以下のスタイルですので、TOPPERS/ASPの慣習では、(たまたま?)大丈夫そうですが、、、([追記] なお、sil_rew_mem()やsil_wrw_mem()のコードに__evenaccessが無いのは、将来のCC-RXのバージョンアップに対するリスク要因である、ような気がして来ましたが、、、)

    pdic\rx600\rx630_uart.c

    /*
     *  SIOドライバのシリアルモードレジスタ(SMR)
     */
    static void
    rx630_uart_setmode(const SIOPINIB *p_siopinib, uint8_t bitrate, uint8_t clksrc)
    {

        /*
         *  モジュールストップ機能の設定
         */
        sil_wrh_mem((uint16_t *)SYSTEM_PRCR_ADDR, (uint16_t)0xA502);    /* 書込み許可 */
        sil_wrw_mem((uint32_t *)p_siopinib->mstpcrreg,
            sil_rew_mem((uint32_t *)p_siopinib->mstpcrreg) & ~p_siopinib->mstpcr_offset);
        sil_wrh_mem((uint16_t *)SYSTEM_PRCR_ADDR, (uint16_t)0xA500);    /* 書込み禁止 */

    }

    include\sil.h ([追記] これでは呼び出し元の方に__evenaccessが有っても効かないような気がして来ました、、、)

    Inline uint32_t
    sil_rew_mem(const uint32_t *mem)
    {
        uint32_t    data;

        data = *((const volatile uint32_t *) mem); ←ここに__evenaccessが無いのはリスク要因な気が、、、
        return(data);
    }

    Inline void
    sil_wrw_mem(uint32_t *mem, uint32_t data)
    {
        *((volatile uint32_t *) mem) = data; ←ここに__evenaccessが無いのはリスク要因な気が、、、
    }

     

Children
No Data