📄 usbd_udphs.c
字号:
//------------------------------------------------------------------------------
void USBD_InterruptHandler(void)
{
unsigned int status;
unsigned char numIT;
if (deviceState >= USBD_STATE_POWERED) {
LED_Set(USBD_LEDUSB);
}
// Get interrupts status
status = AT91C_BASE_UDPHS->UDPHS_INTSTA & AT91C_BASE_UDPHS->UDPHS_IEN;
// Handle all UDPHS interrupts
trace_LOG(trace_DEBUG, "H");
while (status != 0) {
// Start Of Frame (SOF)
if ((status & AT91C_UDPHS_IEN_SOF) != 0) {
trace_LOG(trace_DEBUG, "SOF ");
// Invoke the SOF callback
//USB_StartOfFrameCallback(pUsb);
// Acknowledge interrupt
AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_IEN_SOF;
status &= ~AT91C_UDPHS_IEN_SOF;
}
// Suspend
// This interrupt is always treated last (hence the '==')
else if (status == AT91C_UDPHS_DET_SUSPD) {
trace_LOG(trace_DEBUG, "S");
// The device enters the Suspended state
// MCK + UDPCK must be off
// Pull-Up must be connected
// Transceiver must be disabled
LED_Clear(USBD_LEDUSB);
UDPHS_DisableBIAS();
// Enable wakeup
AT91C_BASE_UDPHS->UDPHS_IEN |= AT91C_UDPHS_WAKE_UP | AT91C_UDPHS_ENDOFRSM;
AT91C_BASE_UDPHS->UDPHS_IEN &= ~AT91C_UDPHS_DET_SUSPD;
// Acknowledge interrupt
AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_DET_SUSPD | AT91C_UDPHS_WAKE_UP;
previousDeviceState = deviceState;
deviceState = USBD_STATE_SUSPENDED;
UDPHS_DisableUsbClock();
// Invoke the Suspend callback
USBDCallbacks_Suspended();
}
// Resume
else if( ((status & AT91C_UDPHS_WAKE_UP) != 0) // line activity
|| ((status & AT91C_UDPHS_ENDOFRSM) != 0)) { // pc wakeup
//JCB
#ifdef NOT_DEFINED
#if !defined(PIN_USB_VBUS)
// Configure PIO
PIO_Configure(&pinVbus, 1);
// Check current level on VBus
if (PIO_Get(&pinVbus) == 1) // Protection
#endif
#endif
{
// Invoke the Resume callback
USBDCallbacks_Resumed();
trace_LOG(trace_DEBUG, "R");
UDPHS_EnableUsbClock();
UDPHS_EnableBIAS();
// The device enters Configured state
// MCK + UDPCK must be on
// Pull-Up must be connected
// Transceiver must be enabled
deviceState = previousDeviceState;
AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_WAKE_UP | AT91C_UDPHS_ENDOFRSM | AT91C_UDPHS_DET_SUSPD;
AT91C_BASE_UDPHS->UDPHS_IEN |= AT91C_UDPHS_ENDOFRSM | AT91C_UDPHS_DET_SUSPD;
AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_WAKE_UP | AT91C_UDPHS_ENDOFRSM;
AT91C_BASE_UDPHS->UDPHS_IEN &= ~AT91C_UDPHS_WAKE_UP;
}
// jcb !!!
#ifdef NOT_DEFINED
#if !defined(PIN_USB_VBUS)
else {
// No VBUS
// Disconnect the pull-up
USBD_Disconnect();
AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_WAKE_UP;
}
#endif
#endif
}
// End of bus reset
else if ((status & AT91C_UDPHS_ENDRESET) == AT91C_UDPHS_ENDRESET) {
// trace_LOG(trace_DEBUG, "EoB ");
// The device enters the Default state
deviceState = USBD_STATE_DEFAULT;
// MCK + UDPCK are already enabled
// Pull-Up is already connected
// Transceiver must be enabled
// Endpoint 0 must be enabled
UDPHS_ResetEndpoints();
UDPHS_DisableEndpoints();
USBD_ConfigureEndpoint(0);
// Flush and enable the Suspend interrupt
AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_WAKE_UP | AT91C_UDPHS_DET_SUSPD;
//// Enable the Start Of Frame (SOF) interrupt if needed
//if (pCallbacks->startOfFrame != 0)
//{
// AT91C_BASE_UDPHS->UDPHS_IEN |= AT91C_UDPHS_IEN_SOF;
//}
// Invoke the Reset callback
USBDCallbacks_Reset();
// Acknowledge end of bus reset interrupt
AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_ENDRESET;
AT91C_BASE_UDPHS->UDPHS_IEN |= AT91C_UDPHS_DET_SUSPD;
}
// Handle upstream resume interrupt
else if (status & AT91C_UDPHS_UPSTR_RES) {
trace_LOG(trace_DEBUG, "ExtRes ");
// - Acknowledge the IT
AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_UPSTR_RES;
}
// Endpoint interrupts
else {
#ifndef DMA
// Handle endpoint interrupts
for (numIT = 0; numIT < NUM_IT_MAX; numIT++) {
if ((status & (1 << SHIFT_INTERUPT << numIT)) != 0) {
UDPHS_EndpointHandler(numIT);
}
}
#else
// Handle endpoint control interrupt
if ((status & (1 << SHIFT_INTERUPT << 0)) != 0) {
UDPHS_EndpointHandler( 0 );
}
else {
numIT = 1;
while((status&(0x7E<<SHIFT_DMA)) != 0) {
// Check if endpoint has a pending interrupt
if ((status & (1 << SHIFT_DMA << numIT)) != 0) {
UDPHS_DmaHandler(numIT);
status &= ~(1 << SHIFT_DMA << numIT);
if (status != 0) {
trace_LOG(trace_INFO, "\n\r - ");
}
}
numIT++;
}
}
#endif
}
// Retrieve new interrupt status
status = AT91C_BASE_UDPHS->UDPHS_INTSTA & AT91C_BASE_UDPHS->UDPHS_IEN;
trace_LOG(trace_DEBUG, "\n\r");
if (status != 0) {
trace_LOG(trace_DEBUG, " - ");
}
}
if (deviceState >= USBD_STATE_POWERED) {
LED_Clear(USBD_LEDUSB);
}
}
//------------------------------------------------------------------------------
// Configure an endpoint with the provided endpoint descriptor
// pDdescriptor Pointer to the endpoint descriptor
//
//------------------------------------------------------------------------------
void USBD_ConfigureEndpoint(const USBEndpointDescriptor *pDescriptor)
{
Endpoint *pEndpoint;
unsigned char bEndpoint;
unsigned char bType;
unsigned char bEndpointDir;
unsigned char bSizeEpt = 0;
// NULL descriptor -> Control endpoint 0
if (pDescriptor == 0) {
bEndpoint = 0;
pEndpoint = &(endpoints[bEndpoint]);
bType = USBEndpointDescriptor_CONTROL;
bEndpointDir = 0;
pEndpoint->size = BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0);
pEndpoint->bank = BOARD_USB_ENDPOINTS_BANKS(0);
}
else {
// The endpoint number
bEndpoint = USBEndpointDescriptor_GetNumber(pDescriptor);
pEndpoint = &(endpoints[bEndpoint]);
// Transfer type: Control, Isochronous, Bulk, Interrupt
bType = USBEndpointDescriptor_GetType(pDescriptor);
// Direction, ignored for control endpoints
bEndpointDir = USBEndpointDescriptor_GetDirection(pDescriptor);
pEndpoint->size = USBEndpointDescriptor_GetMaxPacketSize(pDescriptor);
pEndpoint->bank = BOARD_USB_ENDPOINTS_BANKS(bEndpoint);
}
// Abort the current transfer is the endpoint was configured and in
// Write or Read state
if( (pEndpoint->state == UDP_ENDPOINT_RECEIVING)
|| (pEndpoint->state == UDP_ENDPOINT_SENDING) ) {
UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_RESET);
}
pEndpoint->state = UDP_ENDPOINT_IDLE;
// Disable endpoint
AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLDIS = AT91C_UDPHS_SHRT_PCKT
| AT91C_UDPHS_BUSY_BANK
| AT91C_UDPHS_NAK_OUT
| AT91C_UDPHS_NAK_IN
| AT91C_UDPHS_STALL_SNT
| AT91C_UDPHS_RX_SETUP
| AT91C_UDPHS_TX_PK_RDY
| AT91C_UDPHS_TX_COMPLT
| AT91C_UDPHS_RX_BK_RDY
| AT91C_UDPHS_ERR_OVFLW
| AT91C_UDPHS_MDATA_RX
| AT91C_UDPHS_DATAX_RX
| AT91C_UDPHS_NYET_DIS
| AT91C_UDPHS_INTDIS_DMA
| AT91C_UDPHS_AUTO_VALID
| AT91C_UDPHS_EPT_DISABL;
// Reset Endpoint Fifos
AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_TOGGLESQ | AT91C_UDPHS_FRCESTALL;
AT91C_BASE_UDPHS->UDPHS_EPTRST = 1<<bEndpoint;
// Configure endpoint
if( pEndpoint->size == 8 ) {
bSizeEpt = 0;
}
else if ( pEndpoint->size == 16 ) {
bSizeEpt = 1;
}
else if ( pEndpoint->size == 32 ) {
bSizeEpt = 2;
}
else if ( pEndpoint->size == 64 ) {
bSizeEpt = 3;
}
else if ( pEndpoint->size == 128 ) {
bSizeEpt = 4;
}
else if ( pEndpoint->size == 256 ) {
bSizeEpt = 5;
}
else if ( pEndpoint->size == 512 ) {
bSizeEpt = 6;
}
else if ( pEndpoint->size == 1024 ) {
bSizeEpt = 7;
} //else {
// sizeEpt = 0; // control endpoint
//}
// Configure endpoint
if (bType == USBEndpointDescriptor_CONTROL) {
// Enable endpoint IT for control endpoint
AT91C_BASE_UDPHS->UDPHS_IEN |= (1<<SHIFT_INTERUPT<<bEndpoint);
}
AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG = bSizeEpt
| (bEndpointDir << 3)
| (bType << 4)
| ((pEndpoint->bank) << 6);
while( (signed int)AT91C_UDPHS_EPT_MAPD != (signed int)((AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG) & AT91C_UDPHS_EPT_MAPD) ) {
// resolved by clearing the reset IT in good place
trace_LOG(trace_ERROR, "PB bEndpoint: 0x%X\n\r", bEndpoint);
trace_LOG(trace_ERROR, "PB bSizeEpt: 0x%X\n\r", bSizeEpt);
trace_LOG(trace_ERROR, "PB bEndpointDir: 0x%X\n\r", bEndpointDir);
trace_LOG(trace_ERROR, "PB bType: 0x%X\n\r", bType);
trace_LOG(trace_ERROR, "PB pEndpoint->bank: 0x%X\n\r", pEndpoint->bank);
trace_LOG(trace_ERROR, "PB UDPHS_EPTCFG: 0x%X\n\r", AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG);
for(;;);
}
if (bType == USBEndpointDescriptor_CONTROL) {
AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_RX_BK_RDY
| AT91C_UDPHS_RX_SETUP
| AT91C_UDPHS_EPT_ENABL;
}
else {
#ifndef DMA
AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_EPT_ENABL;
#else
AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_AUTO_VALID
| AT91C_UDPHS_EPT_ENABL;
#endif
}
}
//------------------------------------------------------------------------------
// Sends data through an USB endpoint (IN)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -