📄 usbd_udphs.c
字号:
//------------------------------------------------------------------------------
/// Sends data through an USB endpoint (IN)
/// 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.
/// \param bEndpoint Index of endpoint
/// \param *pData Data to be written
/// \param dLength Data length to be send
/// \param fCallback Callback to be call after the success command
/// \param *pArgument Callback argument
/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
//------------------------------------------------------------------------------
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_DEBUG_WP("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
// 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 {
if( pTransfer->remaining == 0 ) {
// DMA not handle ZLP
AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSETSTA = AT91C_UDPHS_TX_PK_RDY;
// 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;
}
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_DEBUG_WP("\n\r_WR:%d ", pTransfer->remaining );
TRACE_DEBUG_WP("B:%d ", pTransfer->buffered );
TRACE_DEBUG_WP("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)
/// \param bEndpoint Index of endpoint
/// \param *pData Data to be readen
/// \param dLength Data length to be receive
/// \param fCallback Callback to be call after the success command
/// \param *pArgument Callback argument
/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
//------------------------------------------------------------------------------
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_DEBUG_WP("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_DEBUG_WP("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_DEBUG_WP("\n\r_RR:%d ", pTransfer->remaining );
TRACE_DEBUG_WP("B:%d ", pTransfer->buffered );
TRACE_DEBUG_WP("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;
}
//------------------------------------------------------------------------------
/// Put endpoint into Halt state
/// \param bEndpoint Index of endpoint
//------------------------------------------------------------------------------
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_DEBUG_WP("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
}
}
//------------------------------------------------------------------------------
/// Clears the Halt feature on the given endpoint.
/// \param bEndpoint Index of endpoint
//------------------------------------------------------------------------------
void USBD_Unhalt( unsigned char bEndpoint )
{
Endpoint *pEndpoint = &(endpoints[bEndpoint]);
// Check if the endpoint is enabled
if (pEndpoint->state != UDP_ENDPOINT_DISABLED) {
TRACE_DEBUG_WP("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);
}
}
//------------------------------------------------------------------------------
/// Returns the current Halt status of an endpoint.
/// \param bEndpoint Index of endpoint
/// \return 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 ?
/// \return 1 if the device is in High Speed; otherwise 0 (Full 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_DEBUG_WP("High Speed\n\r");
status = 1;
}
else {
TRACE_DEBUG_WP("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.
/// \param bEndpoint Index of endpoint
/// \return Operation result code: USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
//------------------------------------------------------------------------------
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_WARNING("UDP_Stall: Endpoint%d locked\n\r", bEndpoint);
return USBD_STATUS_LOCKED;
}
TRACE_DEBUG_WP("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_DEBUG_WP("Remote WakeUp\n\r");
// Device is currently suspended
if (deviceState == USBD_STATE_SUSPENDED) {
TRACE_DEBUG_WP("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_DEBUG_WP("W");
}
UDPHS_EnableBIAS();
}
// Device is NOT suspended
else {
TRACE_WARNING("USBD_RemoteWakeUp: Device is not suspended\n\r");
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -