RX-130 ターゲットボード の高速オンチップオシレータ HOCO(32MHz)での動作

始めまして、ABCと申します。

RX-130のターゲットボードを買いました。CS + CC評価版(V8.03)を使用して、

プログラムを作成し、デバック・ツールをE2 Liteでダウンロードして実行できました。

作成したプログラムは、whileループで待ち時間を作り、ポートをON / OFFするプログラムです。

最初に、ON時間を200msec、OFF時間を300msecのプログラムを作成しました。

オシロで確認すると、プログラム通りの波形が得られました。

 

Fig. ON = 200msec OFF = 300msecのプログラム 

 

Fig. 200msec ON、300msec OFFの波形

 

 

次に、ON時間を300msec、OFF時間を200msecのプログラムを作成しました。

 

Fig. ON = 300msec OFF = 200msecのプログラム 

 

オシロで確認すると、300msecが378msec、 200msecが254msecとなっていました。

Fig. ON = 300msec OFF = 200msecのプログラムの波形 (ON時間、OFF時間がプログラム通りでない。)

 

動作クロックは、高速オンチップオシレータHOCO(32MHz)使用しています。

また、プログラムの作成に、コンフィギュレータ等は使用していません。

以下は、リセット解除後に、実行される処理です。

 

 

 

 

 

プロジェクトを添付しました。

正常:test_200_300_RX130_OK.zip

異常:test_300_200_RX130.zip

 3000.test2_200_300_RX130_OK.zip 

2630.test2_300_200_RX130.zip

 

 

レジスタへの設定不足や、ボード固有の問題でしょうか。どなたか、再現テストをして頂けると助かります。

よろしくお願いします。

  • ソフトディレイはそんな感じだと思います。ループ回数を納得いくまで調整する。
    精度が欲しいならタイマを使うのが良いかと思います。
  • 時間待ちにはタイマを使うことをお勧めします。ソフトで空ループで実装されるのであれば、アセンブラを使用してループとなる箇所のアライメントまで保証されるようコーディングすべきです。
    命令フェッチの仕組みにより空ループでの分岐先のアライメントは処理時間に影響が生ずる可能性がありますが、コンパイラにより生成されたコードではその点を保証することは困難です。
  • お世話になります。ABCです。

    コメントありがとうございました。

     2つのプログラムの違いを調べてみました。

    よく見ると関数 delay_msec()の開始アドレスが、

    正常の場合、0xfff8 05a4

    異常の場合、0xfff8 05a5 から開始されていました。

    そこで、アドレスにより、処理時間に差がでるのか調べました。

    方法は、関数 delay_msec()用に、#pragma sectionで新しいセクションに変更し、

    リンク・オプションのセクションで、新しいセクションの開始アドレスを指定します。

            

     

     Fig. #pragma sectionで新しいセクションに変更。       Fig.  delay_msec()用のセクションの開始アドレスを指定

     

    ・開始アドレスを変更してテスト

    今回は、ON時間=1msec, OFF時間=2msecとしています。

    結果:

    delay_msecの開始アドレス

    ON時間

    OFF時間

    0xfff80060

    1msec

    2msec

    0xfff80061

    1.26 msec

    2.54msec

    0xfff80062

    1msec

    2msec

    0xfff80063

    1msec

    2msec

    0xfff80064

    1msec

    2msec

    0xfff80065

    1.26 msec

    2.54msec

    0xfff80066

    1msec

    2msec

    0xfff80067

    1msec

    2msec

    0xfff80068

    1msec

    2msec

    0xfff80069

    1.26 msec

    2.54msec

    0xfff8006a

    1msec

    2msec

    0xfff8006b

    1msec

    2msec

    0xfff8006c

    1msec

    2msec

    0xfff8006d

    1.26 msec

    2.54msec

    0xfff8006e

    1msec

    2msec

    0xfff8006f

    1msec

    2msec

      Fig.  開始アドレスと、ON/OFF時間の関係

    delay_msecの開始アドレスを、0xfff80061、0xfff80065、0xfff80069、0xfff8006dとした場合、ON時間が1.26msecとなっていました。

     

             

     Fig. delay_msecの開始アドレスを 0xfff80060としたプログラム

     

      Fig.  逆アセンブル表示

     

     Fig. delay_msecの開始アドレスを 0xfff80060とした時の波形。 (ON=1msec, OFF=2msec)

     

     Fig. delay_msecの開始アドレスを 0xfff80061したプログラム

    Fig.  逆アセンブル表示

     Fig. delay_msecの開始アドレスを 0xfff80061とした時の波形。 (ON=1.26msec, OFF=2.54msec)

     

    ・処理時間を計算してみる

    関数 delay_msec()の処理時間を求めるためには、サイクル数をカウントすれば良いそうです。

    (「RX130グループ ユーザーズマニュアル ハードウェア編」 (Rev 3.00)の

    2.8 パイプライン、2.8.3 命令処理時間の計算方法)

     このマニュアルを見ると、MOV.L #0H,R14 (転送命令 レジスタ間、即値-レジスタ)は、サイクル数 1となっていました。

    この命令の場合、フェッチ、デコード、実行、ライトバック(結果反映)の4サイクルかかるようですが、

    パイプラインがあるので、1サイクルなのでしょう。

        

     

     

    各命令のサイクル数です。

    label

    オペレーション

    オペランド

    サイクル数

    _delay_msec:

    MOV.L

    #0,R14

    1

    _delay_msec + 2

    CMP

    R1,R14

    1

     

    BEQ.B

    _delay_msec+12H

    1(分岐不成立時) or 3(分岐成立時)

     

    MOV.L

    #1F91H,R15

    1

    _delay_msec+AH

    SUB

    #1H,R15

    1

     

    BNE.B

    _delay_msec+AH

    1(分岐不成立時) or 3(分岐成立時)

     

    ADD

    #1H,R14

    1

     

    BRA.B

    _delay_msec+2H

    1(分岐不成立時) or 3(分岐成立時)

    _delay_msec + 12H

    RTS

     

    5

     

    delay_msec(1) の場合のサイクル数を求めます。

    (Cよりdelay_msec(1)が呼ばれると、引数 は、 R1に格納されます。)

    R1=1の場合の、総サイクル数は、

     1+1+1 +1+ (1+3)*8080 + (1+1) + 1 +3 + 1 + 3 +5 = 32339 cycle

     1cycleは、1/32 [usec](ICLK=32MHz)ですので、

     関数 delay_msec(1)の 実行時間 = 32339*1/32 [usec]   約 1.01msecとなり、実測値と一致します。

    delay_msecの開始アドレスを、0xfff80061とした場合、1.26msecとなるのは、

    配置アドレスによっては、サイクル数の計算通りには実行されないようです。

     

    ・分岐先の命令実行向け整合を行う関数の指定

    「CC-RX コンパイラ ユーザーズマニュアル」を見ていると、

    #4.2.3 pragma 指令 (14) 分岐先4 バイト整合指定

    #pragma instalign4 という指定がありました。

    また、ルネサス半導体セミナー「コンパイラコース」のテキストの3.6 

    分岐先の命令実行整合の例がありました。

    試しに、

    #pragma instalign4 delay_msec( inmostloop ) としました。

     Fig. #pragma 分岐先4 バイト整合 を入れる

     Fig 関数の開始アドレス指定

     

     Fig #pragma instalign4 delay_msec( inmostloop )により、0xfff8 0064から開始。

     

       Fig 波形。 (ON=1msec, OFF=2msec)

    関数は、0xFFF8 0064から割り付き、1msec ONとなりました。

     

    今回わかった事は、

      コンパイルすると、分岐命令で、アドレスにより期待した処理時間とならない場合がある。

      #pragma instalign4 関数名 (option) とすれば、回避できる。

     

    以上で、解決しました。どうもありがとうございました。

     

     

    補足:使用したプロジェクトを添付します。
    セクション指定による関数の先頭アドレス指定:

    2330.test2_RX130_0.zip

     


    #pragma instalign4 追加版:

    6232.test2_RX130_0_pragma_instalign4.zip

  • > 以上で、解決しました。どうもありがとうございました。

    コードを見ると最内ループの分岐アドレスが 4 の整数倍に整列されておらず、解決していない気がします。

    コンパイラのコード生成の設定やバージョンアップで将来にわたり同一のコードが生成されるとも限らないのでこの手の処理はタイマーを使わないのであればアセンブラで記述することをお勧めします。

  • ご指摘ありがとうございました。ABCです。

    分岐先アドレスと処理時間について、さらに調べてみました。

     分岐先アドレスを指定するため、アセンブラで記述し、開始アドレスをORGで定義しています。

    アセンブラの中では、ループせずに分岐先と分岐元のアドレスだけを変化させました。

    Fig   Cのプログラム (アセンブラの関数 branch_test)を読み出す。

       Fig アセンブラの関数 (C側からR1=1が渡され、ループせず リターン)

     

    分岐先が、fff8 0080Hの場合、ON時間は、346nsecでした。

    分岐先が、fff8 0083Hの場合、ON時間は、376nsecでした。

     Fig 分岐先が、fff8 0080Hの場合 ( 346 nsec)

     

      Fig 分岐先が、fff8 0083Hの場合 ( 376 nsec)

     

    分岐先を fff8 0080Hから fff8 008fまで変化させた結果です。

    分岐先(SUB #1,R1)のアドレス

    分岐元(BNE.B )のアドレス

    ON時間

    備考

    fff8 0080H

    fff8 0082H

    346 nsec

     

    fff8 0081H

    fff8 0083H

    346 nsec

     

    fff8 0082H

    fff8 0084H

    346 nsec

     

    fff8 0083H

    fff8 0085H

    376 nsec

    *

    fff8 0084H

    fff8 0086H

    346 nsec

     

    fff8 0085H

    fff8 0087H

    346 nsec

     

    fff8 0086H

    fff8 0088H

    346 nsec

     

    fff8 0087H

    fff8 0089H

    376 nsec

    *

    fff8 0088H

    fff8 008aH

    346 nsec

     

    fff8 0089H

    fff8 008bH

    346 nsec

     

    fff8 008aH

    fff8 008cH

    346 nsec

     

    fff8 008bH

    fff8 008dH

    376 nsec

    *

    fff8 008cH

    fff8 008eH

    346 nsec

     

    fff8 008dH

    fff8 008fH

    346 nsec

     

    fff8 008eH

    fff8 0090H

    346 nsec

     

    fff8 008fH

    fff8 0091H

    376 nsec

    *

       Fig 分岐先、分岐元のアドレスと、ON時間の関係

     *の場合に、1サイクル ( 1/32 [usec], ICLK=32MHz)分、余計にかかるようです。

     分岐先と分岐元のアドレスを見やすくすると、

      Fig  分岐アドレスの条件 (矢印の分岐で1サイクル余計に発生)

     

    「CC-RX コンパイラ ユーザーズマニュアル」の、2.5.1 コンパイル・オプション オブジェクトオプション

    -instalign4 を見ると、「分岐先の命令が、アライメント数(4)の倍数であるアドレスをまたいでいる場合に整合をとる」と書かれていました。

    上記のアセンブラで、余計にかかっているのは、まさに4の倍数のアドレス(fff8 0084H,fff8 0088H, fff8 008cH,fff8 0090H)を、またいでいる場合でした。

     

    #pragma instalign4 delay_msec( inmostloop ) についても確認してみました。

      C側からnop(); を入れて、while(delay--)のアドレスを調整しています。

     #pragma instalign4 が無い場合

     

     Fig  読みだし側のメインプログラム

     

       Fig DelayMsecの開始アドレス割り付け

     

     Fig  待ち関数 (instalign4 なし)

     

      Fig  待ち関数 (instalign4 なし)の逆アセンブル表示

    Fig  待ち関数 (instalign4 なし)の場合の波形 (1.26 msec ON)

      (4の倍数のアドレスをまたいで分岐しているので、1msecとなりません。)

     

    ・#pragma instalign4 delay_msec( inmostloop )をいれた場合

     Fig  待ち関数 (instalign4 あり)

     

     Fig  待ち関数 (instalign4 あり)の逆アセンブル表示

    Fig  待ち関数 (instalign4 あり)の場合の波形 (1.0 msec ON)

     (コンパイラで、nopが入り、4の倍数のアドレスをまたいで分岐していません)

     

    このCPU(RX-130)では、4の倍数のアドレスをはさんで分岐すると、1サイクル分、余計にかかるので、

    1サイクルが無視できない場合は、instalignで調整するようです。

     

    使用したプロジェクトです。

     

    分岐先のテスト用(アセンブラ含む):

    test2_RX130_asm1.zip

     

    instalign のテスト用:

    test2_RX130_nop_pragma_instalign4.zip

     

    また、アセンブラの作成には、本フォーラムの「rxマイコンのアセンブラについて」を参考にさせて頂きました。

    どうもありがとうございました。

     

     追記:2020年7月22日

    上記のプログラムですが、delay_msec(1); で 1.01 msec待ちとなっていました。ループ回数を7995とすれば、1.00msc待ちになります。

     

       

     

               Fig ループ回数を修正版                      Fig 1.00msec の波形

     

    修正版サンプルプログラム:

    wait_1_00msec.zip