📄 udp.c
字号:
// Handle all UDP interrupts
while (dStatus != 0) {
// Start Of Frame (SOF)
if (ISSET(dStatus, AT91C_UDP_SOFINT)) {
TRACE_DEBUG_L("SOF ");
// Invoke the SOF callback
USB_StartOfFrameCallback(pUsb);
// Acknowledge interrupt
SET(pInterface->UDP_ICR, AT91C_UDP_SOFINT);
CLEAR(dStatus, AT91C_UDP_SOFINT);
}
// Suspend
if (dStatus == AT91C_UDP_RXSUSP) {
TRACE_DEBUG_L("Susp ");
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
// Enable wakeup
SET(pInterface->UDP_IER, AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM);
// Acknowledge interrupt
SET(pInterface->UDP_ICR, AT91C_UDP_RXSUSP);
SET(*(pUsb->pState), USB_STATE_SUSPENDED);
UDP_DisableTransceiver(pUsb);
UDP_DisableMCK(pUsb);
UDP_DisableUDPCK(pUsb);
// Invoke the Suspend callback
USB_SuspendCallback(pUsb);
}
}
// Resume
else if (ISSET(dStatus, AT91C_UDP_WAKEUP)
|| ISSET(dStatus, AT91C_UDP_RXRSM)) {
// Invoke the Resume callback
USB_ResumeCallback(pUsb);
TRACE_DEBUG_L("Res ");
// The device enters Configured state
// MCK + UDPCK must be on
// Pull-Up must be connected
// Transceiver must be enabled
if (ISSET(USB_GetState(pUsb), USB_STATE_SUSPENDED)) {
// Powered state
UDP_EnableMCK(pUsb);
UDP_EnableUDPCK(pUsb);
// Default state
if (ISSET(USB_GetState(pUsb), USB_STATE_DEFAULT)) {
UDP_EnableTransceiver(pUsb);
}
CLEAR(*(pUsb->pState), USB_STATE_SUSPENDED);
}
SET(pInterface->UDP_ICR,
AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM | AT91C_UDP_RXSUSP);
SET(pInterface->UDP_IDR, AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM);
}
// End of bus reset
else if (ISSET(dStatus, AT91C_UDP_ENDBUSRES)) {
TRACE_DEBUG_L("EoBRes ");
// The device enters the Default state
// MCK + UDPCK are already enabled
// Pull-Up is already connected
// Transceiver must be enabled
// Endpoint 0 must be enabled
SET(*(pUsb->pState), USB_STATE_DEFAULT);
UDP_EnableTransceiver(pUsb);
// The device leaves the Address & Configured states
CLEAR(*(pUsb->pState), USB_STATE_ADDRESS | USB_STATE_CONFIGURED);
UDP_ResetEndpoints(pUsb);
UDP_DisableEndpoints(pUsb);
UDP_ConfigureEndpoint(pUsb, 0);
// Flush and enable the Suspend interrupt
SET(pInterface->UDP_ICR,
AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM | AT91C_UDP_RXSUSP);
// Enable the Start Of Frame (SOF) interrupt if needed
if (pUsb->pCallbacks->startOfFrame != 0) {
SET(pInterface->UDP_IER, AT91C_UDP_SOFINT);
}
// Invoke the Reset callback
USB_ResetCallback(pUsb);
// Acknowledge end of bus reset interrupt
SET(pInterface->UDP_ICR, AT91C_UDP_ENDBUSRES);
}
// Endpoint interrupts
else {
while (dStatus != 0) {
// Get endpoint index
bEndpoint = lastSetBit(dStatus);
UDP_EndpointHandler(pUsb, bEndpoint);
/*CLEAR(pInterface->UDP_CSR[bEndpoint],
AT91C_UDP_TXCOMP | AT91C_UDP_RX_DATA_BK0
| AT91C_UDP_RX_DATA_BK1 | AT91C_UDP_RXSETUP
| AT91C_UDP_STALLSENT);*/
CLEAR(dStatus, 1 << bEndpoint);
if (dStatus != 0) {
TRACE_DEBUG_L("\n\r - ");
}
}
}
// Retrieve new interrupt status
dStatus = pInterface->UDP_ISR & pInterface->UDP_IMR & ISR_MASK;
// Mask unneeded interrupts
if (!ISSET(USB_GetState(pUsb), USB_STATE_DEFAULT)) {
dStatus &= AT91C_UDP_ENDBUSRES | AT91C_UDP_SOFINT;
}
TRACE_DEBUG_L("\n\r");
if (dStatus != 0) {
TRACE_DEBUG_L(" - ");
}
}
if ( (!ISSET(USB_GetState(pUsb), USB_STATE_SUSPENDED))
&& (ISSET(USB_GetState(pUsb), USB_STATE_POWERED))){
LED_TOGGLE(LED_USB);
}
}
//------------------------------------------------------------------------------
// \brief Sends data through an USB endpoint
//
// 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 pUsb Pointer to a S_usb instance
// \param bEndpoint Index of endpoint
// \param pData Pointer to a buffer containing the data to send
// \param dLength Length of the data buffer
// \param fCallback Optional function to invoke when the transfer finishes
// \param pArgument Optional argument for the callback function
// \return Operation result code
// \see Operation result codes
// \see Callback_f
// \see S_usb
//------------------------------------------------------------------------------
char UDP_Write(const S_usb *pUsb,
unsigned char bEndpoint,
const void *pData,
unsigned int dLength,
Callback_f fCallback,
void *pArgument)
{
S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
AT91PS_UDP pInterface = UDP_GetDriverInterface(pUsb);
// Check that the endpoint is in Idle state
if (pEndpoint->dState != endpointStateIdle) {
return USB_STATUS_LOCKED;
}
TRACE_DEBUG_L("Write%d(%d) ", bEndpoint, dLength);
// Setup the transfer descriptor
pEndpoint->pData = (char *) pData;
pEndpoint->dBytesRemaining = dLength;
pEndpoint->dBytesBuffered = 0;
pEndpoint->dBytesTransferred = 0;
pEndpoint->fCallback = fCallback;
pEndpoint->pArgument = pArgument;
// Send one packet
pEndpoint->dState = endpointStateWrite;
UDP_WritePayload(pUsb, bEndpoint);
UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXPKTRDY);
// If double buffering is enabled and there is data remaining,
// prepare another packet
if ((pEndpoint->dNumFIFO > 1) && (pEndpoint->dBytesRemaining > 0)) {
UDP_WritePayload(pUsb, bEndpoint);
}
// Enable interrupt on endpoint
SET(pInterface->UDP_IER, 1 << bEndpoint);
return USB_STATUS_SUCCESS;
}
//------------------------------------------------------------------------------
// \brief Reads incoming data on an USB endpoint
//
// This methods sets the transfer descriptor and activate the endpoint
// interrupt. The actual transfer is then carried out by the endpoint
// interrupt handler. The Read operation finishes either when the
// buffer is full, or a short packet (inferior to endpoint maximum
// packet size) is received.
// \param pUsb Pointer to a S_usb instance
// \param bEndpoint Index of endpoint
// \param pData Pointer to a buffer to store the received data
// \param dLength Length of the receive buffer
// \param fCallback Optional callback function
// \param pArgument Optional callback argument
// \return Operation result code
// \see Callback_f
// \see S_usb
//------------------------------------------------------------------------------
char UDP_Read(const S_usb *pUsb,
unsigned char bEndpoint,
void *pData,
unsigned int dLength,
Callback_f fCallback,
void *pArgument)
{
AT91PS_UDP pInterface = UDP_GetDriverInterface(pUsb);
S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
//! Return if the endpoint is not in IDLE state
if (pEndpoint->dState != endpointStateIdle) {
return USB_STATUS_LOCKED;
}
TRACE_DEBUG_L("Read%d(%d) ", bEndpoint, dLength);
// Endpoint enters Read state
pEndpoint->dState = endpointStateRead;
// Set the transfer descriptor
pEndpoint->pData = (char *) pData;
pEndpoint->dBytesRemaining = dLength;
pEndpoint->dBytesBuffered = 0;
pEndpoint->dBytesTransferred = 0;
pEndpoint->fCallback = fCallback;
pEndpoint->pArgument = pArgument;
// Enable interrupt on endpoint
SET(pInterface->UDP_IER, 1 << bEndpoint);
return USB_STATUS_SUCCESS;
}
//------------------------------------------------------------------------------
// \brief 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.
// \param pUsb Pointer to a S_usb instance
// \param bEndpoint Index of endpoint
// \param bRequest Request to perform
// -> USB_SET_FEATURE, USB_CLEAR_FEATURE, USB_GET_STATUS
// \return true if the endpoint is currently Halted, false otherwise
// \see S_usb
//------------------------------------------------------------------------------
bool UDP_Halt(const S_usb *pUsb,
unsigned char bEndpoint,
unsigned char bRequest)
{
AT91PS_UDP pInterface = UDP_GetDriverInterface(pUsb);
S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
// Clear the Halt feature of the endpoint if it is enabled
if (bRequest == USB_CLEAR_FEATURE) {
TRACE_DEBUG_L("Unhalt%d ", bEndpoint);
// Return endpoint to Idle state
pEndpoint->dState = endpointStateIdle;
// Clear FORCESTALL flag
UDP_CLEAREPFLAGS(pUsb, bEndpoint, AT91C_UDP_FORCESTALL);
// Reset Endpoint Fifos, beware this is a 2 steps operation
SET(pInterface->UDP_RSTEP, 1 << bEndpoint);
CLEAR(pInterface->UDP_RSTEP, 1 << bEndpoint);
}
// Set the Halt feature on the endpoint if it is not already enabled
// and the endpoint is not disabled
else if ((bRequest == USB_SET_FEATURE)
&& (pEndpoint->dState != endpointStateHalted)
&& (pEndpoint->dState != endpointStateDisabled)) {
TRACE_DEBUG_L("Halt%d ", bEndpoint);
// Abort the current transfer if necessary
UDP_EndOfTransfer(pEndpoint, USB_STATUS_ABORTED);
// Put endpoint into Halt state
UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_FORCESTALL);
pEndpoint->dState = endpointStateHalted;
// Enable the endpoint interrupt
SET(pInterface->UDP_IER, 1 << bEndpoint);
}
// Return the endpoint halt status
if (pEndpoint->dState == endpointStateHalted) {
return true;
}
else {
return false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -