So-net無料ブログ作成
検索選択

PSoC 5LP で BULK 転送 (1) [PSoC]このエントリーを含むはてなブックマーク#

回路図

PSoC 5LP には、 Full-Speed USB のインターフェイスが搭載されています。 今回からの記事では、 PSoC 5LP でどのくらいの転送速度が実現できるか、実験してみます。

USBFS コンポーネントの設定

CY8CKIT-059 Pioneer kit

実験に使用するハードウェアは、 CY8CKIT-059 PSoC® 5LP Prototyping Kit です。 USB のコネクタも実装されていますから、今回の実験にはピッタリです。

回路は、この記事のタイトルに掲げた通りです。 USBFS コンポーネントを配置して、インスタンス名を "USB" に変更しています。


Descriptor Root ノード

USBFS コンポーネントの設定ダイアログでは、デバイス・ディスクリプタを設定します。 すべて、 "Device Descriptor" タブの中で設定できます。

最初は、 "Descriptor Root" ノードの設定です。 ここには、エンドポイントバッファの取り扱い方法を四つの選択肢から選びます。 まずは、 "Manual (Static Allocation)" を試してみます。 他の方法は、続く記事で取り扱います。


Device Descriptor ノード

次は、 "Device Descriptor" ノードの設定です。 ここで重要なのは、 "Vendor ID" と "Product ID" です。 それぞれ "4B4" と "F1" に設定しています。

この VID/PID は、サイプレスが "Bulk Loop" というデバイスに設定した番号です。 そのため、新たに作成することなくデバイスドライバを使いまわすことができます。 デバイスドライバおよび関連するアプリケーションのインストールは、後ほど説明します。

"Manufacturing String" および "Product String" が設定されていますが、これらは必須ではありません。


Configuration Descriptor ノード

"Configuration Descriptor" ノードでは、 "Max Power (mA)" を 100 に変更しています。 また、 "Device Power" を "Bus Powered" にしています。 この実験の使い方では、消費電流の申告値を大きくする必要は、あまりありません。 また、 "Bus Powered" 申告をしてもしなくても、動作に影響はありません。 "100mA" であれば、一般的なバスパワーの USB ハブでも接続できるでしょう。


Alternate Setting 0 ノード

次は、 "Alternate Setting 0" ノードです。 このノードでは、設定はデフォルトのままですが、ひとつだけやることが有ります。 それは、エンドポイントを追加する事です。

これから作ろうとしているプロジェクトでは、 "BULK-IN" と "BULK-OUT" のエンドポイントをそれぞれひとつ使用します。 ところが、デフォルト状態では、エンドポイントが一つしか定義されていません。 ふたつ目のエンドポイントを追加するためには、 "Add Endpoint" ボタンをクリックします。


Endpoint Descriptor ノード (1)

ひとつめのエンドポイントは、 EP#1 を BULK-OUT で使用します。 パケットの最大サイズは、 Full-Speed 規格上の最大値である 64 とします。


Endpoint Descriptor ノード (2)

ふたつ目のエンドポイントは、 EP#2 を BULK-IN で使用します。 パケットの最大サイズは、 EP#1 と同じく 64 とします。

以上で USBFS コンポーネントの設定は終わりです。


この説明で使われた "BULK-IN" と "BULK-OUT" は、 USB インテーフェイスの用語です。

USB 規格では、ホストとファンクションと言う役割が有ります。 ほとんどの場合、 PC がホストになり、 PSoC 5LP で作るデバイスはファンクション側になります。 "BULK-IN" は、ホストから見た時のデータ方向を表していて、ホストがデータを受信する手順を表します。 同様に "BULK-OUT" はホストがデータを送信する手順を表します。

ファンクションから見るとデータの方向が逆になりますので、注意が必要です。

クロックの設定

クロック設定

USB を使用する上で気を付けなくてはならないのが、クロックの設定です。 USB の規格では、比較的高精度なクロックを要求されています。 ところが、 CY8CKIT-059 にはクリスタルなどの高精度なクロック源は搭載されていません。 こんな場合でも困らないように、 PSoC 5LP の場合、 USB ホストから送信された USB パケットのクロック情報を基準として、内蔵クロックである Internal Main Oscillator (IMO) を微調整し、最終的に ±0.25% の精度のクロックを得る機能があります。

微調整のタイミングをとるために 100kHz の低速クロックが使用されます。 このような事情から低速クロックもこの通りに設定しなくてはなりません。

IMO クロックは、 PLL に導入されて高速なバスクロックを生成しています。 このとき、 PLL の出力周波数を 80MHz に設定すると、 IMO が +0.25% 側に振れたときにバスクロックの最大値である 80.01MHz を超えてしまいます。 ここでは、 IMO が +0.25% の時でも最大値を超えない最大周波数設定ということで、 79.5MHz に設定しています。 これで、 IMO の誤差が大きい時でも安心して使用できます。

プログラム

プログラム

ハードウェアが整ったら、プロジェクトを Build して、ソースコードを記述します。 ソースコードは、すべて "main.c" に記述していきます。

#include "project.h"

#define     IN_EP               (0x02u)
#define     OUT_EP              (0x01u)
#define     BUFFER_SIZE         (64u)

ソースコードの最初の部分で、マクロにより定数を定義しています。 "IN_EP" は、 "BULK-IN" 転送に使用するエンドポイントの番号です。 エンドポイントは、 EP1 から EP8 までの最大8個を使用できます。 同様に、 "OU_EP" で "BULK-OUT" 転送に使用するエンドポイントを表します。

"BUFFER_SIZE" は、エンドポイントバッファのサイズを表します。 コンポーネントの設定で使用した最大サイズである "64" を使用しています。

uint8       buffer_in[BUFFER_SIZE] = "@@ABCDEFGIHJKLMNOPQRSTUVWXYZ";
uint8       buffer_out[BUFFER_SIZE];
uint16      length;

"BULK-IN" 転送では、 "buffer_in" に格納されたデータを少しずつ変化させながらホストに送信します。 一方 "BULK-OUT" 転送では、ホストから受信したデータの長さを "length" に受け取り、データ本体を "buffer_out" に引き取ります。 今回のプロジェクトは転送速度の上限を探ることを目的としています。 そのため、送受信するデータの加工は行われません。

int main(void) {
    CyGlobalIntEnable;                  // 割り込みの有効化    
    USB_Start(0, USB_5V_OPERATION);     // 動作電圧5VにてUSBFSコンポーネントを初期化

"main()" 関数の戦闘で割り込みを許可し、 USB コンポーネントの初期化を行っています。 CY8CKIT-059 評価ボードでは、ホストから供給された VBUS がそのまま PSoC 5LP に供給されます。 そのため、電源電圧が 5V である事を明記して初期化を行っています。

    for (;;) {
        // 初期化終了まで待機
        while (USB_GetConfiguration() == 0);

        USB_IsConfigurationChanged();   // CHANGEフラグを確実にクリアする

        USB_EnableOutEP(OUT_EP);        // OUTエンドポイントでホストからデータを受信する

初期化が終わったら、無限ループに入ります。 この無限ループでは、ホストから SET_CONFIGURATION で USB デバイスとしての初期設定が行われるのを待ちます。 "USB_GetConfiguration()" 関数で、 SET_CONFIGURATION が行われるのを待ちます。

さらに "USB_IsConfigurationChanged()" 関数が呼ばれて返り値が捨てられています。 この関数により、設定が変更された事を示す内部フラグが確実にクリアされます。 一部のオペレーティングシステムでは、 USB デバイスの検出後、二回 SET_CONFIGURATION が発行されます。 この関数呼び出しは、そういった SET_CONFIGURATION が複数回発行される場合に対処するためのものです。

デバイスが初期化された後は、受信が禁止されているため、 "BULK-OUT" データが受信できません。 そのため、最後の "USB_EnableOutEp()" 関数で "BULK-OUT" データの受信を許可しています。

        for (;;) {
            // 設定が変更されたら、再初期化をおこなう
            if (USB_IsConfigurationChanged()) {
                break;
            }

さらに内側にループが構成されています。 このループでは、実際のデータの送受信を行いますが、ホストから SET_CONFIGURATION が発行されたら外側のループに脱出して、初期設定を行います。 SET_CONFIGURATION を "USB_IsConfigurationChenged()" 関数で検出したら break でループを脱出します。

            // BULK-OUT : データが受信されたか調べる
            if (USB_GetEPState(OUT_EP) & USB_OUT_BUFFER_FULL) {
                // 受信バイト数を取得する
                length = USB_GetEPCount(OUT_EP);

                // OUTバッファからデータを取り出す
                USB_ReadOutEP(OUT_EP, &buffer_out[0], length);
            }

次に "BULK-OUT" データの受信を行います。 "BULK-OUT" からデータを受信すると、 "USB_GetState()" 関数で返される USB_OUT_BUFFER_FULL フラグがセットされます。 フラグがセットされているのを検出したら、受信したデータの長さを "USB_GetEPCount()" 関数から受け取り、その長さ分のデータを "USB_ReadOutEP()" 関数で受け取ります。 受け取ったデータは "buffer_out[]" に格納されますが、格納されたデータは使用されず破棄されます。 以上でデータの受信は終わりです。

もし、データをバッファに受け取る前に次の "BULK-OUT" パケットが届いてしまったら、 PSoC 5LP の USB インターフェイスハードウェアは自動的に NAK を返し、受信できない事をホストに示します。 NAK を受けたホストは、次の機会を待って、ふたたび "BULK-OUT" パケットを送信し、データが受信できた事を示す ACK をファンクションが返すまでデータを送り続けます。

このような動作を行っているので、 "BULK-OUT" 転送ではホストから送信されたデータが確実にファンクションに届くことが保証できます。

            // BULK-IN : 送信バッファが空いたか調べる
            if (USB_GetEPState(IN_EP) & USB_IN_BUFFER_EMPTY) {
                // INバッファにデータを送り込む
                buffer_in[0]++;
                USB_LoadInEP(IN_EP, &buffer_in[0], BUFFER_SIZE);
            }
        }
    }
}

最後は、 "BULK-IN" 転送です。 "BULK-IN" からデータを送信できるようになると、 "USB_GetState()" 関数で返される USB_IN_BUFFER_EMPTY フラグがセットされます。 フラグがセットされているのを検出したら、 "buffer_in[]" のデータを準備し "USB_LoadInEP()" 関数でデータを送信します。 ホスト側が受信したパケットをそれぞれ区別できるように、送信されるデータの最初の1バイトの値を変化させています。

準備されたデータは、ホストから要求が来たらホストに送信されます。 ファンクションのデータは、ホストが受信した事を示す ACK が来るまで保存されます。 このため、 "BULK-IN" のデータもホストに確実に届くことが保証されます。

ソースコードは以上です。 PSoC 5LP にプログラムしたら、 USB デバイスの出来上がりです。

転送速度の測定

デバイスが出来上がったら、転送速度を測定してみます。 PSoC 向けに測定を行うツールは、ありませんが、 EZ-USB FX3 向けに作られたツールならあります。 今回は、ありがたく、このツールを利用させてもらいます。

ツールは、 Cypress USB Suite というソフトウェア群に含まれており、 EZ-USB FX3 Software Development Kit からダウンロードできます。 インストールするには、 "EZ-USB FX3 SDK" インストーラをダウンロードして "" をまるごとインストールするか、 "USB Suite Zip" をダウンロードして使う方法があります。 ハードディスクに余裕が有れば、インストーラをご利用ください。

プログラムした PSoC 5LP の USB コネクタを PC に接続すると、デバイスドライバがインストールされます。 もし、自動的にインストールされない場合には、ダウンロードまたはインストールしたファイルからデバイスドライバを探してインストールしてください。


Streamer

転送速度を測定するツールは、 "Streamer" と呼ばれています。 ツールを起動すると、 "Connected Device" に "Cypress FX3 USB Streamer Example" というデバイスが見えます。 これが、さきほどプログラムした "PSoC 5LP" デバイスです。 "Endpoint" で "BULK IN" または "BULK OUT" を選び、 "Start" ボタンをクリックすると転送が始まり転送速度が表示されます。


BULK IN 転送速度

"BULK-IN" を選んだ場合、私の PC では 850kB/s (毎秒850kバイト)と表示されました。 Full-Speed のバス速度が 12Mb/s ですから妥当な値でしょう。


BULK OUT 転送速度

"BULK-OUT" の転送速度は 700kB/s と表示されました。


送受信転送速度

Streamer アプリケーションをふたつ開いて、 "BULK-IN" と "BULK-OUT" を同時に動かす事も出来ます。 この場合、 "BULK-IN" も "BULK-OUT" も転送速度が 560kB/s になりました。 ソースコードの構成から、転送速度が速い状態では、 "BULK-IN" と "BULK-OUT" が代わる代わる処理されます。 そのため、双方の転送速度が等しくなったと考えられます。

プロジェクトアーカイブ

この記事で作成したプロジェクトは、このファイルの拡張子を "zip" に変更すると再現できます。

関連商品

CY8CKIT-059 PSoC 5LP Prototyping Kit

CY8CKIT-059 PSoC 5LP Prototyping Kit

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス

nice!(0)  コメント(0)  トラックバック(0)  このエントリーを含むはてなブックマーク#

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この記事のトラックバックURL:
※言及リンクのないトラックバックは受信されません。