Example #1
0
static void rxData(unsigned char epNum, unsigned rxMask)
{
	DEBUGMSG( "rxMask " ); DEBUGHEX( rxMask ); DEBUGMSG( "\r\n" );
	unsigned readyCount = (0 != (rxMask & AT91C_UDP_RX_DATA_BK0) );
	readyCount += ( 0 != (rxMask & AT91C_UDP_RX_DATA_BK1) );
	
	struct endpointDetails_t *const ep = &connections[epNum];
	if( 2 == readyCount ){
		rxMask = ep->pingPong ^ 0x42 ;
		if( 0 == rxMask ){
			UDP_CLEAREPFLAGS( UDP->UDP_CSR+epNum, rxMask );
			DEBUGMSG( "double rx on first go-round\r\n" );
			return ;
		}
	}
	ep->pingPong = rxMask ; // keep track of last
	
	unsigned short rxLength = ( UDP->UDP_CSR[epNum] >> 16 ) & 0x7FF ;
	if( ep->rx_data ){
		assert( endpointMaxSize[epNum] >= rxLength );
		unsigned i ;
		unsigned char volatile *const fifo = (unsigned char *)&UDP->UDP_FDR[epNum];
		for( i = 0 ; i < rxLength ; i++ ){
			ep->rx_data[i] = *fifo ;
		}
		assert( ep->rx_callback );
		ep->rx_callback( ep->rx_opaque, epNum, ep->rx_data, rxLength );
	} // read if somebody's listening
	
	UDP_CLEAREPFLAGS( UDP->UDP_CSR+epNum, rxMask );
}
Example #2
0
static void transmitComplete( unsigned char epNum )
{
if( 0 )// != epNum )
	NODEBUGMSG( "TXCOMP\r\n" );
	struct endpointDetails_t *const ep = &connections[epNum];
	struct transmitRequest_t *tx = (ep->txTake != ep->txAdd)  ? ep->txQueue + ep->txTake : 0 ;
	struct transmitRequest_t *firstTx = tx ;
	int completed = 0 ;

	ep->txState = EPTX_IDLE ;

	if( tx && tx->txNext && SG_END(tx->txNext) ){
		if( tx->flags & NEEDNULLTX ){
			DEBUGMSG( "NULL tx\r\n" );
                        tx->flags &= ~NEEDNULLTX ;
		}
		else {
			if( tx->callback )
				tx->callback( tx->opaque, epNum, tx->txStart );
			memset( tx, 0, sizeof(*tx) ); // kill pointers
			ep->txTake++ ;
			if( ep->txTake > MAXTX_ENTRIES )
				ep->txTake = 0 ;
		}
	} // done with previous request

	tx = (ep->txTake != ep->txAdd) ? ep->txQueue + ep->txTake : 0 ;
	if( 0 ){ // tx
		DEBUGMSG( "multi-tx 0x" ); DEBUGHEX( sg_len(tx->txStart) ); DEBUGMSG( " bytes\r\n" );
		dump_sg( tx->txStart );
	}

	if( tx ){
		if( firstTx == tx )
			continueTransmit(epNum,tx);
		else {
                        UDP_CLEAREPFLAGS(UDP->UDP_CSR+epNum, AT91C_UDP_TXCOMP);
			DEBUGMSG( "nextTx 0x" ); DEBUGHEX( sg_len(tx->txStart) ); DEBUGMSG("\r\n");
			startTransmit(epNum,tx);
                        completed = 1 ;
		}
	}
	else {
		assert(ep->txTake == ep->txAdd);
	}

	if( !completed )
		UDP_CLEAREPFLAGS(UDP->UDP_CSR+epNum, AT91C_UDP_TXCOMP);
}
Example #3
0
void usbll_resume( unsigned bEndpoint )
{
	UDP_CLEAREPFLAGS(UDP->UDP_CSR + bEndpoint, AT91C_UDP_FORCESTALL);
	
	// Reset Endpoint Fifos, beware this is a 2 steps operation
	UDP->UDP_RSTEP |= 1 << bEndpoint;
	UDP->UDP_RSTEP &= ~(1 << bEndpoint);
}
Example #4
0
int
udp_read(U8* buf, int off, int len)
{
  /* Perform a non-blocking read operation. We use double buffering (ping-pong)
   * operation to provide better throughput.
   */
  int packetSize = 0, i;
  
  if (len == 0) return 0;
  if ((*AT91C_UDP_CSR1) & currentRxBank) // data to read
  {
    packetSize = ((*AT91C_UDP_CSR1) & AT91C_UDP_RXBYTECNT) >> 16;
    if (packetSize > len) packetSize = len;
    // Transfer the data 
    for(i=0;i<packetSize;i++) buf[off+i] = *AT91C_UDP_FDR1;

    // Flip bank
    ENTER();
    UDP_CLEAREPFLAGS(*AT91C_UDP_CSR1, currentRxBank); 
    if (currentRxBank == AT91C_UDP_RX_DATA_BK0) {    
      currentRxBank = AT91C_UDP_RX_DATA_BK1;
    } else {
      currentRxBank = AT91C_UDP_RX_DATA_BK0;
    }
    // We may have an enable/reset pending do it now if there is no data
    // in the buffers.
    if (delayedEnable && ((*AT91C_UDP_CSR1) & AT91C_UDP_RXBYTECNT) == 0)
    {
      delayedEnable = 0;
      UDP_CLEAREPFLAGS(*AT91C_UDP_CSR1, AT91C_UDP_FORCESTALL);
      (*AT91C_UDP_RSTEP) |= AT91C_UDP_EP1;
      (*AT91C_UDP_RSTEP) &= ~AT91C_UDP_EP1;
    }
    LEAVE();

    // use special case for a real zero length packet so we can use it to
    // indicate EOF
    if (packetSize == 0) return -2;
    return packetSize;
  }
Example #5
0
static void abortTransmitter(unsigned epNum)
{
	struct endpointDetails_t *const ep = &connections[epNum];
	while(ep->txTake != ep->txAdd){
		struct transmitRequest_t *tx = ep->txQueue + ep->txTake ;
		ep->txTake++ ;
		if( ep->txTake > MAXTX_ENTRIES )
			ep->txTake = 0 ;
		usbll_tx_callback_t callback = tx->callback ;
		if( callback )
			callback( tx->opaque, epNum, tx->txStart );
		memset( tx, 0, sizeof(*tx) ); // kill pointers
	}
	ep->txState = EPTX_IDLE ;
	UDP_CLEAREPFLAGS(UDP->UDP_CSR+epNum, AT91C_UDP_TXCOMP|AT91C_UDP_TXPKTRDY);
}
Example #6
0
//------------------------------------------------------------------------------
// \brief  Clears the correct RX flag in an endpoint status register
// \param  pUsb      Pointer to a S_usb instance
// \param  bEndpoint Index of endpoint
// \see    S_usb_endpoint
// \see    S_usb
//------------------------------------------------------------------------------
static void UDP_ClearRXFlag(const S_usb * pUsb,
                            unsigned char bEndpoint)
{
    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);

    // Clear flag
    UDP_CLEAREPFLAGS(pUsb, bEndpoint, pEndpoint->dFlag);

    // Swap banks
    if (pEndpoint->dFlag == AT91C_UDP_RX_DATA_BK0) {

        if (pEndpoint->dNumFIFO > 1) {

            // Swap bank if in dual-fifo mode
            pEndpoint->dFlag = AT91C_UDP_RX_DATA_BK1;
        }
    }
    else {

        pEndpoint->dFlag = AT91C_UDP_RX_DATA_BK0;
    }
}
Example #7
0
/* called by the main application to poll for events */
void usbll_poll( void )
{
	int epNum ;
	unsigned gstate ;
	unsigned isr = UDP->UDP_ISR ;
	if( isr != prevISR ){
		prevISR = isr ;
	}
	
	if( isr & AT91C_UDP_EPINT0 ){
		UDP->UDP_ICR = AT91C_UDP_EPINT0 ;
	}

	if( isr & AT91C_UDP_WAKEUP ){
		DEBUGMSG( "UDP_WAKEUP\r\n" );
		UDP->UDP_ICR = AT91C_UDP_WAKEUP ;
	}

	if( isr & AT91C_UDP_RXRSM ){
		DEBUGMSG( "UDP_RXRSM\r\n" );
		UDP->UDP_ICR = AT91C_UDP_RXRSM ;
	}

	if( isr & AT91C_UDP_EXTRSM ){
		DEBUGMSG( "UDP_EXTRSM\r\n" );
		UDP->UDP_ICR = AT91C_UDP_EXTRSM ;
	}

	if( isr & AT91C_UDP_SOFINT ){
//		DEBUGMSG( "UDP_SOFINT\r\n" );
		UDP->UDP_ICR = AT91C_UDP_SOFINT ;
	}

	if( isr & AT91C_UDP_ENDBUSRES ){
//		write( DEFUART, "GLBSTATE == " ); writeHex( DEFUART, UDP->UDP_GLBSTATE ); write( DEFUART, "\r\n" );
		UDP->UDP_FADDR = AT91C_UDP_FEN ;
		UDP_CLEAREPFLAGS(&UDP->UDP_GLBSTATE,AT91C_UDP_CONFG|AT91C_UDP_FADDEN);
		UDP->UDP_RSTEP = 0xffffffff ;
		UDP->UDP_RSTEP = 0 ;
		UDP_SETEPFLAGS(UDP->UDP_CSR + 0, AT91C_UDP_EPEDS);
                UDP_CLEAREPFLAGS(UDP->UDP_CSR + 0, AT91C_UDP_DIR);
		UDP->UDP_ICR = AT91C_UDP_ENDBUSRES ;
		abortTransmitters();
//		write( DEFUART, "UDP_ENDBUSRES 0x" );writeHex( DEFUART, UDP->UDP_GLBSTATE ); write( DEFUART, "\r\n" );
	}

	gstate = UDP->UDP_GLBSTATE; 

	for( epNum = 0 ; epNum < UDP_MAXENDPOINTS ; epNum++ ){
		unsigned int dStatus = UDP->UDP_CSR[epNum];

		if( dStatus & AT91C_UDP_TXCOMP ){
			transmitComplete(epNum);
		} // transmit completed

		if( dStatus & AT91C_UDP_RXSETUP ){
			unsigned char setupBuf[16];
			unsigned short rxLength = ( dStatus >> 16 ) & 0x7FF ;
			if( sizeof(struct S_usb_request) <= rxLength ){
                                struct S_usb_request const *rxSetup = (struct S_usb_request const *)setupBuf ;
                                rxLength = sizeof(*rxSetup);
				unsigned i ;
                                unsigned char volatile *const fifo = (unsigned char *)&UDP->UDP_FDR[epNum];
				for( i = 0 ; i < rxLength ; i++ ){
					setupBuf[i] = *fifo ;
				}
				if( rxSetup->bmRequestType & 0x80) {
					UDP_SETEPFLAGS(UDP->UDP_CSR + epNum, AT91C_UDP_DIR);
				}

				UDP_CLEAREPFLAGS(UDP->UDP_CSR + epNum, AT91C_UDP_RXSETUP);

				if( 0 != (UDP->UDP_CSR[epNum] & (AT91C_UDP_TXPKTRDY|AT91C_UDP_TXCOMP|AT91C_UDP_STALLSENT)) ){
					write( DEFUART, "rxSetup: txPending\r\n" );
				}

				if( setupCallback ){
					completeTransmit(epNum);
					setupCallback( setupOpaque, setupBuf, rxLength );
				}
			}
			else {
				write( DEFUART, "rxSetup too small 0x" ); writeHexChar( DEFUART, rxLength ); write( DEFUART, "\r\n" );
				UDP_CLEAREPFLAGS(UDP->UDP_CSR + epNum, AT91C_UDP_RXSETUP);
			}
		}
		
		if( dStatus & AT91C_UDP_STALLSENT ){
			UDP_CLEAREPFLAGS(UDP->UDP_CSR + epNum, AT91C_UDP_STALLSENT);
		}

		unsigned int rxMask = dStatus & (AT91C_UDP_RX_DATA_BK0|AT91C_UDP_RX_DATA_BK1);
		if( rxMask ){
			rxData(epNum,rxMask);
		} // received something
	}
Example #8
0
//------------------------------------------------------------------------------
// \brief  Endpoint interrupt handler.
//
//         Handle IN/OUT transfers, received SETUP packets and STALLing
// \param  pUsb      Pointer to a S_usb instance
// \param  bEndpoint Index of endpoint
// \see    S_usb
//------------------------------------------------------------------------------
static void UDP_EndpointHandler(const S_usb *pUsb, unsigned char bEndpoint)
{
    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
    AT91PS_UDP pInterface = UDP_GetDriverInterface(pUsb);
    unsigned int dStatus = pInterface->UDP_CSR[bEndpoint];

    TRACE_DEBUG_L("Ept%d ", bEndpoint);

    // Handle interrupts
    // IN packet sent
    if (ISSET(dStatus, AT91C_UDP_TXCOMP)) {

        TRACE_DEBUG_L("Wr ");

        // Check that endpoint was in Write state
        if (pEndpoint->dState == endpointStateWrite) {

            // End of transfer ?
            if ((pEndpoint->dBytesBuffered < pEndpoint->wMaxPacketSize)
                ||
                (!ISCLEARED(dStatus, AT91C_UDP_EPTYPE)
                 && (pEndpoint->dBytesRemaining == 0)
                 && (pEndpoint->dBytesBuffered == pEndpoint->wMaxPacketSize))) {

                TRACE_DEBUG_L("%d ", pEndpoint->dBytesBuffered);

                pEndpoint->dBytesTransferred += pEndpoint->dBytesBuffered;
                pEndpoint->dBytesBuffered = 0;

                // Disable interrupt if this is not a control endpoint
                if (!ISCLEARED(dStatus, AT91C_UDP_EPTYPE)) {

                    SET(pInterface->UDP_IDR, 1 << bEndpoint);
                }

                UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
            }
            else {

                // Transfer remaining data
                TRACE_DEBUG_L("%d ", pEndpoint->wMaxPacketSize);

                pEndpoint->dBytesTransferred += pEndpoint->wMaxPacketSize;
                pEndpoint->dBytesBuffered -= pEndpoint->wMaxPacketSize;

                // Send next packet
                if (pEndpoint->dNumFIFO == 1) {

                    // No double buffering
                    UDP_WritePayload(pUsb, bEndpoint);
                    UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXPKTRDY);
                }
                else {

                    // Double buffering
                    UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXPKTRDY);
                    UDP_WritePayload(pUsb, bEndpoint);
                }
            }
        }

        // Acknowledge interrupt
        UDP_CLEAREPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXCOMP);
    }
    // OUT packet received
    if (ISSET(dStatus, AT91C_UDP_RX_DATA_BK0)
        || ISSET(dStatus, AT91C_UDP_RX_DATA_BK1)) {

        TRACE_DEBUG_L("Rd ");

        // Check that the endpoint is in Read state
        if (pEndpoint->dState != endpointStateRead) {

            // Endpoint is NOT in Read state
            if (ISCLEARED(dStatus, AT91C_UDP_EPTYPE)
                && ISCLEARED(dStatus, 0xFFFF0000)) {

                // Control endpoint, 0 bytes received
                // Acknowledge the data and finish the current transfer
                TRACE_DEBUG_L("Ack ");
                UDP_ClearRXFlag(pUsb, bEndpoint);

                UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
            }
            else if (ISSET(dStatus, AT91C_UDP_FORCESTALL)) {

                // Non-control endpoint
                // Discard stalled data
                TRACE_DEBUG_L("Disc ");
                UDP_ClearRXFlag(pUsb, bEndpoint);
            }
            else {

                // Non-control endpoint
                // Nak data
                TRACE_DEBUG_L("Nak ");
                SET(pInterface->UDP_IDR, 1 << bEndpoint);
            }
        }
        else {

            // Endpoint is in Read state
            // Retrieve data and store it into the current transfer buffer
            unsigned short wPacketSize = (unsigned short) (dStatus >> 16);

            TRACE_DEBUG_L("%d ", wPacketSize);

            UDP_GetPayload(pUsb, bEndpoint, wPacketSize);
            UDP_ClearRXFlag(pUsb, bEndpoint);

            if ((pEndpoint->dBytesRemaining == 0)
                || (wPacketSize < pEndpoint->wMaxPacketSize)) {

                // Disable interrupt if this is not a control endpoint
                if (!ISCLEARED(dStatus, AT91C_UDP_EPTYPE)) {

                    SET(pInterface->UDP_IDR, 1 << bEndpoint);
                }

                UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
            }
        }
    }