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
  • 反応ありがとうございます。
    コンパイル結果のコードを貼り付けさせていただきます。
    私はアセンブラコード不慣れなのでマニュアル見ながら細かく確認
    していこうと考えていました。

    ■対象関数(例として1つ)
    \hw\r_usb_hreg_access.c
    -----------------------------------------------------------------
    L.55 void hw_usb_hset_rwupe (usb_utr_t *ptr, uint16_t port)
    L.56 {
    L.57 if (USB_PORT0 == port)
    L.58 {
    L.59 ptr->ipp->DVSTCTR0.WORD |= USB_RWUPE;
    L.60 }
    L.61 }
    -----------------------------------------------------------------

    \r_bsp\mcu\rx71m\register_access\iodefine.h
    -----------------------------------------------------------------
    struct st_usb0 {
    ...(省略)
    union {
    unsigned short WORD;
    } DVSTCTR0;
    ...(省略)
    };

    #define USB0 (*(volatile struct st_usb0 __evenaccess *)0xA0000)
    -----------------------------------------------------------------

    ■CS+6(V6.01.00)/ビルドツールCC-RX V2.08.00】
     最適化なし:
      _hw_usb_hset_rwupe:
    .STACK _hw_usb_hset_rwupe=12
    .LINE "...\hw\r_usb_hreg_access.c",55
    SUB #08H, R0
    MOV.L R1, 04H[R0]
    MOV.W R2, 02H[R0]
    .LINE "...\hw\r_usb_hreg_access.c",59
    MOV.L 04H[R0], R1
    MOV.L 08H[R1], R1
    MOV.W 08H[R1], R2
    BSET #07H, R2
    MOV.W R2, 08H[R1]
    RTSD #08H

     最適化レベル1:
      _hw_usb_hset_rwupe:
    .STACK _hw_usb_hset_rwupe=4
    .LINE "...\hw\r_usb_hreg_access.c",55
    MOV.L 08H[R1], R1
    .LINE "...\hw\r_usb_hreg_access.c",59
    MOV.W 08H[R1], R2
    BSET #07H, R2
    MOV.W R2, 08H[R1]
    RTS

     最適化レベル2:
      _hw_usb_hset_rwupe:
    .STACK _hw_usb_hset_rwupe=4
    .LINE "...\hw\r_usb_hreg_access.c",55
    MOV.L 08H[R1], R1
    MOV.L #00000080H, R2
    .LINE "...\hw\r_usb_hreg_access.c",59
    OR 08H[R1].UB, R2
    MOV.B R2, 08H[R1]
    RTS

    ■CS+4(V4.00.00)/ビルドツールCC-RX V2.05.00】
     最適化レベル2:
      _hw_usb_hset_rwupe:
    .STACK _hw_usb_hset_rwupe=4
    .LINE "...\hw\r_usb_hreg_access.c",55
    CMP #00H, R2
    BNE L12
      L11: ; if_then_bb
    .LINE "...\hw\r_usb_hreg_access.c",59
    MOV.L 08H[R1], R1
    MOV.W 08H[R1], R2
    BSET #07H, R2
    MOV.W R2, 08H[R1]
      L12: ; return
    .LINE "...\hw\r_usb_hreg_access.c",61
    RTS

    ■考察
     CS+6の最適化レベル2だけがBSET命令を使わないコードになっているようで、
     代わりにMOV.Bとなっており、バイトアクセスしている模様(?)

    ■今後について
     アセンブラに不慣れなため、マニュアル見ながら詳しく確認してみたいと思います。
     また、対象のレジスタについてもハードウェアマニュアルなどで再確認してみたいと
     思います。

    引き続きご協力お願いできれば幸いです。
    以上
  • こんにちは

    CC-RXにおけるビット操作命令の生成についてV2.06.00で仕様変更がされていたようです。

    【リビジョンアップ】RXファミリ用C/C++コンパイラパッケージ V2.06.00

    ⇒ 2.7 その他改善

      (1) ビット操作命令の出力

    もしかしてマニュアルのビット操作命令出力の条件に合致したりしてないでしょうか。

    CC-RX コンパイラ ユーザーズマニュアル

    ⇒ 11.5.4 V2.06 以降【V2.05 以前からの変更点】

      (1) ビット操作命令の出力を制御する方法の導入

  • わわい様ありがとうございます。V2.06.00の仕様変更「(1) ビット操作命令の出力を制御する方法の導入」の影響は間違いなさそうです。ビット操作命令出力の条件に合致しており、最適化しているためコンパイラ判断によるものとなっていました。
    とはいえ、evenaccessを指定しているにもかかわらずバイトアクセスになってしまっているのはコンパイラのバグのように思えます。
  • 先ほどの返信、じま様宛てでした。。。失礼しました。
    じま様わわい様ありがとうございます。引き続きお付き合いいただけたら幸いです。
  • FITのUSBドライバのレジスタ制御部分は多くの場所でNGでした。暫定対策としては最適化レベルを2ではなく1にしておこうと思います。
    本件、コンパイラのバグの可能性が高いと思うのですが、この投稿内容はルネサスの開発担当者の方に伝わるものでしょうか?

    今後の進展度合いによってはCS+6の利用は控えて、安定動作できているCS+4のまま開発を進めることも検討しようかと、正直悩んでいるところです。CS+6を利用する場合、すべてのドライバの動作実績や信頼性も白紙に戻ってしまうので、評価しなおす覚悟をしなければ。。。
  • こんにちは

    Renesas社員も本サイトを参照はされていますが、公式見解をここで発表することは無いと考えられます。製品開発に関わる問題であればRenesasの正規問合せ窓口へ連絡して正式回答をもらっておくのが良いと思います。
    開発環境・開発ツールの技術に関するお問合せ
    support.renesas.com/.../new
  • ふじさん

    こんにちは、シェルティです。ルネサス社員です。

    本件ご不便をおかけしております。
    コンパイラチーム、USBチームに報告しました。
    じまさんも仰っている通りなのですが、特に量産製品の開発をされている場合は、
    弊社営業や特約店にご連絡いただくか、問い合わせ窓口に連絡するのが良いです。
    本サイトにおいてはRXマイコンに関しては私が可能な限り拾い上げて関係者に連絡しておりますが
    本来業務の外側での対応となりますので、限界があります。

    私見ですが、ご教示いただいた条件以外に何かが潜んでいると思われます。
    私の環境(CC-RX V207、最適化2)では不再現でした。
    特定コンパイルオプションの条件下において不正なコードが出力されるといったところで、
    USBドライバ自体には問題がないように感じました。
    各リストファイル(*.lst)の先頭の方にCOMMAND PARAMETERというのが出力されていて、
    -isa=rxv2 のようにコンパイルオプションが列挙されていると思います。
    書き出していただけますか?

    以上です
  • シェルティさん、こんにちは。NoMaYです。(私のPCのCPUが古過ぎてCC-RX V2.04以降が使えず回りくどいレスですが)

    >私の環境(CC-RX V207、最適化2)では不再現でした。
    >特定コンパイルオプションの条件下において不正なコードが出力されるといったところで、
    >USBドライバ自体には問題がないように感じました。
    この部分は、私だけでなくて、ふじさんも気になる文面かと思いますが、
    生成されたコードは、ふじさんのNGコードの方では無くてOKコードの方だった、
    ということでしょうか?

    ふじさんのNGコード ≠ シェルティさんがCC-RX V2.07 最適化2で試された結果

    ■CS+6(V6.01.00)/ビルドツールCC-RX V2.08.00】
     最適化レベル2:
    省略(by NoMaY))
    MOV.L #00000080H, R2
    OR 08H[R1].UB, R2 ← 皆さんが仰る通り unsigned short かつ __evenaccess のI/Oレジスタ対するコードとしては変ですね
    MOV.B R2, 08H[R1] ← 皆さんが仰る通り unsigned short かつ __evenaccess のI/Oレジスタ対するコードとしては変ですね

    (参) 4.2.5 キーワードの使用方法 - CS+ V6.01.00 > コンパイラ編 > コンパイラ言語仕様 > 拡張言語仕様 > キーワードの使用方法
    (1)指定サイズのアクセス記述
    tool-support.renesas.com/autoupdate/support/onlinehelp/ja-JP/csp/V6.01.00/CS+.chm/Compiler-CCRX.chm/Output/ccrx04c0205y.html

    __evenaccess <型指定子> <変数名>
    <型指定子> __evenaccess <変数名>

    宣言または定義したサイズで変数をアクセスします。
    変数の型のサイズでアクセスすることを保証します。


    ふじさんのOKコード(以下の3つは同じ) = シェルティさんがCC-RX V2.07 最適化2で試された結果

    ■CS+6(V6.01.00)/ビルドツールCC-RX V2.08.00】

     最適化なし:
    省略(by NoMaY))
    MOV.W 08H[R1], R2
    BSET #07H, R2
    MOV.W R2, 08H[R1]

     最適化レベル1:
    省略(by NoMaY))
    MOV.W 08H[R1], R2
    BSET #07H, R2
    MOV.W R2, 08H[R1]

    もしくは

    ■CS+4(V4.00.00)/ビルドツールCC-RX V2.05.00】

     最適化レベル2:
    省略(by NoMaY))
    MOV.W 08H[R1], R2
    BSET #07H, R2
    MOV.W R2, 08H[R1]

    あと、細かいところですが、ふじさんとじまさんの以下の文面はアセンブラに不慣れゆえの書き間違いかな、と思われます。以下の(a)と(b)に合致していませんので。

    11.5.4 V2.06以降【V2.05以前からの変更点】 - CS+ V6.01.00 > コンパイラ編 > 注意事項 > 旧バージョン・旧リビジョンとの互換性
    (1)ビット操作命令の出力を制御する方法の導入
    tool-support.renesas.com/autoupdate/support/onlinehelp/ja-JP/csp/V6.01.00/CS+.chm/Compiler-CCRX.chm/Output/ccrx11c0504y.html

    組み込み関数を使用せずに、コンパイラにビット操作命令を必ず出力させる場合は、
    次の条件をすべて満たすソース・プログラムを記述してください。
    (a) 定数値を代入する
    (b) 代入先を1バイト型で1ビット幅のビットフィールドにする
    (c) 代入先をvolatile 修飾する


    ふじさん

    >ビット操作命令出力の条件に合致しており、最適化しているためコンパイラ判断によるものとなっていました。
    ↓(むしろ以下の文面かと思われます)
    ビット操作命令出力の条件に合致しておりおらず、最適化しているためコンパイラ判断によるものとなっていました。

    じまさん

    >もしかしてマニュアルのビット操作命令出力の条件に合致したりしてないでしょうか。
    ↓(むしろ以下の文面かと思われます)
    もしかしてマニュアルのビット操作命令出力の条件に合致したり合致していなかったりしてないでしょうか。

Reply
  • シェルティさん、こんにちは。NoMaYです。(私のPCのCPUが古過ぎてCC-RX V2.04以降が使えず回りくどいレスですが)

    >私の環境(CC-RX V207、最適化2)では不再現でした。
    >特定コンパイルオプションの条件下において不正なコードが出力されるといったところで、
    >USBドライバ自体には問題がないように感じました。
    この部分は、私だけでなくて、ふじさんも気になる文面かと思いますが、
    生成されたコードは、ふじさんのNGコードの方では無くてOKコードの方だった、
    ということでしょうか?

    ふじさんのNGコード ≠ シェルティさんがCC-RX V2.07 最適化2で試された結果

    ■CS+6(V6.01.00)/ビルドツールCC-RX V2.08.00】
     最適化レベル2:
    省略(by NoMaY))
    MOV.L #00000080H, R2
    OR 08H[R1].UB, R2 ← 皆さんが仰る通り unsigned short かつ __evenaccess のI/Oレジスタ対するコードとしては変ですね
    MOV.B R2, 08H[R1] ← 皆さんが仰る通り unsigned short かつ __evenaccess のI/Oレジスタ対するコードとしては変ですね

    (参) 4.2.5 キーワードの使用方法 - CS+ V6.01.00 > コンパイラ編 > コンパイラ言語仕様 > 拡張言語仕様 > キーワードの使用方法
    (1)指定サイズのアクセス記述
    tool-support.renesas.com/autoupdate/support/onlinehelp/ja-JP/csp/V6.01.00/CS+.chm/Compiler-CCRX.chm/Output/ccrx04c0205y.html

    __evenaccess <型指定子> <変数名>
    <型指定子> __evenaccess <変数名>

    宣言または定義したサイズで変数をアクセスします。
    変数の型のサイズでアクセスすることを保証します。


    ふじさんのOKコード(以下の3つは同じ) = シェルティさんがCC-RX V2.07 最適化2で試された結果

    ■CS+6(V6.01.00)/ビルドツールCC-RX V2.08.00】

     最適化なし:
    省略(by NoMaY))
    MOV.W 08H[R1], R2
    BSET #07H, R2
    MOV.W R2, 08H[R1]

     最適化レベル1:
    省略(by NoMaY))
    MOV.W 08H[R1], R2
    BSET #07H, R2
    MOV.W R2, 08H[R1]

    もしくは

    ■CS+4(V4.00.00)/ビルドツールCC-RX V2.05.00】

     最適化レベル2:
    省略(by NoMaY))
    MOV.W 08H[R1], R2
    BSET #07H, R2
    MOV.W R2, 08H[R1]

    あと、細かいところですが、ふじさんとじまさんの以下の文面はアセンブラに不慣れゆえの書き間違いかな、と思われます。以下の(a)と(b)に合致していませんので。

    11.5.4 V2.06以降【V2.05以前からの変更点】 - CS+ V6.01.00 > コンパイラ編 > 注意事項 > 旧バージョン・旧リビジョンとの互換性
    (1)ビット操作命令の出力を制御する方法の導入
    tool-support.renesas.com/autoupdate/support/onlinehelp/ja-JP/csp/V6.01.00/CS+.chm/Compiler-CCRX.chm/Output/ccrx11c0504y.html

    組み込み関数を使用せずに、コンパイラにビット操作命令を必ず出力させる場合は、
    次の条件をすべて満たすソース・プログラムを記述してください。
    (a) 定数値を代入する
    (b) 代入先を1バイト型で1ビット幅のビットフィールドにする
    (c) 代入先をvolatile 修飾する


    ふじさん

    >ビット操作命令出力の条件に合致しており、最適化しているためコンパイラ判断によるものとなっていました。
    ↓(むしろ以下の文面かと思われます)
    ビット操作命令出力の条件に合致しておりおらず、最適化しているためコンパイラ判断によるものとなっていました。

    じまさん

    >もしかしてマニュアルのビット操作命令出力の条件に合致したりしてないでしょうか。
    ↓(むしろ以下の文面かと思われます)
    もしかしてマニュアルのビット操作命令出力の条件に合致したり合致していなかったりしてないでしょうか。

Children
  • こんにちは。NoMaYです。

    >OR 08H[R1].UB, R2 ← 皆さんが仰る通り unsigned short かつ __evenaccess のI/Oレジスタ対するコードとしては変ですね
    >MOV.B R2, 08H[R1] ← 皆さんが仰る通り unsigned short かつ __evenaccess のI/Oレジスタ対するコードとしては変ですね

    ちょっと待った! >> 自分
    変なのかな?

    r_ usb_basic_if.h

    typedef volatile struct st_usb0 * usb_regadr_t; ← ここに _evenaccess が無いですよね?

    typedef struct usb_utr      usb_utr_t;
    typedef void (*usb_cb_t)(struct usb_utr *, uint16_t, uint16_t);

    typedef struct usb_utr
    {
        usb_mh_t    msghead;        /* Message header (for SH-solution) */
        uint16_t    msginfo;        /* Message Info for F/W */
        uint16_t    keyword;        /* Rootport / Device address / Pipe number */
        union
        {
            usb_regadr_t    ipp;    /* USB module startAddress(USB0/USB1)*/
        #if USB_NUM_USBIP == 2
            usb_regadr1_t   ipp1;   /* USB module start address(USBA) */
        #endif /* USB_NUM_USBIP == 2 */
        };
        uint16_t    ip;             /* USB module number(0 or 1) */
        uint16_t    result;         /* Result */
        usb_cb_t    complete;       /* Call Back Function Info */
        void        *p_tranadr;     /* Transfer data Start address */
        uint32_t    tranlen;        /* Transfer data length */
        uint16_t    *p_setup;       /* Setup packet(for control only) */
        uint16_t    status;         /* Status */
        uint16_t    pipectr;        /* Pipe control register */
        uint8_t     errcnt;         /* Error count */
        uint8_t     segment;        /* Last flag */
        void        *p_usr_data;
    } usb_message_t;

    iodefine.h

    struct st_usb0 { ← ここにはコンパイラの仕様上 _evenaccess を記述出来ません
    ...
        union {
            unsigned short WORD;
    //      struct {
    //          unsigned short :4;
    //          unsigned short HNPBTOA:1;
    //          unsigned short EXICEN:1;
    //          unsigned short VBUSEN:1;
    //          unsigned short WKUP:1;
    //          unsigned short RWUPE:1;
    //          unsigned short USBRST:1;
    //          unsigned short RESUME:1;
    //          unsigned short UACT:1;
    //          unsigned short :1;
    //          unsigned short RHST:3;
    //      } BIT;
        } DVSTCTR0;
    ...
    };

    #define USB0        (*(volatile struct st_usb0     __evenaccess *)0xA0000) ← ここに _evenaccess が付いてますよね?

     

  • こんにちは。NoMaYです。

    分かった、、、(少なくとも)最新のUSBドライバのソースでは変更されてますね、、、

    r_usb_typedef.h

    typedef volatile struct st_usb0 __evenaccess * usb_regadr_t; ← ここに _evenaccess が付いてますね!

    typedef struct usb_utr      usb_utr_t;
    typedef void (*usb_cb_t)(struct usb_utr *, uint16_t, uint16_t);


    typedef struct usb_utr
    {
        usb_mh_t    msghead;        /* Message header (for SH-solution) */
        uint16_t    msginfo;        /* Message Info for F/W */
        uint16_t    keyword;        /* Root port / Device address / Pipe number */
        union
        {
            usb_regadr_t    ipp;    /* USB module startAddress(USB0/USB1)*/
        #if USB_NUM_USBIP == 2
            usb_regadr1_t   ipp1;   /* USB module start address(USBA) */
        #endif /* USB_NUM_USBIP == 2 */
        };
        uint16_t    ip;             /* USB module number(0 or 1) */
        uint16_t    result;         /* Result */
        usb_cb_t    complete;       /* Call Back Function Info */
        void        *p_tranadr;     /* Transfer data Start address */
        uint32_t    tranlen;        /* Transfer data length */
        uint16_t    *p_setup;       /* Setup packet(for control only) */
        uint16_t    status;         /* Status */
        uint16_t    pipectr;        /* Pipe control register */
        uint8_t     errcnt;         /* Error count */
        uint8_t     segment;        /* Last flag */
        void        *p_usr_data;
    } usb_message_t;

     

  • NoMaYさん

    こんにちは、シェルティです。

    >生成されたコードは、ふじさんのNGコードの方では無くてOKコードの方だった、
    >ということでしょうか?

    はい、そうです。
    私が動作確認に使ったコードはスマートコンフィグレータが出力したコードですね。
    RX Driver Packageの最新版(V114)に入っているものです。
    st_usb0 を見てみたら、__evenaccessが付いてました。

    解析ありがとうございます。答えにたどり着けて良かったです。

    以上です
  • ご協力ありがとうございます。最新ソースで対処されている可能性については最初から想定してはいたのですが調査が早く進み非常に助かります。
    とはいえ、すべての古いドライバに対してはもうそのままでは使えない可能性があるとなったいま、コンパイラの最適化を調整するしかなく、コンパイラとしてそれで良いのか疑問は感じます。

    現在、お客さまの技術アドバイザ的な立場で開発に携わっている事情もあり、すでに安定動作できているCS+4で作ったFW、ついでにいうとiTRON向けにドライバの改造や性能チューニングを要所要所で施しているため、最新FITへの置き換えやCS+6への移行はリスクが大きく、引き続きしっかり検討してみます。
    トライしてみようとは考えていますので、また何かあればご報告させていただきます。