« Artix-7にMicroBlazeを入れてみた | トップページ | Artix-7ボードにFX3 USB-JTAG機能を実装 »

2013.07.19

EZ-USB FX3でEndPointを追加する

特電Artix-7ボード上のEZ-USB FX3でUSB-JTAGを実現するため、FX3にEndPointを追加することにしました。

現在、このFX3はEndpoint1(と0x81)をそれぞれOUT用とIN用のSlaveFIFOに使っています。これらのEndPointのデータはハード的に処理されてFPGAに送られるので、CPUが関与できません。

そこで、CPUが自由に操作できるEndPointを2つ追加しようというわけです。

そのためにはまず、ディスクリプタを書き換えて、EndPointを2つ作りました。1個分を示します。SuperSpeedだとcompanion descriptorというのが必要なようです。

/* Endpoint descriptor for producer EP */
0x07,                           /* Descriptor size */
CY_U3P_USB_ENDPNT_DESCR,        /* Endpoint descriptor type */
0x04,                           /* Endpoint address and description */
CY_U3P_USB_EP_BULK,             /* Bulk endpoint type */
0x00,0x04,                      /* Max packet size = 1024 bytes */
0x00,                           /* Servicing interval for data transfers : 0 for bulk */

/* Super speed endpoint companion descriptor for producer EP */
0x06,                           /* Descriptor size */
CY_U3P_SS_EP_COMPN_DESCR,       /* SS endpoint companion descriptor type */
0x00,                           /* Max no. of packets in a burst : 0: burst 1 packet at a time */
0x00,                           /* Max streams for bulk EP = 0 (No streams) */
0x00,0x00,                      /* Service interval for the EP : 0 for bulk */

エンドポイントの番号は、OUT用が0x04、IN用が0x88にしました。

それから、ファームウェアでもEndPointの設定をします。

CyU3PMemSet ((uint8_t *)&epCfg, 0, sizeof (epCfg));
epCfg.enable = CyTrue;
epCfg.epType = CY_U3P_USB_EP_BULK;
epCfg.burstLen = 1;
epCfg.streams = 0;
epCfg.pcktSize = size;
CyU3PSetEpConfig(CY_FX_EP_MYPRODUCER, &epCfg); // 0x04 EP4 OUT
CyU3PSetEpConfig(CY_FX_EP_MYCONSUMER, &epCfg); // 0x88 EP8 IN

ここで、CY_FX_EP_MYPRODUCERは0x04、CY_FX_EP_MYCONSUMERは0x88です。

これで、EndPoint4と8が作られ、それぞれBulkOUTとBuldInとしてセットアップされます。

次にdmaの設定を行います。CPUがデータを処理したい場合でもDMAを使います。
FX3ではProducerとかConsumerという用語が出てくるのですが、BulkInの場合はProducerはCPUのプログラムで、ConsumerはUSBのEndPointです。

// EndPoint EP8 INの設定
dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;
dmaCfg.notification = 0;
dmaCfg.cb = NULL;
dmaCfg.prodHeader = 0;
dmaCfg.prodFooter = 0;
dmaCfg.consHeader = 0;
dmaCfg.prodAvailCount = 0;
dmaCfg.prodSckId = CY_U3P_CPU_SOCKET_PROD;
dmaCfg.consSckId = CY_FX_EP_MYCONSUMER_SOCKET; // <= CY_U3P_UIB_SOCKET_CONS_8
apiRetStatus = CyU3PDmaChannelCreate (&glChHandleBulkLpOut,
    CY_U3P_DMA_TYPE_MANUAL_OUT, &dmaCfg);

CyU3PUsbFlushEp(CY_FX_EP_MYCONSUMER); // 0x88
apiRetStatus = CyU3PDmaChannelSetXfer (&glChHandleBulkLpOut, 0);

prodSckIdとconsSckIdは上のリストのように設定します。consSckIdに設定されているCY_FX_EP_MYCONSUMER_SOCKETは、マクロ定義でCY_U3P_UIB_SOCKET_CONS_8にしています。こうすると、8番のEndPointに割り当てられるのだと思います。

ちなみに、USB Managerで見るとこうなっています。

Fx3_ep_4

これをどうやって使うかというと、SlFifoAppThread_Entryの中で、

int i;
CyU3PDmaChannelGetBuffer (&glChHandleBulkLpOut, &inBuf_p, CYU3P_WAIT_FOREVER);
for(i=0;i<1024;i++) {
    inBuf_p.buffer[i] = i;
}
CyU3PDmaChannelCommitBuffer (&glChHandleBulkLpOut, 1024, 0);

とするようです。つまり、バッファが空きになるまで待って、空いたらデータを詰めて、それからCommitします。

上のリストはBulkInの場合ですが、BulkOutの場合も同様でCyU3PDmaChannelCommitBufferの代わりにCyU3PDmaChannelDiscardBufferを使えばよいようです。

これで、EndPointに入ったデータをCPUで読んだり、CPUからデータをセットしてINパケットに乗せることができるようになります。

|

« Artix-7にMicroBlazeを入れてみた | トップページ | Artix-7ボードにFX3 USB-JTAG機能を実装 »

コメント

コメントを書く



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




« Artix-7にMicroBlazeを入れてみた | トップページ | Artix-7ボードにFX3 USB-JTAG機能を実装 »