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

📄 sausb.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 4 页
字号:
	  /* Resume the DMA channel
	   */
	  SA_ResumeDMA(rcvDmaP);
	}
      }
      else
	DM_WarnPrintf("Packet after DMA complete");

      acceptPacket = 1;
    }

    /* Clear RPC/RIR if we accept the packet.
     */
    if (acceptPacket) {
      int s;

      udcStats.acceptPacketCount++;
      rcvPacketCount++;

      /* Make sure we clear RIR first or we have a race condition with RPC
       * reset. RIR should not set again while RPC is still set because
       * packets are being NAKed. However, make sure we can not get
       * interrupted when polling this code.
       */
      if (!udcInterrupts)
	s = IRQ_DisableInterrupts(CPSR_I_Bit|CPSR_F_Bit);

      UDC_REG_BITSET(struct udcsrBits,&udcP->udcsr,rir,1,
		     udcP->udcsr.rir != 0,
		     rir);

      /* If RPC was set clear it for next time. There is a race condition
       * here because as soon as the bit actually clears the transfer
       * (which is currently bing NAK'd) will proceed. This may set the bit
       * again before we see it clear in which case we'll clear the second
       * set). To try to preclude this in polling mode make sure we can not
       * be interrupted while in this loop.
       */
#if 1
      if (udcP->udccs1.rpc) {
	UDC_REG_BITSET(struct udccs1Bits,&udcP->udccs1,rpc,1,
		       udcP->udccs1.rpc != 0,
		       rpc);
      }
#else
      /* Experiment with assembly code to clear the bit.
       */
      SA_ClearBit(&udcP->udccs1,1 << 1);
#endif

      if (!udcInterrupts)
	IRQ_EnableInterrupts(s);

    }
    /* If we dont accept the packet disable interrupts until the next
     * buffer arrives. Make sure we clear RIR or we'll be in an infinite loop.
     */
    else {
      udcStats.rejectPacket++;

      UDC_REG_WRITE(struct udccrBits,&udcP->udccr,rim,1,
		    udcP->udccr.rim != 1,
		    rim);
      UDC_REG_BITSET(struct udcsrBits,&udcP->udcsr,rir,1,
		     udcP->udcsr.rir != 0,
		     rir);
    }
  }

  if (udcsr.tir) {

    if (udcP->udccs2.tpc) {
      /* Packet in error, back up the DMA pointer and repeat.
       */
      if (udcP->udccs2.tpe) {
	char * txBufP = xmitBufs[whichGetXmitBuf].dmaP;
	
	/* Pause the DMA channel so we can access the pointers
	 */
	SA_PauseDMA(xmitDmaP);

	/* Back up the DMA pointer to the last packet
	 */
	SA_SetDMABuffer(xmitDmaP,whichGetXmitBuf,txBufP);

	/* Resume the DMA channel
	 */
	SA_ResumeDMA(xmitDmaP);

	udcStats.badWrPacketCount++;
      }
      /* Packet not in error - update the saved DMA pointer and length
       */
      else {
	xmitBufs[whichGetXmitBuf].len -= maxPacketSize;
	xmitBufs[whichGetXmitBuf].dmaP += maxPacketSize;
	udcStats.goodWrPacketCount++;
      }

      /* Clear the interrupt, this needs to be done before TPC gets cleared.
       */
      UDC_REG_BITSET(struct udcsrBits,&udcP->udcsr,tir,1,
		     udcP->udcsr.tir != 0,
		     tir);

      /* Clear TPC, this will reset the FIFO and allow the next packet to
       * be sent.
       */
      UDC_REG_BITSET(struct udccs2Bits,&udcP->udccs2,tpc,1,
		     udcP->udccs2.tpc != 0,
		     tpc);

      /* The transmit function can only send one packet at a time because TPC
       * clears the FIFO. Check to see if we have data still to send and if so
       * start the next packet.
       */
      if (xmitBufs[whichGetXmitBuf].buf) {
	udcStats.writePacketCount++;
	DM_DbgPrintf("Tx %d, %x, len %d",
		     whichGetXmitBuf,
		     xmitBufs[whichGetXmitBuf].dmaP,
		     xmitBufs[whichGetXmitBuf].len);
	if (xmitBufs[whichGetXmitBuf].len > 0) {
	  int len = xmitBufs[whichGetXmitBuf].len;
	  if (len > maxPacketSize)
	    len = maxPacketSize;
	  SA_StartDMA(xmitDmaP,
		      xmitBufs[whichGetXmitBuf].dmaP,
		      len,
		      dmaInterrupts && (xmitCallback != NULL));
	}
	else
	  xmitHandler(NULL);
      }
      else {
	DM_WarnPrintf("Transmit w/o DMA active");
	udcStats.noDMA++;
      }
    }
#if 0
    else {
      /* TIR set w/o TPC, just clear it.
       */
      UDC_REG_BITSET(struct udcsrBits,&udcP->udcsr,tir,1,
		     udcP->udcsr.tir != 0,
		     tir);
    }
#endif
  }

  if (udcsr.susir) {
    UDC_REG_BITSET(struct udcsrBits,&udcP->udcsr,susir,1,
		   udcP->udcsr.susir != 0,
		   susir);
  }

  if (udcsr.resir) {
    UDC_REG_BITSET(struct udcsrBits,&udcP->udcsr,resir,1,
		   udcP->udcsr.resir != 0,
		   resir);
  }
}

/*----------------------------------------------------------------------
 * Initialize the UDC
 */
void setup(DM_Function_T * funcP, int intEnable, int dmaEnable)
{
  int i;

  DM_DbgPrintf("Enable SA1110 USB receiver\n");

  /* Enable the USB receiver, make sure we cycle disable to reset the UDC
   */
  UDC_REG_WRITE(struct udccrBits,&udcP->udccr,udd,1,
		udcP->udccr.udd != 1,
		udd);
  DM_WaitUs(100);
  UDC_REG_WRITE(struct udccrBits,&udcP->udccr,udd,0,
		udcP->udccr.udd != 0,
		udd);

  /* Disable all interrupts
   */
#if 0
  IOW_REG_FIELD(struct udccrBits,&udcP->udccr,eim,1);
  IOW_REG_FIELD(struct udccrBits,&udcP->udccr,rim,1);
  IOW_REG_FIELD(struct udccrBits,&udcP->udccr,tim,1);
  IOW_REG_FIELD(struct udccrBits,&udcP->udccr,srm,1);
  IOW_REG_FIELD(struct udccrBits,&udcP->udccr,rem,1);
#endif

  if (intEnable && !udcInterruptConnected) {
    /* Register an interrupt handler
     */
    RegisterHandler(IRQ_UDC_SERVICE_REQ_VEC,
		    DM_InterruptRisingEdge,
		    DM_InterruptDefault,
		    interruptHandler,
		    NULL);
    udcInterruptConnected = 1;
  }
  udcInterrupts = intEnable;

  /* Enable endpoint interrupts (even if we are polling we need these)
   */
#if 1
  UDC_REG_WRITE(struct udccrBits,&udcP->udccr,eim,0,
		udcP->udccr.eim != 0,
		eim);
  UDC_REG_WRITE(struct udccrBits,&udcP->udccr,rim,0,
		udcP->udccr.rim != 0,
		rim);
  UDC_REG_WRITE(struct udccrBits,&udcP->udccr,tim,0,
		udcP->udccr.tim != 0,
		tim);
#endif

  /* Setup the DMA channels
   */
  if (dmaEnable) {
    if ((xmitDmaP = (void*)SA_AllocateDMA(SA11x0_UDC_Xmit,0)) == NULL)
      return;
    if ((rcvDmaP = (void*)SA_AllocateDMA(SA11x0_UDC_Rcv,0)) == NULL) {
      SA_ReleaseDMA(xmitDmaP);
      return;
    }
  }

  if (dmaEnable && intEnable) {
    /* Register handlers for the DMA channels
     */
    RegisterHandler(IRQ_CHANNEL0_VEC+SA_GetChannelDMA(rcvDmaP),
		    DM_InterruptRisingEdge,
		    DM_InterruptDefault,
		    rcvHandler,
		    NULL);

    RegisterHandler(IRQ_CHANNEL0_VEC+SA_GetChannelDMA(xmitDmaP),
		    DM_InterruptRisingEdge,
		    DM_InterruptDefault,
		    xmitHandler,
		    NULL);
    dmaInterrupts = 1;
  }
  else
    dmaInterrupts = 0;

  /* Open the timer
   */
  if (timerP) {
    timerFuncP = (DM_TimerFuncs_T*)timerP->open(timerP);
    reSendTimerInterval = RESEND_INTERVAL / timerFuncP->getInterval(timerP);
  }

  /* Get the non cacheable address for the data buffers
   */
  rxDataP = (char*)SA_NonCacheableAddress(rxData);
  txDataP = (char*)SA_NonCacheableAddress(txData);
 
  /* Fill the transmit buffer
   */
  for (i=0; i < TX_BUFSIZE; i += 2) {
    txDataP[i] = i % maxPacketSize;
    txDataP[i+1] = i / maxPacketSize;
  }

  /* Set the completion callback.
   */
  if (rcvDmaP)
    setCallback(funcP, loopDma, DM_SerialReceiveDone);

  DM_DbgPrintf("Enable SA1110 USB receiver done\n");
}

/*----------------------------------------------------------------------
 * Usb interface receive function. Post the buffer to the DMA
 * channel and record any callback info in the buffer info structure.
 */
static
int receive(DM_Function_T * funcP, char * buf, int len, void * param)
{
  rcvBufs[whichPutRcvBuf].buf = buf;
  rcvBufs[whichPutRcvBuf].param = param;
  rcvBufs[whichPutRcvBuf].funcP = funcP;
  rcvBufs[whichPutRcvBuf].len = len;
  rcvBufs[whichPutRcvBuf].dmaP = buf;
  whichPutRcvBuf ^= 1;

  if (dmaInterrupts)
    EnableInterrupt(IRQ_CHANNEL0_VEC+SA_GetChannelDMA(rcvDmaP));

  UDC_REG_WRITE(struct udccrBits,&udcP->udccr,rim,0,
		udcP->udccr.rim != 0,
		rim);

  SA_StartDMA(rcvDmaP, buf, len, dmaInterrupts && (rcvCallback != NULL));

  return 0;
}

/*----------------------------------------------------------------------
 * Usb interface transmit function. Post the buffer to the DMA
 * channel and record any callback info in the buffer info structure.
 */
static
int transmit(DM_Function_T * funcP, char * buf, int len, void * param)
{
  xmitBufs[whichPutXmitBuf].buf = buf;
  xmitBufs[whichPutXmitBuf].param = param;
  xmitBufs[whichPutXmitBuf].funcP = funcP;
  xmitBufs[whichPutXmitBuf].len = len;
  xmitBufs[whichPutXmitBuf].dmaP = buf;
  whichPutXmitBuf ^= 1;

  if (dmaInterrupts)
    EnableInterrupt(IRQ_CHANNEL0_VEC+SA_GetChannelDMA(xmitDmaP));

  if (udcP->udccr.tim)
    DM_WarnPrintf("TIM magically disabled!");

  UDC_REG_WRITE(struct udccrBits,&udcP->udccr,tim,0,
		udcP->udccr.tim != 0,
		tim);

  /* Only send one packet at a time
   */
  if (len > maxPacketSize)
    len = maxPacketSize;
  SA_StartDMA(xmitDmaP, buf, len, dmaInterrupts && (xmitCallback != NULL));

  return 0;
}

/*----------------------------------------------------------------------
 * Usb interface set callback function. Establish (or cancel) a callback
 * for buffer completion.
 */
static
int setCallback(DM_Function_T * funcP, DM_SerialCallback_T func, int reason)
{
  switch (reason) {
  case DM_SerialReceiveDone:
    rcvCallback = func;
    break;
  case DM_SerialTransmitDone:
    xmitCallback = func;
    break;
  }
  return 0;
}

/*----------------------------------------------------------------------
 * Cleanup resources
 */
static
void cleanup(DM_Function_T * funcP)
{

  /* Register an interrupt handler
   */
  UnregisterHandler(IRQ_UDC_SERVICE_REQ_VEC,
		    interruptHandler);
  udcInterruptConnected = 0;

  /* Unregister handlers for the DMA channels
   */
  UnregisterHandler(IRQ_CHANNEL0_VEC+SA_GetChannelDMA(rcvDmaP),
		    rcvHandler);
  UnregisterHandler(IRQ_CHANNEL0_VEC+SA_GetChannelDMA(xmitDmaP),
		    xmitHandler);

  /* Release the DMA channels
   */
  SA_ReleaseDMA(xmitDmaP);
  xmitDmaP = NULL;
  SA_ReleaseDMA(rcvDmaP);
  rcvDmaP = NULL;

  /* Close the timer
   */
  if (timerFuncP)
    timerP->close(timerP);
  timerFuncP = NULL;
}

/*----------------------------------------------------------------------
 * Class open function. Just return the vectors
 */
static
void * open(DM_Function_T * funcP)
{
  return NULL;
}

/*----------------------------------------------------------------------
 * Class close function. Cleanup any allocated resources.
 */
static
void close(DM_Function_T * funcP)
{
}

/*----------------------------------------------------------------------
 * Class bind function. Set the timer to use for resend.
 */
static
void bind(DM_Function_T * funcP, DM_Function_T * bindP)
{
  if (bindP->class == DM_ClassTimer)
    timerP = bindP;
}

/*----------------------------------------------------------------------
 * Class test function.
 */
static
void test(DM_Function_T * funcP)
{
  DM_DoMenu(funcP, usbBanner, usbTests);
}

void USBR_InitLoopback(void)
{
  setup(thisP,0,1); /* No interrupts w/ DMA */
}

void USBR_CheckLoopback(void)
{
  interruptHandler(NULL);
}

/*----------------------------------------------------------------------
 * Main entry point
 */
void SA11x0_USB_Init(DM_Function_T * funcP, struct udcreg * regsP)
{
  funcP->name = "USB";
  funcP->version = 1;
  funcP->class = DM_ClassUsb;
  funcP->regsP = regsP;
  funcP->subFuncs = NULL;
  funcP->find = NULL;
  funcP->bind = bind;
  funcP->open = open;
  funcP->close = close;
  funcP->test = test;

  udcP = regsP;
  thisP = funcP;
}

⌨️ 快捷键说明

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