■経緯について 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モジュール)の確認 ・最適化によるアセンブラコードの違いを確認 ・場合によってはソースコードを修正して対応する ・その他全てのドライバの確認(共通問題の可能性が高い)
何か情報お持ちの方がいましたら教えていただきたく、よろしくお願いいたします。
以上
ふじさん、こんにちは。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 voidrx630_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_tsil_rew_mem(const uint32_t *mem){ uint32_t data; data = *((const volatile uint32_t *) mem); ←ここに__evenaccessが無いのはリスク要因な気が、、、 return(data);}Inline voidsil_wrw_mem(uint32_t *mem, uint32_t data){ *((volatile uint32_t *) mem) = data; ←ここに__evenaccessが無いのはリスク要因な気が、、、}