📄 usbd_otghs.c
字号:
else if (ISSET(dStatus, AT91C_OTGHS_STALL)) {
// Non-control endpoint
// Discard stalled data
TRACE_DEBUG_L("Disc ");
pInterface->OTGHS_DEVEPTCCR[bEndpoint] = AT91C_OTGHS_RXOUT;
}
else {
// Non-control endpoint
// Nak data
TRACE_DEBUG_L("Nak ");
pInterface->OTGHS_DEVIDR = 1<<SHIFT_INTERUPT<<bEndpoint;
}
}
else {
// Endpoint is in Read state
// Retrieve data and store it into the current transfer buffer
wPacketSize = (unsigned short) ((dStatus >> 20) & 0x7FF);
TRACE_DEBUG_L("%d ", wPacketSize);
OTGHS_GetPayload(pUsb, bEndpoint, wPacketSize);
pInterface->OTGHS_DEVEPTCCR[bEndpoint] = AT91C_OTGHS_RXOUT;
pInterface->OTGHS_DEVEPTCDR[bEndpoint] = AT91C_OTGHS_FIFOCON;
if ((pEndpoint->dBytesRemaining == 0)
|| (wPacketSize < pEndpoint->wMaxPacketSize)) {
pInterface->OTGHS_DEVEPTCDR[bEndpoint] = AT91C_OTGHS_RXOUT;
// Disable interrupt if this is not a control endpoint
if ((AT91C_OTGHS_EPT_TYPE & pInterface->OTGHS_DEVEPTCFG[bEndpoint])
!= AT91C_OTGHS_EPT_TYPE_CTL_EPT) {
pInterface->OTGHS_DEVIDR = 1<<SHIFT_INTERUPT<<bEndpoint;
}
OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
}
}
}
// SETUP packet received
if(ISSET(dStatus, AT91C_OTGHS_RXSTP)) {
TRACE_DEBUG_L("Stp ");
// If a transfer was pending, complete it
// Handle the case where during the status phase of a control write
// transfer, the host receives the device ZLP and ack it, but the ack
// is not received by the device
if ((pEndpoint->dState == endpointStateWrite)
|| (pEndpoint->dState == endpointStateRead)) {
OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
}
// Copy the setup packet in S_usb
OTGHS_GetSetup(pUsb);
// Acknowledge setup packet
pInterface->OTGHS_DEVEPTCCR[bEndpoint] = AT91C_OTGHS_RXSTP;
// Forward the request to the upper layer
USB_NewRequestCallback(pUsb);
}
// STALL sent
if (ISSET(dStatus, AT91C_OTGHS_STALL)) {
TRACE_WARNING("Sta 0x%X [%d] ", dStatus, bEndpoint);
// Acknowledge STALL interrupt and disable it
pInterface->OTGHS_DEVEPTCCR[bEndpoint] = AT91C_OTGHS_STALL;
//pInterface->OTGHS_DEVEPTCDR[bEndpoint] = AT91C_OTGHS_STALL;
// If the endpoint is not halted, clear the stall condition
if (pEndpoint->dState != endpointStateHalted) {
TRACE_WARNING("_ " );
// Acknowledge the stall RQ flag
pInterface->OTGHS_DEVEPTCDR[bEndpoint] = AT91C_OTGHS_STALLRQ;
}
}
}
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// \brief Configure an endpoint with the provided endpoint descriptor
// \param pUsb Pointer to a S_usb instance
// \param pEpDesc Pointer to the endpoint descriptor
// \return true if the endpoint is now configured, false otherwise
// \see S_usb_endpoint_descriptor
// \see S_usb
//------------------------------------------------------------------------------
static bool OTGHS_ConfigureEndpoint(const S_usb *pUsb,
const S_usb_endpoint_descriptor *pEpDesc)
{
AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);
S_usb_endpoint *pEndpoint;
unsigned char bEndpoint;
unsigned char bType;
unsigned char endpointDir;
unsigned short sizeEpt = 0;
// Maximum packet size configuration value
if( pEpDesc->wMaxPacketSize == 8 ) {
sizeEpt = AT91C_OTGHS_EPT_SIZE_8;
} else if ( pEpDesc->wMaxPacketSize == 16 ) {
sizeEpt = AT91C_OTGHS_EPT_SIZE_16;
} else if ( pEpDesc->wMaxPacketSize == 32 ) {
sizeEpt = AT91C_OTGHS_EPT_SIZE_32;
} else if ( pEpDesc->wMaxPacketSize == 64 ) {
sizeEpt = AT91C_OTGHS_EPT_SIZE_64;
} else if ( pEpDesc->wMaxPacketSize == 128 ) {
sizeEpt = AT91C_OTGHS_EPT_SIZE_128;
} else if ( pEpDesc->wMaxPacketSize == 256 ) {
sizeEpt = AT91C_OTGHS_EPT_SIZE_256;
} else if ( pEpDesc->wMaxPacketSize == 512 ) {
sizeEpt = AT91C_OTGHS_EPT_SIZE_512;
} else if ( pEpDesc->wMaxPacketSize == 1024 ) {
sizeEpt = AT91C_OTGHS_EPT_SIZE_1024;
} //else {
// sizeEpt = 0; // control endpoint
//}
// if pEpDesc == 0 then initialize the control endpoint
if (pEpDesc == (S_usb_endpoint_descriptor const *) 0) {
bEndpoint = 0;
bType = 0; // Control endpoint
}
else {
// The endpoint number
bEndpoint = (unsigned char) (pEpDesc->bEndpointAddress & 0x7);
// Transfer type: Control, Isochronous, Bulk, Interrupt
bType = (unsigned char) (pEpDesc->bmAttributes & 0x3);
// Direction, ignored for control endpoints
endpointDir = (unsigned char) (pEpDesc->bEndpointAddress & (1<<7));
}
// Get pointer on endpoint
pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
if (pEndpoint == 0) {
return false;
}
// Configure wMaxPacketSize
if (pEpDesc != 0) {
pEndpoint->wMaxPacketSize = pEpDesc->wMaxPacketSize;
}
else {
pEndpoint->wMaxPacketSize = USB_ENDPOINT0_MAXPACKETSIZE;
}
// Abort the current transfer is the endpoint was configured and in
// Write or Read state
if ((pEndpoint->dState == endpointStateRead)
|| (pEndpoint->dState == endpointStateWrite)) {
OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_RESET);
}
// Enter in IDLE state
pEndpoint->dState = endpointStateIdle;
// Reset Endpoint Fifos
pInterface->OTGHS_DEVEPT |= (1<<bEndpoint<<16);
pInterface->OTGHS_DEVEPT &= ~(1<<bEndpoint<<16);
// Enable endpoint
pInterface->OTGHS_DEVEPT |= (1<<bEndpoint);
// Configure endpoint
switch (bType) {
//-------------------------
case ENDPOINT_TYPE_CONTROL:
//-------------------------
TRACE_INFO("Control[%d]\n\r",bEndpoint);
//! Configure endpoint
pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC |
AT91C_OTGHS_EPT_SIZE_64 | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_CTL_EPT | AT91C_OTGHS_BK_NUMBER_1;
// Enable RXSTP interrupt
pInterface->OTGHS_DEVEPTCER[bEndpoint] = AT91C_OTGHS_RXSTP;
// Enable endpoint IT
pInterface->OTGHS_DEVIER = 1<<SHIFT_INTERUPT<<bEndpoint;
break;
//-----------------------------
case ENDPOINT_TYPE_ISOCHRONOUS:
//-----------------------------
if (endpointDir) {
TRACE_INFO("Iso In[%d]\n\r",bEndpoint);
//! Configure endpoint
#ifndef DMA
pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC |
sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_ISO_EPT | AT91C_OTGHS_BK_NUMBER_2;
#else
pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_ISO_EPT | AT91C_OTGHS_BK_NUMBER_2;
#endif
}
else {
TRACE_INFO("Iso Out[%d]\n\r",bEndpoint);
//! Configure endpoint
#ifndef DMA
pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC |
sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_ISO_EPT | AT91C_OTGHS_BK_NUMBER_2;
#else
pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_ISO_EPT | AT91C_OTGHS_BK_NUMBER_2;
#endif
}
break;
//----------------------
case ENDPOINT_TYPE_BULK:
//----------------------
if (endpointDir) {
TRACE_INFO("Bulk In(%d)[%d] ",bEndpoint, pEpDesc->wMaxPacketSize);
//! Configure endpoint
#ifndef DMA
pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC |
sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_BUL_EPT | AT91C_OTGHS_BK_NUMBER_2;
#else
pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_BUL_EPT | AT91C_OTGHS_BK_NUMBER_2;
#endif
}
else {
TRACE_INFO("Bulk Out(%d)[%d]\n\r",bEndpoint, pEpDesc->wMaxPacketSize);
//! Configure endpoint
#ifndef DMA
pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC |
sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_BUL_EPT | AT91C_OTGHS_BK_NUMBER_2;
#else
pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_BUL_EPT | AT91C_OTGHS_BK_NUMBER_2;
#endif
}
break;
//---------------------------
case ENDPOINT_TYPE_INTERRUPT:
//---------------------------
if (endpointDir) {
TRACE_INFO("Interrupt In[%d]\n\r",bEndpoint);
//! Configure endpoint
#ifndef DMA
pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC |
sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_INT_EPT | AT91C_OTGHS_BK_NUMBER_2;
#else
pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_INT_EPT | AT91C_OTGHS_BK_NUMBER_2;
#endif
}
else {
TRACE_INFO("Interrupt Out[%d]\n\r",bEndpoint);
//! Configure endpoint
#ifndef DMA
pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC |
sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_INT_EPT | AT91C_OTGHS_BK_NUMBER_2;
#else
pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_INT_EPT | AT91C_OTGHS_BK_NUMBER_2;
#endif
}
break;
//------
default:
//------
TRACE_ERROR(" unknown endpoint type\n\r");
return false;
}
// Check if the configuration is ok
if (ISCLEARED(pInterface->OTGHS_DEVEPTCSR[bEndpoint], AT91C_OTGHS_CFGOK)) {
TRACE_FATAL("F: OTGHS_ConfigureEndpoint: Cannot configure endpoint\n\r");
return false;
}
return true;
}
//------------------------------------------------------------------------------
// Interrupt service routine
//------------------------------------------------------------------------------
#ifdef DMA
//----------------------------------------------------------------------------
//! \fn OTGHS_DmaHandler
//! \brief This function (ISR) handles DMA interrupts
//----------------------------------------------------------------------------
static void OTGHS_DmaHandler(const S_usb *pUsb, unsigned char endpoint)
{
AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);
S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, endpoint);
unsigned int csr;
csr = pInterface->OTGHS_DEVDMA[endpoint].OTGHS_DEVDMASTATUS;
pInterface->OTGHS_DEVIDR = (1<<SHIFT_DMA<<endpoint);
if((csr & AT91C_OTGHS_END_BF_ST) || (csr & AT91C_OTGHS_END_TR_ST)) {
// READ
TRACE_DEBUG_M("END_BF_ST\n\r");
pEndpoint->dBytesTransferred = pEndpoint->dBytesBuffered;
pEndpoint->dBytesBuffered = 0;
TRACE_DEBUG_M("dBytesBuffered: 0x%x\n\r",pEndpoint->dBytesBuffered);
TRACE_DEBUG_M("dBytesRemaining: 0x%x\n\r",pEndpoint->dBytesRemaining);
TRACE_DEBUG_M("dBytesTransferred: 0x%x\n\r",pEndpoint->dBytesTransferred);
OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
pEndpoint->dState = endpointStateIdle;
}
else {
TRACE_FATAL("Probleme IT DMA\n\r");
}
}
#endif
//------------------------------------------------------------------------------
// \brief OTGHS interrupt handler
//
// Manages device resume, suspend, end of bus reset. Forwards endpoint
// interrupts to the appropriate handler.
// \param pUsb Pointer to a S_usb instance
//------------------------------------------------------------------------------
static void OTGHS_Handler(const S_usb *pUsb)
{
AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);
unsigned int dStatus;
unsigned char numIT;
if ( (!ISSET(USB_GetState(pUsb), USB_STATE_SUSPENDED))
&& (ISSET(USB_GetState(pUsb), USB_STATE_POWERED))){
LED_TOGGLE(LED_USB);
}
TRACE_DEBUG_H("Hlr ");
// Get General interrupts status
dStatus = pInterface->OTGHS_SR & pInterface->OTGHS_CTRL & 0xFF;
while (dStatus != 0) {
if(ISSET(dStatus, AT91C_OTGHS_VBUSTI))
{
TRACE_DEBUG_M("__VBus\n\r");
USB_Attach(pUsb);
// Acknowledge the interrupt
pInterface->OTGHS_SCR = AT91C_OTGHS_VBUSTI;
}
// Don't treat others interrupt for this time
pInterface->OTGHS_SCR = AT91C_OTGHS_IDT | AT91C_OTGHS_SRP
| AT91C_OTGHS_VBERR | AT91C_OTGHS_BCERR
| AT91C_OTGHS_ROLEEX | AT91C_OTGHS_HNPERR
| AT91C_OTGHS_STO;
dStatus = pInterface->OTGHS_SR & pInterface->OTGHS_CTRL & 0xFF;
}
// Get OTG Device interrupts status
dStatus = pInterface->OTGHS_DEVISR & pInterface->OTGHS_DEVIMR;
TRACE_DEBUG_H("OTGHS_DEVISR:0x%X\n\r", pInterface->OTGHS_DEVISR);
while (dStatus != 0) {
// Start Of Frame (SOF)
if (ISSET(dStatus, AT91C_OTGHS_SOF)) {
TRACE_DEBUG_L("SOF ");
// Invoke the SOF callback
USB_StartOfFrameCallback(pUsb);
// Acknowledge interrupt
SET(pInterface->OTGHS_DEVICR, AT91C_OTGHS_SOF);
CLEAR(dStatus, AT91C_OTGHS_SOF);
}
// Suspend
else if (dStatus & AT91C_OTGHS_SUSP) {
TRACE_DEBUG_M("S ");
if (!ISSET(USB_GetState(pUsb), USB_STATE_SUSPENDED)) {
// The device enters the Suspended state
// MCK + UDPCK must be off
// Pull-Up must be connected
// Transceiver must be disabled
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -