⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sausb.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 4 页
字号:
/*----------------------------------------------------------------------
 * Copyright (C) 1999 Intel Corp.
 *
 * This file contains the USB loopback device. This device provides basic
 * test capability for control and bulk transfer testing. The device
 * supports a few basic general commands (SetAddress, GetDescriptor,
 * SetConfiguration) and a few "vendor" specific commands.
 *
 * USB problems
 *
 * 1.  Reads and writes are ignored by the interface (only writes stated in
 *     spec)!
 * 2.  Given above the design *should* provide a mechanism to verify
 *     the action of every read/write. For the most part it does.
 * 3.  EP0 FIFO reads are ignored. Length register can be used to detect this.
 *     Repeat the read until the count register changes.
 * 4.  EP0 FIFO writes are ignored. Length register can be used to detect this.
 *     Repeat the read until the count register changes. When the write counter
 *     changes you *must* wait a period of time before writing the next byte.
 *     Failure to do this will result in the first byte being overwritten.
 * 5.  EF0 IPR sets are ignored. Retry is dangerous, especially with DE side
 *     effect.
 *     Workaround to use timer to detect missed transmit, IPR clear with
 *     packets data still remaining indicates ignored transmit. DE set after
 *     last packet sent indicates ignored write on last packet. Resend whole
 *     packet. Alternative is to repeat set of IPR until is is visible.
 * 6.  EP1 FIFO reads do NOT clear RNE when the FIFO overruns! This causes
 *     hangs if packets larger than 16 are allowed in polled mode. Make sure
 *     max packet is < FIFO size in this case.
 * 7.  Hardware race condition on RPC and RIR. No way to repeat clear and
 *     guarantee the result is visible unless there are no interrupts and
 *     very tight loop.
 * 8.  Write to TPC clears FIFO loosing any data DMA'd for the next packet.
 *     Workaround is to setup single packet DMA and reset DMA in the interrupt
 *     service function for each packet.
 * 9.  RNE will not clear if RPE is set, probably another case of #6.
 * 10. DMA will occur on a bad packet, it needs to be cuaght and undone. Due
 *     to this problem no DMA completion interrupts can be used (the completion
 *     interrupt can fire on a bad packet which can't be undone).
 * 11. Set and test mechanism for UDC bits will cause hang until the USB
 *     clocks are running. Dont try this if the USB cable is disconnected or
 *     the host is stopped.
 * 12. Client detects error in packet when analyzer in line does not. Possible
 *     problem in client receive. Effect is RPE will be set and no response is
 *     generated for packet (see #9). Host may or may not tolerate this.
 * 14. Client does not always respond to IN packets. This can cause the host
 *     to declare the client dead. No workaround at this time but it has been
 *     observed that running the USB clock at 11.88Mhz (from the host) avoids
 *     the problem.
 * 15. EP0 FIFO does not hold off the host or ACK the receipt of a packet until
 *     it is read. This means if you do not respond to the interrupt within
 *     the host retry period (10us or so) the host will retransmit. The new
 *     data will overwrite the existing FIFO data including portions currently
 *     being read. The result is a corrupt packet. If the packet can not
 *     be completely read from the FIFO in this period it will never be
 *     received correctly. This problem has only been observed at 148Mhz and
 *     only after 4K IN packet transmission.
 */
#include <string.h>
#include "dm.h"
#include "usbx.h"
#include "usbr.h"
#include "sa11x0.h"
#include "StrongArm.h"
#include "sadma.h"
#include "sairq.h"
#include "sairqh.h"

/*----------------------------------------------------------------------
 * Test menu structures
 */
DM_TestFunc_T DM_EditMemory;

static DM_TestFunc_T startClient, stopClient, pollClient, showStats,
		     clearStats;
static char usbBanner[] = "USB Test Menu";
static DM_Test_T usbTests[] = {
   0, "Start client 16",       startClient,	(void*)16,
   1, "Start client 64",       startClient,	(void*)64,
   2, "Start client 16 (poll)",pollClient,	(void*)16,
   3, "Stop USB Client",       stopClient,	NULL,
   4, "Show Statistics",       showStats,       NULL,
   5, "Clear Statistics",      clearStats,      NULL,
  14, "Exit",		       NULL,		NULL,
  15, "Edit Memory",	       DM_EditMemory,	NULL,
  0, NULL
};

/*----------------------------------------------------------------------
 * SA1110 USB receiver base address
 */
static volatile struct udcreg * udcP;

/*----------------------------------------------------------------------
 * Register writes need to be verified. This macro loops the write until
 * the effects are visible and records the number of retries.
 */
#define UDC_REG_WRITE(_struct,_ptr,_field,_val,_cmpexp,_stat) {		\
  int reWrites = 0;							\
  do {									\
    IOW_REG_FIELD(_struct,_ptr,_field,_val);				\
    reWrites++;								\
  } while (_cmpexp);							\
  udcStats._stat##Writes++;						\
  udcStats._stat##Rewrites += reWrites-1;				\
}

#define UDC_REG_BITSET(_struct,_ptr,_field,_val,_cmpexp,_stat) {	\
  int reWrites = 0;							\
  _struct xx;								\
  *(unsigned int *)&xx = 0;						\
  xx._field = _val;							\
  do {									\
    IOW_REG_SET(_struct,_ptr,*(unsigned int*)&xx);			\
    reWrites++;								\
  } while (_cmpexp);							\
  udcStats._stat##Writes++;						\
  udcStats._stat##Rewrites += reWrites-1;				\
}

#define UDC_REG_WRITEX(_setptr,_setval,_cmpexp,_stat) {			\
  int reWrites = 0;							\
  int retryCount = 1000000;						\
  do {									\
    _setptr = _setval;							\
    reWrites++;								\
  } while ((_cmpexp) && (--retryCount > 0));				\
  udcStats._stat##Writes++;						\
  udcStats._stat##Rewrites += reWrites-1;				\
}

/*----------------------------------------------------------------------
 * The IN/OUT packet size may be configured between 1-255 bytes (seems like
 * 16 is the only value that works reliably).
 */
#define USBR_MAX_PACKET_SIZE 16

/*----------------------------------------------------------------------
 * The control FIFO is fixed at 8 bytes and will not work unless both
 * host and device use 8 byte packet size.
 */
#define USBR_MAX_PACKET_SIZE_CTL 8

/*----------------------------------------------------------------------
 * Variables for resend control. Keep track of last packet sent.
 */
static char * sendPacket;
static int sendPacketLength;
static int sendTotalLength;
static char * savSendPacket;
static int savSendPacketLength;
#define RESEND_INTERVAL 100 /* 100ms */
static int reSendTimerInterval;
static int readRetryCount = 100;
static int writeRetryCount = 100;
static int maxPacketSize = USBR_MAX_PACKET_SIZE;

/*----------------------------------------------------------------------
 * Statistics
 */
typedef struct Udc_Stats_S {
  /* General stats
   */
  int usbIntCount;

  /* Endpoint 0 (Command) stats
   */
  int commandCount;

  int sendCount;
  int sendFailCount;
  int reSendCount;

  int readCount;
  int readFailCount;
  int reReadCount;

  int writeCount;
  int reWriteCount;

  /* DMA stats
   */
  int rcvDmaCount;
  int xmitDmaCount;

  /* Loopback stats
   */
  int loopCount;
  int rxCompareCount;
  int rxCompareError;

  /* Endpoint 1 (OUT) stats
   */
  int readPacketCount;
  int acceptPacketCount;
  int extraFIFOReads;
  int fifoReadOverrun;
  int missedRIR;
  int badRdPacketCount;
  int dmaReadPending;
  int noRPC;
  int rejectPacket;

  /* Endpoint 2 (IN) stats
   */
  int writePacketCount;
  int missedTIR;
  int badWrPacketCount;
  int goodWrPacketCount;
  int noDMA;

  /* UDCCR bit write stats
   */
  int uddWrites;
  int uddRewrites;
  int rimWrites;
  int rimRewrites;
  int eimWrites;
  int eimRewrites;
  int timWrites;
  int timRewrites;

  /* UDCOMP bit write stats
   */
  int compWrites;
  int compRewrites;

  /* UDCIMP bit write stats
   */
  int cimpWrites;
  int cimpRewrites;

  /* UDCCS0 bit write stats
   */
  int sseWrites;
  int sseRewrites;
  int soWrites;
  int soRewrites;
  int sstWrites;
  int sstRewrites;
  int fstWrites;
  int fstRewrites;
  int iprWrites;
  int iprRewrites;

  /* UDCCS1 bit write stats
   */
  int rpcWrites;
  int rpcRewrites;
  int fst1Writes;
  int fst1Rewrites;
  int sst1Writes;
  int sst1Rewrites;

  /* UDCCS2 bit write stats
   */
  int tpcWrites;
  int tpcRewrites;
  int fst2Writes;
  int fst2Rewrites;
  int sst2Writes;
  int sst2Rewrites;

  /* UDCSR bit write stats
   */
  int eirWrites;
  int eirRewrites;
  int rirWrites;
  int rirRewrites;
  int tirWrites;
  int tirRewrites;
  int rstirWrites;
  int rstirRewrites;
  int susirWrites;
  int susirRewrites;
  int resirWrites;
  int resirRewrites;
} Udc_Stats_T;

static Udc_Stats_T udcStats;

/*----------------------------------------------------------------------
 * Buffer information used by interrupt service routine to dispatch
 * callback functions.
 */
typedef struct bufInfo_S {
  DM_Function_T * funcP;
  char * buf;
  char * dmaP;
  void * param;
  int len;
} bufInfo_T;

static DM_Function_T * thisP;

#define RX_BUFSIZE 4096
#define TX_BUFSIZE 4096
static char rxData[64*1024];
static char txData[64*1024];
static char * rxDataP;
static char * txDataP;

static bufInfo_T rcvBufs[2];
static bufInfo_T xmitBufs[2];

static int whichGetRcvBuf;
static int whichPutRcvBuf;

static int whichGetXmitBuf;
static int whichPutXmitBuf;

static void * xmitDmaP;
static void * rcvDmaP;
static int rcvPacketCount;
static int dmaInterrupts;
static int udcInterrupts;
static int udcInterruptConnected;

static DM_SerialCallback_T rcvCallback;
static DM_SerialCallback_T xmitCallback;

/*----------------------------------------------------------------------
 * Timer for retries
 */
static DM_Function_T * timerP;
static DM_TimerFuncs_T * timerFuncP;

/*----------------------------------------------------------------------
 * The loopback device descriptor
 */
char SA11x0_USB_DeviceDesc[18] = {
  18,			/* Descriptor length */
  UsbDescTypeDevice,	/* Device descriptor */
  0,			/* USB 1.00 */
  1,			/* USB 1.00 */
  0xff,			/* No class */
  0xff,			/* No sub class */
  0xff,			/* No protoocol */
  USBR_MAX_PACKET_SIZE_CTL, /* Max packet size */
  0x55,			/* Vendor ID */
  0x55,			/* Vendor ID */
  0x55,			/* Product ID */
  0x55,			/* Product ID */
  0,			/* Device BCD */
  0,			/* Device BCD */
  0,			/* Index of Manufacturer string */
  0,			/* Index of Product string */
  0,			/* Index of Serial number string */
  1			/* Number of configurations */
};

/*----------------------------------------------------------------------
 * The loopback device configuration descriptor
 */
char SA11x0_USB_ConfigDesc[] = {
  9,			/* Descriptor length */
  UsbDescTypeConfiguration, /* Configuration descriptor */
  32,			/* Total len LSB */
  0,			/* Total len MSB */
  1,			/* Number interfaces */
  1,			/* Configuration value */
  0,			/* Configuration string index */
  0x40,			/* Attributes */
  1,			/* Max Power */

  9,			/* Descriptor length */
  UsbDescTypeInterface, /* Interface descriptor */
  0,			/* Number of interface */
  0,			/* Alternate setting */
  2,			/* Number endpoints */
  0xff,			/* Interface class */
  0xff,			/* Interface sub class */
  0xff,			/* Interface protocol */
  0,			/* Interface string descriptor */

  7,			/* Descriptor length */
  UsbDescTypeEndpoint,  /* Endpoint descriptor */
  0x01,			/* Endpoint address 1 (OUT) */
  UsbBulk,		/* Bulk transfer */
  USBR_MAX_PACKET_SIZE,	/* Max packet size LSB */
  0,			/* Max packet size MSB */
  0,			/* Polling interval */

  7,			/* Descriptor length */
  UsbDescTypeEndpoint,  /* Endpoint descriptor */
  0x82,			/* Endpoint address 2 (IN) */
  UsbBulk,		/* Bulk transfer */
  USBR_MAX_PACKET_SIZE,	/* Max packet size LSB */
  0,			/* Max packet size MSB */
  0,			/* Polling interval */
};

/*----------------------------------------------------------------------
 * Forward reference
 */
static void reSendProc(void * arg);
static int receive(DM_Function_T * funcP, char * buf, int len, void * param);
static int transmit(DM_Function_T * funcP, char * buf, int len, void * param);
static int setCallback(DM_Function_T * funcP, DM_SerialCallback_T func,
		       int reason);
void USBR_CheckLoopback(void);
static void setup(DM_Function_T * funcP, int intEnable, int dmaEnable);
static void cleanup(DM_Function_T * funcP);

/*----------------------------------------------------------------------
 * Clear stats block
 */
static
void clearUdcStats(void)
{
  memset(&udcStats,0,sizeof(udcStats));
}

/*----------------------------------------------------------------------
 * Poll the client
 */
static
void pollClient(DM_Function_T * funcP, void * arg)
{
  DM_StartTest("USB Polled Client");
  DM_Message("Hit any key to stop test");
  setup(funcP,0,0); /* No interrupts w/ no DMA */
  do {
    USBR_CheckLoopback();
  } while (!DM_StopTest(NULL));
  DM_FinishTest("USB Polled Client Complete");
}

/*----------------------------------------------------------------------
 * Stop the client interface
 */
static
void stopClient(DM_Function_T * funcP, void * arg)
{
  DisableInterrupt(IRQ_UDC_SERVICE_REQ_VEC);
  cleanup(funcP);
  DM_AnyKeyToContinue("UDC processing stopped");
}

/*----------------------------------------------------------------------
 * Start the client interface
 */
static
void startClient(DM_Function_T * funcP, void * arg)
{
  maxPacketSize = (int)arg;
  SA11x0_USB_ConfigDesc[22] = maxPacketSize;
  SA11x0_USB_ConfigDesc[29] = maxPacketSize;
  setup(funcP,1,1); /* Interrupts w/ DMA */
  EnableInterrupt(IRQ_UDC_SERVICE_REQ_VEC);
  DM_AnyKeyToContinue("UDC processing started");
}

/*----------------------------------------------------------------------
 * Show statistics

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -