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

📄 sausb.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 4 页
字号:
 */
static
void showStats(DM_Function_T * funcP, void * arg)
{
  DM_ClearScreen();

  /* Global stats
   */
  DM_PrintfPaged("Int: %d, Cmd: %d",
		 udcStats.usbIntCount,
		 udcStats.commandCount);

  /* DMA stats
   */
  DM_PrintfPaged("RcvDma: %d, XmitDma: %d",
		 udcStats.rcvDmaCount,
		 udcStats.xmitDmaCount);

  /* Loopback stats
   */
  DM_PrintfPaged("Loop: %d, RxCmp: %d/%d",
		 udcStats.loopCount,
		 udcStats.rxCompareError,
		 udcStats.rxCompareCount);

  /* Endpoint 1 (IN) stats
   */
  DM_PrintfPaged("RcvPkt: %d, AcptPkt: %d",
		 udcStats.readPacketCount,
		 udcStats.acceptPacketCount);
  DM_PrintfPaged("FifoRd: %d, FifoOvr: %d",
		 udcStats.extraFIFOReads,
		 udcStats.fifoReadOverrun);
  DM_PrintfPaged("BadPkt: %d, DmaBsy: %d",
		 udcStats.badRdPacketCount,
		 udcStats.dmaReadPending);
  DM_PrintfPaged("NpRPC: %d, RejectPkt: %d",
		 udcStats.noRPC,
		 udcStats.rejectPacket);

  /* Endpoint 2 (OUT) count
   */
  DM_PrintfPaged("XmitPkt: %d/%d, WrtPkt: %d",
		 udcStats.badWrPacketCount,
		 udcStats.goodWrPacketCount,
		 udcStats.writePacketCount);
  DM_PrintfPaged("NoDMA: %d",
		 udcStats.noDMA);

  /* Endpoint 0 (control) stats
   */
  DM_PrintfPaged("Send: %d/%d, Fail: %d",
		 udcStats.reSendCount,
		 udcStats.sendCount,
		 udcStats.sendFailCount);
  DM_PrintfPaged("WriteCnt: %d/%d",
		 udcStats.reWriteCount,
		 udcStats.writeCount);
  DM_PrintfPaged("ReadCnt: %d/%d, Fail: %d",
		 udcStats.reReadCount,
		 udcStats.readCount,
		 udcStats.readFailCount);

  /* Register read/write stats
   */
  DM_PrintfPaged("UDD: %d/%d, RIM: %d/%d",
		 udcStats.uddRewrites, udcStats.uddWrites,
		 udcStats.rimRewrites, udcStats.rimWrites);

  DM_PrintfPaged("Comp: %d/%d, Cimp: %d/%d",
		 udcStats.compRewrites, udcStats.compWrites,
		 udcStats.cimpRewrites, udcStats.cimpWrites);

  DM_PrintfPaged("SSE: %d/%d, SO: %d/%d",
		 udcStats.sseRewrites, udcStats.sseWrites,
		 udcStats.soRewrites, udcStats.soWrites);
  DM_PrintfPaged("SST: %d/%d, FST: %d/%d",
		 udcStats.sstRewrites, udcStats.sstWrites,
		 udcStats.fstRewrites, udcStats.fstWrites);
  DM_PrintfPaged("IPR: %d/%d",
		 udcStats.iprRewrites, udcStats.iprWrites);

  DM_PrintfPaged("SST1: %d/%d, FST1: %d/%d",
		 udcStats.sst1Rewrites, udcStats.sst1Writes,
		 udcStats.fst1Rewrites, udcStats.fst1Writes);
  DM_PrintfPaged("SST2: %d/%d, FST2: %d/%d",
		 udcStats.sst2Rewrites, udcStats.sst2Writes,
		 udcStats.fst2Rewrites, udcStats.fst2Writes);
  DM_PrintfPaged("RPC: %d/%d, TPC: %d/%d",
		 udcStats.rpcRewrites, udcStats.rpcWrites,
		 udcStats.tpcRewrites, udcStats.tpcWrites);
  DM_PrintfPaged("RIR: %d/%d, MisRIR: %d",
		 udcStats.rirRewrites, udcStats.rirWrites,
		 udcStats.missedRIR);
  DM_PrintfPaged("TIR: %d/%d, MisTIR: %d",
		 udcStats.tirRewrites, udcStats.tirWrites,
		 udcStats.missedTIR);

  DM_PrintfPaged("EIR: %d/%d, RSTIR: %d/%d",
		 udcStats.eirRewrites, udcStats.eirWrites,
		 udcStats.rstirRewrites, udcStats.rstirWrites);

  DM_PrintfPaged("SUSIR: %d/%d, RESIR: %d/%d",
		 udcStats.susirRewrites, udcStats.susirWrites,
		 udcStats.resirRewrites, udcStats.resirWrites);

  DM_AnyKeyToContinue(NULL);
}

/*----------------------------------------------------------------------
 * Clear statistics
 */
static
void clearStats(DM_Function_T * funcP, void * arg)
{
  clearUdcStats();
}

/*----------------------------------------------------------------------
 * Compare the receive buffer
 */
static
void compareRx(void)
{
  int i, j;

  udcStats.rxCompareCount++;
  for (i=0; i < RX_BUFSIZE/maxPacketSize; i++) {
    for (j=0; j < maxPacketSize; j++) {
      if (rxDataP[i*maxPacketSize+j] != i) {
	DM_WarnPrintf("Mismatch buf %d, index %d\n",
		   udcStats.rxCompareCount,
		   i*maxPacketSize+j);
	udcStats.rxCompareError++;
	return;
      }
    }
  }
}

/*----------------------------------------------------------------------
 * Loopback data received to data transmit
 */
static
void loopDma(int reason, char * buf, void * param)
{
  udcStats.loopCount++;
  compareRx();
  memset(rxDataP,0xff,RX_BUFSIZE);
}

/*----------------------------------------------------------------------
 * Receive interrupt handler. This is called on DMA channel buffer
 * completion. Dispatch the callback function (if any) and keep track of
 * which buffer is active. Make sure the channel is cleared in case the
 * callback is not active so we don't continue to get interrupts.
 */
static
void rcvHandler(void * arg)
{
  void * buf = rcvBufs[whichGetRcvBuf].buf;

  udcStats.rcvDmaCount++;

  SA_ClearDMA(rcvDmaP,whichGetRcvBuf);
  rcvBufs[whichGetRcvBuf].buf = NULL;
  rcvBufs[whichGetRcvBuf].dmaP = NULL;
  DM_DbgPrintf("Rcv done %d bufs", rcvPacketCount);
  if (rcvCallback)
    rcvCallback(DM_SerialReceiveDone,
		(char*)buf,
		rcvBufs[whichGetRcvBuf].param);
  whichGetRcvBuf ^= 1;
}

/*----------------------------------------------------------------------
 * Transmit interrupt service handler. This is called on DMA channel
 * buffer completion. Dispatch the callback function (if any) and keep
 * track of which buffer is active. Make sure the channel is cleared in
 * case the callback is not active so we don't continue to get interrupts.
 */
static
void xmitHandler(void * arg)
{
  void * buf = xmitBufs[whichGetXmitBuf].buf;
  udcStats.xmitDmaCount++;

  SA_ClearDMA(xmitDmaP,whichGetXmitBuf);
  xmitBufs[whichGetXmitBuf].buf = NULL;
  xmitBufs[whichGetXmitBuf].dmaP = NULL;
  if (xmitCallback)
    xmitCallback(DM_SerialTransmitDone,
		(char*)buf,
		xmitBufs[whichGetXmitBuf].param);
  whichGetXmitBuf ^= 1;
}

/*----------------------------------------------------------------------
 * Find the requested descriptor
 */
static
char * getDescriptor(int type, int index, int * length)
{
  switch (type) {
  case UsbDescTypeDevice:
    *length = SA11x0_USB_DeviceDesc[0];
    return SA11x0_USB_DeviceDesc;
    break;
  case UsbDescTypeConfiguration:
    *length = SA11x0_USB_ConfigDesc[2]; /* Total length */
    return SA11x0_USB_ConfigDesc;
    break;
  }
  return NULL;
}

/*----------------------------------------------------------------------
 * Read the command from the endpoint 0 FIFO
 */
static
int getCommand(void * argP)
{
  unsigned char * bufP = (unsigned char*)argP;
  int length = udcP->udcwc.wc;
  int reReadAttempts = 10;
  char wcBuf[16];
  char tcBuf[16];
  int count[16];
  int attempts[16];
  int i;

  if (timerFuncP)
    timerFuncP->stop(timerP, 0, reSendTimerInterval, reSendProc, NULL);

  memset(bufP,0x55,8);

  for (i=0; i < length; i++) {
    int oldwc = udcP->udcwc.wc;
    int retryCount = readRetryCount;
    bufP[i] = udcP->udcd0.data;
    udcStats.readCount++;
    /* Make sure the read actually worked by polling the FIFO count.
     * When it decrements the read has been done, otherwise the read was
     * ignored.
     */
    wcBuf[i] = oldwc;
    tcBuf[i] = udcP->udcwc.wc;
    while (oldwc == tcBuf[i]) {
      if (--retryCount < 0) { /* Looks like we missed a read */
	bufP[i] = udcP->udcd0.data;
	udcStats.reReadCount++;
	retryCount = readRetryCount;
	/* If we get stuck here abort the command.
	 */
	if (--reReadAttempts < 0) {
	  udcStats.readFailCount++;
	  return 1;
	}
      }
      tcBuf[i] = udcP->udcwc.wc;
    }
    count[i] = readRetryCount - retryCount;
    attempts[i] = 10 - reReadAttempts;
#if 0
#if 0
    {
      int dummy, x;
      /* We have finished the write, now wait a bit to let things propagate.
       */
      for (x=0; x < 10; x++)
	dummy += *(volatile unsigned int *)&udcP->udcwc;
    }
#else
    DM_WaitUs(2);
#endif
#endif
  }

  /* All setup commands are 8 bytes in length
   */
  if (length != 8) {
    DM_WarnPrintf("UDC bad command length %d\n", length);
    return 1;
  }
  if (udcP->udcwc.wc != 0) {
    DM_WarnPrintf("UDC EP0 FIFO not empty %d\n", udcP->udcwc.wc);
    DM_WarnPrintf("%02X %02X %02X %02X %02X %02X %02X %02X",
		  bufP[0], bufP[1], bufP[2], bufP[3],
		  bufP[4], bufP[5], bufP[6], bufP[7]);
    DM_WarnPrintf("%02X %02X %02X %02X %02X %02X %02X %02X",
		  wcBuf[0], wcBuf[1], wcBuf[2], wcBuf[3],
		  wcBuf[4], wcBuf[5], wcBuf[6], wcBuf[7]);
    DM_WarnPrintf("%02X %02X %02X %02X %02X %02X %02X %02X",
		  tcBuf[0], tcBuf[1], tcBuf[2], tcBuf[3],
		  tcBuf[4], tcBuf[5], tcBuf[6], tcBuf[7]);
    DM_WarnPrintf("%2d %2d %2d %2d %2d %2d %2d %2d",
		  count[0], count[1], count[2], count[3],
		  count[4], count[5], count[6], count[7]);
    DM_WarnPrintf("%2d %2d %2d %2d %2d %2d %2d %2d",
		  attempts[0], attempts[1], attempts[2], attempts[3],
		  attempts[4], attempts[5], attempts[6], attempts[7]);
    return 1;
  }

  return 0;
}

/*----------------------------------------------------------------------
 * Command response with data packets
 */
static
void sendData(void * argP, int length, int totalLen)
{
  unsigned char * bufP = (unsigned char*)argP;
  struct udccs0Bits udccs0;
  int i;

  DM_DbgPrintf("UDC send %d bytes\n", length);

  /* Send the data back. The FIFO should be turned around for
   * us already. Just blast away ...
   */
  for (i=0; (i < length) && (i < USBR_MAX_PACKET_SIZE_CTL); i++) {
    int oldwc = udcP->udcwc.wc;
    int retryCount = writeRetryCount;
    int retryAttempts = 10;
    int wc;
    IOW_REG_FIELD(struct udcdBits,&udcP->udcd0,data,bufP[i]);
    udcStats.writeCount++;
    IOW_REG_GET(struct udcwcBits, &udcP->udcwc,wc,wc);
    while (oldwc == wc) {
      if (--retryCount < 0) { /* Looks like we missed a write */
	IOW_REG_FIELD(struct udcdBits,&udcP->udcd0,data,bufP[i]);
	udcStats.reWriteCount++;
	retryCount = writeRetryCount;
	/* If the FIFO did not detect a command requiring return
	 * data we will get stuck here. Abort the command.
	 */
	if (--retryAttempts < 0) {
	  UDC_REG_BITSET(struct udccs0Bits,&udcP->udccs0,fst,1,
			 udcP->udccs0.fst != 1,
			 fst);
	  udcStats.sendFailCount++;
	  return;
	}
      }
      IOW_REG_GET(struct udcwcBits, &udcP->udcwc,wc,wc);
    }
#if 1
    {
      int dummy, x;
      /* We have finished the write, now wait a bit to let things propagate.
       */
      for (x=0; x < 10; x++)
	dummy += *(volatile unsigned int *)&udcP->udcwc;
    }
#endif
  }

  /* Form the register update. Always set IPR.
   */
  udccs0 = udcP->udccs0;
  udccs0.ipr = 1;

  /* We can not complete on a packet which is full only if
   * the request allowed for more data. We need to wait till
   * next time and generate a zero length packet, so only complete
   * if we're at the end and it is not the max packet size.
   */
  if ((i == length) && ((i != USBR_MAX_PACKET_SIZE_CTL) || (i == totalLen))) {
    savSendPacket = sendPacket;
    savSendPacketLength = sendPacketLength;
    sendPacket = NULL;
    sendPacketLength = length - i;
    sendTotalLength = totalLen - i;
    udccs0.de = 1;
  }
  /* Need to send another packet.
   */
  else {
    sendPacket = (char*)&bufP[i];
    sendPacketLength = length - i;
    sendTotalLength = totalLen - i;
    savSendPacket = sendPacket;
    savSendPacketLength = sendPacketLength;
  }

  /* Update the register
   */
  UDC_REG_WRITEX(*(volatile unsigned *)&udcP->udccs0,*(unsigned *)&udccs0,
		 udcP->udccs0.ipr != 1,
		 ipr);

  udcStats.sendCount++;

  DM_DbgPrintf("UDC send packet done\n");
}

/*----------------------------------------------------------------------
 * Send command done
 */
static
void sendCommandDone(void)
{
  /* Release the command FIFO and start the data phase
   */
  UDC_REG_BITSET(struct udccs0Bits,&udcP->udccs0,so,1,
		 udcP->udccs0.opr != 0,
		 so);
}

/*----------------------------------------------------------------------
 * Command response with no data packets
 */
static
void sendDone(int err)
{
  struct udccs0Bits udccs0 = udcP->udccs0;

  DM_DbgPrintf("UDC send done\n");

  udccs0.so = 1;
  udccs0.de = 1;
  udccs0.fst = err;

  UDC_REG_WRITEX(udcP->udccs0,udccs0,
		 udcP->udccs0.opr != 0,
		 so);
}

/*----------------------------------------------------------------------
 * Timer handler. If there is still a transmit pending restart it
 */
static
void reSendProc(void * arg)
{
  struct udccs0Bits udccs0 = udcP->udccs0;

  /* If IPR and DE are both zero we have sent the last packet.
   */
  if ((udccs0.ipr == 0) && (udccs0.de == 0) && (sendPacket == NULL))
    savSendPacket = NULL;

  /* If there is still data to send we have missed a write to IPR. Resend
   */
  if ((udccs0.ipr == 0) && (savSendPacket)) {
    sendData(sendPacket, sendPacketLength, sendTotalLength);
    udcStats.reSendCount++;
  }
}

/*----------------------------------------------------------------------
 * Set the device address
 */
static

⌨️ 快捷键说明

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