始めまして、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
0xfff80063
0xfff80064
0xfff80065
0xfff80066
0xfff80067
0xfff80068
0xfff80069
0xfff8006a
0xfff8006b
0xfff8006c
0xfff8006d
0xfff8006e
0xfff8006f
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. 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
BEQ.B
_delay_msec+12H
1(分岐不成立時) or 3(分岐成立時)
#1F91H,R15
_delay_msec+AH
SUB
#1H,R15
BNE.B
ADD
#1H,R14
BRA.B
_delay_msec+2H
_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 )のアドレス
備考
fff8 0080H
fff8 0082H
346 nsec
fff8 0081H
fff8 0083H
fff8 0084H
fff8 0085H
376 nsec
*
fff8 0086H
fff8 0087H
fff8 0088H
fff8 0089H
fff8 008aH
fff8 008bH
fff8 008cH
fff8 008dH
fff8 008eH
fff8 008fH
fff8 0090H
fff8 0091H
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