ColdFire V1 のバス周波数を目で確認する [ColdFire (ColdeFire) V1]
命令実行時間を測定するために、アセンブラでソフトウェア・ループを組み、 LEDを点滅させてみました。
#include/* for EnableInterrupts macro */ #include "derivative.h" /* include peripheral declarations */
プログラムは、全部main関数に押し込んであります。
void main(void) {犬のおまわりさん(COP)を黙らせるためには、HCS08同様にSOPT1レジスタを設定します。 このあたりの勝手は、HCS08と同じなので、今までの経験が役立ちます。
SOPT1 = 0b01010111; // |||| ||+--- RSTPE=1 Enable RST port // |||| |+---- BKGDPE=1 Enable BKGD port // |||| +----- RSTOPE=1 Enable RSTO port // |||+------- WAITE=1 Enable WAIT // ||+-------- STOPE=0 Disable STOP // |+--------- COPT=1 Disable COP // +---------- COPE=0 Disable COPバスクロック周波数を設定する方法もHCS08同様です。 QE128は、DRSというレジスタが追加されて、Digitally Controlled Oscillator (DCO)の 出力周波数倍率が変更できるようになっています。 ここでは、 内部参照クロックを31.25kHzに設定し、 DCO出力を内部参照クロックの1536倍、すなわち48MHzに設定します。 バス・クロック周波数は、その半分の24MHzになるはずです。
// Configure ICS ICSC2_BDIV = 0; // BDIV 1/1 ICSSC_DRST_DRS = 2; // FLL x1536
LEDを点灯させるために、RGPIOという新モジュールを使います。 ここで使用するポートは、RGPIO8(PTC0)のみです。 RGPIOを出力としてイネーブルします。
// Configure RGPIO8=PTC0 as output RGPIO_DIR_DIR8 = 1; RGPIO_ENB_ENB8 = 1;処理本体では、時間稼ぎループをアセンブラで記述しています。 ループ回数は、4,000,000回です。 MCF51QE128のリファレンス・マニュアルによれば、ループ一回で3バス・クロック要するので、 時間稼ぎ部分で12,000,000バスサイクルを消費するはずです。 バス周波数を24MHzに設定すると、0.5秒に相当します。 nopについては、のちほど。
for(;;) { __asm { move.l #4000000,d0 // nop L1: subq #1,d0 // 1(0/0) bne L1 // 2(0/0) backward taken }時間稼ぎが終わったら、RGPIOの出力を反転させます。 0.5秒毎に反転されるので、1秒周期でLEDが点滅します。
// Toggle RGPIO10 RGPIO_TOG = RGPIO_TOG_TOG8_MASK; } /* loop forever */ /* please make sure that you never leave main */ }
これで、1秒周期でLEDが点滅するはずです。 ところが、実際の点滅周期は、2/3秒になってしまいました。 なぜなんだろう。
ループの回数を間違えることはないと思われるので、 ループ当たりのバス・サイクル数が2サイクルになったと推測しました。
色々とやり直した結果、ラベル"L1"のアドレスが、"0-modulo-4"だった場合は、 ループ当たり2バス・サイクルを消費し、 "2-modulo-4"の場合は、3サイクルを消費するらしいことがわかりました。 nopをコメントからはずすと、結果が異なってきます。 えっ?リファレンス・マニュアルが違うの?それとも、シリコン?
まさに、パイプラインのなせる業。 インライン・アセンブラは、".align 4"を入れることが出来ないらしいので、 こういった使い方をする際には、要注意です。
RGPIOを使った理由
RGPIOというのは、簡単に16本のポートの操作を行うありがたい仕掛けなのですが、 これを使ったのには理由があります。 この解に至るまでにHCS08で良く使われる以下のような構文を試してみました。
- PTCD_PTCD0 = !PTCD_PTCD0;
- PTCD_PTCD0 = ~PTCD_PTCD0;
- PTCD ^= PTCD_PTCD0_MASK;
ところが、こいつらが見るに耐えない冗長なコードを出力してしまったので、 RGPIOの登場となったしだいです。 どんな、冗長なコードができたかは、ぜひ、ご自身でお試しください。
> 犬のおまわりさん(COP)を黙らせるためには、HCS08同様に
> SOPT1レジスタを設定します。このあたりの勝手は、HCS08と
> 同じなので、今までの経験が役立ちます。
TPMもHCS08の経験がそのまま、と言うか処理そのものを流用できるので、HCS08からの移行組みは楽できますね。
うん、コントローラコンティナムだ!。
by hamayan (2008-01-18 06:59)