« RX-DIPの基板が出来上がった! | トップページ | EZ-USB FX3のI2C ROMにアクセス »

2013.02.11

EZ-USB FX3のGPIOを高速化する

EZ-USB FX3のデータバスや様々な端子はGPIOとして使えるわけなのですが、このGPIOの実力はどの程度でしょうか?

Gpio_test

FX3のGPIOにはSimpleモードとComplexモードというのがあるようで、単純なGPIOとして使うにはSimpleモードにします。

まずCyU3PGpioSetSimpleConfig()関数を使ってそのモードを設定します。

CyU3PGpioSimpleConfig_t gpioConfig;
gpioConfig.outValue = CyFalse;
gpioConfig.driveLowEn = CyTrue;
gpioConfig.driveHighEn = CyTrue;
gpioConfig.inputEn = CyFalse;
gpioConfig.intrMode = CY_U3P_GPIO_NO_INTR;
CyU3PGpioSetSimpleConfig(ポート番号, &gpioConfig);

こんな感じで、そのポートのドライバの有効無効や、入力の有効無効、割り込みの有無などを設定します。ポート番号は0~56です。

そうしたら、

CyU3PGpioSimpleSetValue (ポート番号, CyTrue);

CyU3PGpioSimpleSetValue (ポート番号, CyFalse);

で1→0が出力されます。

ただ、この方法だと遅いのです。GPIOのシンプルなポート出力用APIにはCyU3PGpioSetValue()とCyU3PGpioSimpleSetValue()という関数がありますが、どちらも遅い

実際にやってみた波形をご覧ください。これはCyU3PGpioSimpleSetValue()をwhile文のループでぐるぐる回したときの波形です。

Gpio_simple

なんと、CyU3PGpioSimpleSetValue()の中で1.3μ秒も費やしているのです。だから、このAPIを使ってカチカチやると、340kHzくらいまでしか出ません。CyU3PGpioSetValue()なんて使った日には240kHzまでしか出ませんでした。

遅い、とにかく遅すぎる。

そういうわけで、このAPIの中身を解析したのが、前回の記事http://nahitafu.cocolog-nifty.com/nahitafu/2012/03/ez-usb-fx3gpio-.htmlでした。

前回の記事ではAPIの中身を逆アセンブルして晒していたわけですが、[0xe0001100 + 4*GPIO番号]番地が、GPIOのポートのアドレスだろうと推測していました。

では、直接、0xe00011000番地に出力したい値を書き込んでやりましょう。最初に考えたのがこんなプログラム。これをGpioOutputThread_Entry()の中に書いてやります。

unsigned long *d = (unsigned long *)0xe0001100;
while(1){
  *d = 0x1;
  *d = 0x0;
}

しかし、これはダメでした。ポートから何も出てきません。最下位ビットが出力値なのでしょうが、上のほうのビットもいろいろ使われているようなのです。そこで、1ビットずつつぶさに機能を調べました。

その結果、わかってきたのは、

  • bit0 outValue;
  • bit4 driveLowEn;
  • bit5 driveHighEn
  • bit6 速度が下がる?
  • bit7 速度が下がる?
  • bit28 常に0にすること
  • bit31 常に1にすること

という関係です。

*d = 0x800000f1;
*d = 0x800000f0;

にしてループを回すと、

Gpio_direct

やった!3.2MHz出た。API経由で叩いていたときの10倍の速度です。

面白いのはbit4とbit5。どうやらFX3の出力ドライバは、上側と下側で別々にイネーブルできるようです。だから、これを片方だけ0にすると、

Gpio_upper_2

こんないびつな波形が出るようになります。

謎なのはbit6とbit7。これを0にするとさらに速くなります。だいたい180nsで1周期なので5MHz超の速度が出ます。ちょっと立下りが「ぶれ」ていますが、約10nsの「ぶれ」がありました。この10nsの「ぶれ」はおそらくシステムクロック416MHzの4分の1ではないかと思います。

Gpio_fastest

やっていいのか悪いのかはわかりませんが、結論を言うと、

  • 直接I/Oをたたくには、0xe0001100 + ポート番号*4番地にアクセスする。
  • Hを出力したいときには0x800000f1を書く。Lを出力したいときには0x800000f0を書く。

ということでした。ポートを直叩きすることでGPIOを高速化することができました。
これで、オンチップのUSB3.0-JTAGが作れるぞっ!

|

« RX-DIPの基板が出来上がった! | トップページ | EZ-USB FX3のI2C ROMにアクセス »

コメント

コメントを書く



(ウェブ上には掲載しません)




« RX-DIPの基板が出来上がった! | トップページ | EZ-USB FX3のI2C ROMにアクセス »