static void startTransmit(unsigned epNum, struct transmitRequest_t *tx) { unsigned total = fillOutput(epNum,tx); if( 0 == ( UDP->UDP_CSR[epNum] & AT91C_UDP_TXPKTRDY ) ){ UDP_SETEPFLAGS(UDP->UDP_CSR+epNum, AT91C_UDP_TXPKTRDY ); connections[epNum].txState = EPTX_WAITCOMP ; if( USBEP_BULKIN == epNum ) total += fillOutput(epNum,tx); if( 0 )// != epNum ) { NODEBUGMSG( "extra 0x" ); NODEBUGHEX( total ); NODEBUGMSG( "\r\n" ); } } else { write( DEFUART, "PKTRDY already set for ep 0x" ); writeHexChar( DEFUART, epNum ); write( DEFUART, "\r\n" ); } DEBUGMSG( "~txPacket: 0x" ); DEBUGHEX(tx->txNext->length-tx->txNext->offset); DEBUGMSG( "\r\n" ); }
/* 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 }
void usbll_halt( unsigned bEndpoint ) { UDP_SETEPFLAGS(UDP->UDP_CSR + bEndpoint, AT91C_UDP_FORCESTALL); }
//------------------------------------------------------------------------------ // \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); } } }