📄 usbd_udphs.c
字号:
// Sets up the transfer descriptor, write one or two data payloads
// (depending on the number of FIFO banks for the endpoint) and then
// starts the actual transfer. The operation is complete when all
// the data has been sent.
//------------------------------------------------------------------------------
char USBD_Write( unsigned char bEndpoint,
const void *pData,
unsigned int dLength,
TransferCallback fCallback,
void *pArgument )
{
Endpoint *pEndpoint = &(endpoints[bEndpoint]);
Transfer *pTransfer = &(pEndpoint->transfer);
// Return if the endpoint is not in IDLE state
if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
return USBD_STATUS_LOCKED;
}
trace_LOG(trace_DEBUG, "Write%d(%d) ", bEndpoint, dLength);
// Setup the transfer descriptor
pTransfer->pData = (void *) pData;
pTransfer->remaining = dLength;
pTransfer->buffered = 0;
pTransfer->transferred = 0;
pTransfer->fCallback = fCallback;
pTransfer->pArgument = pArgument;
// Send one packet
pEndpoint->state = UDP_ENDPOINT_SENDING;
#ifdef DMA
// Test if endpoint type control
if(AT91C_UDPHS_EPT_TYPE_CTL_EPT == (AT91C_UDPHS_EPT_TYPE&(AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG))) {
#endif
// Send the first packet
UDPHS_WritePayload(bEndpoint);
AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSETSTA = AT91C_UDPHS_TX_PK_RDY;
// If double buffering is enabled and there is data remaining,
// prepare another packet
if( (BOARD_USB_ENDPOINTS_BANKS(bEndpoint) > 1) && (pTransfer->remaining > 0) ) {
UDPHS_WritePayload( bEndpoint );
}
// Enable endpoint IT
AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_INTERUPT << bEndpoint);
AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_TX_PK_RDY;
#ifdef DMA
}
else {
// Others endpoints (not control)
if( pTransfer->remaining > DMA_MAX_FIFO_SIZE ) {
// Transfer the max
pTransfer->buffered = DMA_MAX_FIFO_SIZE;
}
else {
// Transfer the good size
pTransfer->buffered = pTransfer->remaining;
}
trace_LOG(trace_DEBUG, "\n\r_WR:%d ", pTransfer->remaining );
trace_LOG(trace_DEBUG, "B:%d ", pTransfer->buffered );
trace_LOG(trace_DEBUG, "T:%d ", pTransfer->transferred );
AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMAADDRESS = (unsigned int)(pTransfer->pData);
// Clear unwanted interrupts
AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;
// Enable DMA endpoint interrupt
AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_DMA << bEndpoint);
// DMA config
AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0; // raz
AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL =
( ((pTransfer->buffered << 16) & AT91C_UDPHS_BUFF_COUNT)
| AT91C_UDPHS_END_B_EN
| AT91C_UDPHS_END_BUFFIT
| AT91C_UDPHS_CHANN_ENB );
}
#endif
return USBD_STATUS_SUCCESS;
}
//------------------------------------------------------------------------------
// Reads incoming data on an USB endpoint (OUT)
//------------------------------------------------------------------------------
char USBD_Read( unsigned char bEndpoint,
void *pData,
unsigned int dLength,
TransferCallback fCallback,
void *pArgument )
{
Endpoint *pEndpoint = &(endpoints[bEndpoint]);
Transfer *pTransfer = &(pEndpoint->transfer);
// Return if the endpoint is not in IDLE state
if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
return USBD_STATUS_LOCKED;
}
trace_LOG(trace_DEBUG, "Read%d(%d) ", bEndpoint, dLength);
// Endpoint enters Receiving state
pEndpoint->state = UDP_ENDPOINT_RECEIVING;
// Set the transfer descriptor
pTransfer->pData = pData;
pTransfer->remaining = dLength;
pTransfer->buffered = 0;
pTransfer->transferred = 0;
pTransfer->fCallback = fCallback;
pTransfer->pArgument = pArgument;
#ifdef DMA
// Test if endpoint type control
if(AT91C_UDPHS_EPT_TYPE_CTL_EPT == (AT91C_UDPHS_EPT_TYPE&(AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG))) {
#endif
// Control endpoint
// Enable endpoint IT
AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_INTERUPT << bEndpoint);
AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_RX_BK_RDY;
#ifdef DMA
}
else {
trace_LOG(trace_DEBUG, "Read%d(%d) ", bEndpoint, dLength);
// Others endpoints (not control)
if( pTransfer->remaining > DMA_MAX_FIFO_SIZE ) {
// Transfer the max
pTransfer->buffered = DMA_MAX_FIFO_SIZE;
}
else {
// Transfer the good size
pTransfer->buffered = pTransfer->remaining;
}
AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMAADDRESS = (unsigned int)(pTransfer->pData);
// Clear unwanted interrupts
AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;
// Enable DMA endpoint interrupt
AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_DMA << bEndpoint);
trace_LOG(trace_DEBUG, "\n\r_RR:%d ", pTransfer->remaining );
trace_LOG(trace_DEBUG, "B:%d ", pTransfer->buffered );
trace_LOG(trace_DEBUG, "T:%d ", pTransfer->transferred );
// DMA config
AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0; // raz
AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL =
( ((pTransfer->buffered << 16) & AT91C_UDPHS_BUFF_COUNT)
| AT91C_UDPHS_END_TR_EN
| AT91C_UDPHS_END_TR_IT
| AT91C_UDPHS_END_B_EN
| AT91C_UDPHS_END_BUFFIT
| AT91C_UDPHS_CHANN_ENB );
}
#endif
return USBD_STATUS_SUCCESS;
}
//------------------------------------------------------------------------------
// Clears, sets or returns the Halt state on specified endpoint
//
// When in Halt state, an endpoint acknowledges every received packet
// with a STALL handshake. This continues until the endpoint is
// manually put out of the Halt state by calling this function.
// pUsb Pointer to a S_usb instance
// bEndpoint Index of endpoint
// bRequest Request to perform
// -> USB_SET_FEATURE, USB_CLEAR_FEATURE, USB_GET_STATUS
// \return true if the endpoint is currently Halted, false otherwise
//
//------------------------------------------------------------------------------
void USBD_Halt( unsigned char bEndpoint )
{
Endpoint *pEndpoint = &(endpoints[bEndpoint]);
// Check that endpoint is enabled and not already in Halt state
if( (pEndpoint->state != UDP_ENDPOINT_DISABLED)
&& (pEndpoint->state != UDP_ENDPOINT_HALTED) ) {
trace_LOG(trace_DEBUG, "Halt%d ", bEndpoint);
// Abort the current transfer if necessary
UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);
// Put endpoint into Halt state
AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSETSTA = AT91C_UDPHS_FRCESTALL;
pEndpoint->state = UDP_ENDPOINT_HALTED;
#ifdef DMA
// Test if endpoint type control
if(AT91C_UDPHS_EPT_TYPE_CTL_EPT == (AT91C_UDPHS_EPT_TYPE&(AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG))) {
#endif
// Enable the endpoint interrupt
AT91C_BASE_UDPHS->UDPHS_IEN |= (1<<SHIFT_INTERUPT<<bEndpoint);
#ifdef DMA
}
else {
// Enable IT DMA
AT91C_BASE_UDPHS->UDPHS_IEN |= (1<<SHIFT_DMA<<bEndpoint);
}
#endif
}
}
//------------------------------------------------------------------------------
// Function: USBD_Unhalt
// Clears the Halt feature on the given endpoint.
//------------------------------------------------------------------------------
void USBD_Unhalt( unsigned char bEndpoint )
{
Endpoint *pEndpoint = &(endpoints[bEndpoint]);
// Check if the endpoint is enabled
if (pEndpoint->state != UDP_ENDPOINT_DISABLED) {
trace_LOG(trace_DEBUG, "Unhalt%d ", bEndpoint);
// Return endpoint to Idle state
pEndpoint->state = UDP_ENDPOINT_IDLE;
// Clear FORCESTALL flag
AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_TOGGLESQ | AT91C_UDPHS_FRCESTALL;
// Reset Endpoint Fifos
AT91C_BASE_UDPHS->UDPHS_EPTRST = (1<<bEndpoint);
}
}
//------------------------------------------------------------------------------
// Function: USBD_IsHalted
// Returns the current Halt status of an endpoint.
//
// Parameters:
// bEndpoint - Endpoint number.
//
// Returns:
// 1 if the endpoint is currently halted; otherwise 0.
//------------------------------------------------------------------------------
unsigned char USBD_IsHalted( unsigned char bEndpoint )
{
Endpoint *pEndpoint = &(endpoints[bEndpoint]);
unsigned char status = 0;
if (pEndpoint->state == UDP_ENDPOINT_HALTED) {
status = 1;
}
return( status );
}
//------------------------------------------------------------------------------
// IS High Speed device working in High Speed ?
//------------------------------------------------------------------------------
unsigned char USBD_IsHighSpeed( void )
{
unsigned char status = 0;
if( AT91C_UDPHS_SPEED == (AT91C_BASE_UDPHS->UDPHS_INTSTA & AT91C_UDPHS_SPEED) )
{
// High Speed
trace_LOG(trace_DEBUG, "High Speed\n\r");
status = 1;
}
else {
trace_LOG(trace_DEBUG, "Full Speed\n\r");
}
return( status );
}
//------------------------------------------------------------------------------
// Causes the endpoint to acknowledge the next received packet with
// a STALL handshake.
// Further packets are then handled normally.
// bEndpoint Index of endpoint
// \return Operation result code
//------------------------------------------------------------------------------
unsigned char USBD_Stall( unsigned char bEndpoint )
{
Endpoint *pEndpoint = &(endpoints[bEndpoint]);
// Check that endpoint is in Idle state
if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
trace_LOG(trace_WARNING, "W: UDP_Stall: Endpoint%d locked\n\r", bEndpoint);
return USBD_STATUS_LOCKED;
}
trace_LOG(trace_DEBUG, "Stall%d ", bEndpoint);
AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSETSTA = AT91C_UDPHS_FRCESTALL;
return USBD_STATUS_SUCCESS;
}
//------------------------------------------------------------------------------
// Activates a remote wakeup procedure
//------------------------------------------------------------------------------
void USBD_RemoteWakeUp(void)
{
trace_LOG(trace_DEBUG, "Remote WakeUp\n\r");
// Device is currently suspended
if (deviceState == USBD_STATE_SUSPENDED) {
trace_LOG(trace_DEBUG, "RW\n\r");
UDPHS_EnableUsbClock();
// Activates a remote wakeup
AT91C_BASE_UDPHS->UDPHS_CTRL |= AT91C_UDPHS_REWAKEUP;
while ((AT91C_BASE_UDPHS->UDPHS_CTRL&AT91C_UDPHS_REWAKEUP) == AT91C_UDPHS_REWAKEUP) {
trace_LOG(trace_DEBUG, "W");
}
UDPHS_EnableBIAS();
}
// Device is NOT suspended
else {
trace_LOG(trace_WARNING, "-W- USBD_RemoteWakeUp: Device is not suspended\n\r");
}
}
//------------------------------------------------------------------------------
// Sets or unsets the device address
// This function directly accesses the S_usb_request instance located
// in the S_usb structure to extract its new address.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -