📄 udp.c
字号:
//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include "common.h"
#include "device.h"
#include "board.h"
//#include "trace.h"
#include "usb.h"
#ifdef UDP
#define UDP_STATE_SHOULD_RECONNECT 0x10000000
#define UDP_EPTYPE_INDEX 8
#define UDP_EPDIR_INDEX 10
#define ISR_MASK 0x00003FFF
//------------------------------------------------------------------------------
// Structures
//------------------------------------------------------------------------------
// \brief Endpoint states
typedef enum {
endpointStateDisabled,
endpointStateIdle,
endpointStateWrite,
endpointStateRead,
endpointStateHalted
} EndpointState_t;
//------------------------------------------------------------------------------
// Macros
//------------------------------------------------------------------------------
// \brief Clear flags in the UDP_CSR register and waits for synchronization
// \param pUsb Pointer to a S_usb instance
// \param bEndpoint Index of endpoint
// \param dFlags Flags to clear
#define UDP_CLEAREPFLAGS(pUsb, bEndpoint, dFlags) { \
while (!ISCLEARED(UDP_GetDriverInterface(pUsb)->UDP_CSR[bEndpoint], dFlags)) \
CLEAR(UDP_GetDriverInterface(pUsb)->UDP_CSR[bEndpoint], dFlags); \
}
// \brief Set flags in the UDP_CSR register and waits for synchronization
// \param pUsb Pointer to a S_usb instance
// \param bEndpoint Index of endpoint
// \param dFlags Flags to clear
#define UDP_SETEPFLAGS(pUsb, bEndpoint, dFlags) { \
while (ISCLEARED(UDP_GetDriverInterface(pUsb)->UDP_CSR[bEndpoint], dFlags)) \
SET(UDP_GetDriverInterface(pUsb)->UDP_CSR[bEndpoint], dFlags); \
}
//------------------------------------------------------------------------------
// Internal Functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// \brief Returns a pointer to the UDP controller interface used by an USB
// driver
//
// The pointer is cast to the correct type (AT91PS_UDP).
// \param pUsb Pointer to a S_usb instance
// \return Pointer to the USB controller interface
// \see S_usb
//------------------------------------------------------------------------------
extern __inline AT91PS_UDP UDP_GetDriverInterface(const S_usb *pUsb)
{
return (AT91PS_UDP) pUsb->pDriver->pInterface;
}
//------------------------------------------------------------------------------
// \brief Enables the peripheral clock of the USB controller associated with
// the specified USB driver
// \param pUsb Pointer to a S_usb instance
// \see S_usb
//------------------------------------------------------------------------------
extern __inline void UDP_EnableMCK(const S_usb *pUsb)
{
AT91C_BASE_PMC->PMC_PCER = 1 << USB_GetDriverID(pUsb);
}
//------------------------------------------------------------------------------
// \brief Disables the peripheral clock of the USB controller associated with
// the specified USB driver
// \param pUsb Pointer to a S_usb instance
// \see S_usb
//------------------------------------------------------------------------------
extern __inline void UDP_DisableMCK(const S_usb *pUsb)
{
AT91C_BASE_PMC->PMC_PCDR = 1 << USB_GetDriverID(pUsb);
}
//------------------------------------------------------------------------------
// \brief Enables the 48MHz clock of the USB controller associated with
// the specified USB driver
// \param pUsb Pointer to a S_usb instance
// \see S_usb
//------------------------------------------------------------------------------
extern __inline void UDP_EnableUDPCK(const S_usb *pUsb)
{
SET(AT91C_BASE_PMC->PMC_SCER, USB_GetDriverPMC(pUsb));
}
//------------------------------------------------------------------------------
// \brief Disables the 48MHz clock of the USB controller associated with
// the specified USB driver
// \param pUsb Pointer to a S_usb instance
// \see S_usb
//------------------------------------------------------------------------------
extern __inline void UDP_DisableUDPCK(const S_usb *pUsb)
{
SET(AT91C_BASE_PMC->PMC_SCDR, USB_GetDriverPMC(pUsb));
}
//------------------------------------------------------------------------------
// \brief Enables the transceiver of the USB controller associated with
// the specified USB driver
// \param pUsb Pointer to a S_usb instance
// \see S_usb
//------------------------------------------------------------------------------
extern __inline void UDP_EnableTransceiver(const S_usb *pUsb)
{
CLEAR(UDP_GetDriverInterface(pUsb)->UDP_TXVC, AT91C_UDP_TXVDIS);
}
//------------------------------------------------------------------------------
// \brief Disables the transceiver of the USB controller associated with
// the specified USB driver
// \param pUsb Pointer to a S_usb instance
// \see S_usb
//------------------------------------------------------------------------------
extern __inline void UDP_DisableTransceiver(const S_usb *pUsb)
{
SET(UDP_GetDriverInterface(pUsb)->UDP_TXVC, AT91C_UDP_TXVDIS);
}
//------------------------------------------------------------------------------
// \brief Invokes the callback associated with a finished transfer on an
// endpoint
// \param pEndpoint Pointer to a S_usb_endpoint instance
// \param bStatus Status code returned by the transfer operation
// \see Status codes
// \see S_usb_endpoint
//------------------------------------------------------------------------------
extern __inline void UDP_EndOfTransfer(S_usb_endpoint *pEndpoint,
char bStatus)
{
if ((pEndpoint->dState == endpointStateWrite)
|| (pEndpoint->dState == endpointStateRead)) {
// Endpoint returns in Idle state
pEndpoint->dState = endpointStateIdle;
// Invoke callback is present
if (pEndpoint->fCallback != 0) {
pEndpoint->fCallback((unsigned int) pEndpoint->pArgument,
(unsigned int) bStatus,
pEndpoint->dBytesTransferred,
pEndpoint->dBytesRemaining
+ pEndpoint->dBytesBuffered);
}
}
}
//------------------------------------------------------------------------------
// \brief Clears the correct RX flag in an endpoint status register
// \param pUsb Pointer to a S_usb instance
// \param bEndpoint Index of endpoint
// \see S_usb_endpoint
// \see S_usb
//------------------------------------------------------------------------------
static void UDP_ClearRXFlag(const S_usb * pUsb,
unsigned char bEndpoint)
{
S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
// Clear flag
UDP_CLEAREPFLAGS(pUsb, bEndpoint, pEndpoint->dFlag);
// Swap banks
if (pEndpoint->dFlag == AT91C_UDP_RX_DATA_BK0) {
if (pEndpoint->dNumFIFO > 1) {
// Swap bank if in dual-fifo mode
pEndpoint->dFlag = AT91C_UDP_RX_DATA_BK1;
}
}
else {
pEndpoint->dFlag = AT91C_UDP_RX_DATA_BK0;
}
}
//------------------------------------------------------------------------------
// \brief Transfers a data payload from the current tranfer buffer to the
// endpoint FIFO.
// \param pUsb Pointer to a S_usb instance
// \param bEndpoint Index of endpoint
// \return Number of bytes transferred
// \see S_usb
//------------------------------------------------------------------------------
static unsigned int UDP_WritePayload(const S_usb * pUsb,
unsigned char bEndpoint)
{
AT91PS_UDP pInterface = UDP_GetDriverInterface(pUsb);
S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
unsigned int dBytes;
unsigned int dCtr;
// Get the number of bytes to send
dBytes = min(pEndpoint->wMaxPacketSize, pEndpoint->dBytesRemaining);
// Transfer one packet in the FIFO buffer
for (dCtr = 0; dCtr < dBytes; dCtr++) {
pInterface->UDP_FDR[bEndpoint] = *(pEndpoint->pData);
pEndpoint->pData++;
}
pEndpoint->dBytesBuffered += dBytes;
pEndpoint->dBytesRemaining -= dBytes;
return dBytes;
}
//------------------------------------------------------------------------------
// \brief Transfers a data payload from an endpoint FIFO to the current
// transfer buffer.
// \param pUsb Pointer to a S_usb instance
// \param bEndpoint Index of endpoint
// \param wPacketSize Size of received data packet
// \return Number of bytes transferred
// \see S_usb
//------------------------------------------------------------------------------
static unsigned int UDP_GetPayload(const S_usb * pUsb,
unsigned char bEndpoint,
unsigned short wPacketSize)
{
AT91PS_UDP pInterface = UDP_GetDriverInterface(pUsb);
S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
unsigned int dBytes;
unsigned int dCtr;
char ch;
// Get number of bytes to retrieve
dBytes = min(pEndpoint->dBytesRemaining, wPacketSize);
// Retrieve packet
for (dCtr = 0; dCtr < dBytes; dCtr++) {
*pEndpoint->pData = (char) pInterface->UDP_FDR[bEndpoint];
pEndpoint->pData++;
}
pEndpoint->dBytesRemaining -= dBytes;
pEndpoint->dBytesTransferred += dBytes;
pEndpoint->dBytesBuffered += wPacketSize - dBytes;
return dBytes;
}
extern unsigned int g_menuzzz;
//------------------------------------------------------------------------------
// \brief Transfers a received SETUP packet from endpoint 0 FIFO to the
// S_usb_request structure of an USB driver
// \param pUsb Pointer to a S_usb instance
// \see S_usb
//------------------------------------------------------------------------------
static void UDP_GetSetup(S_usb const *pUsb)
{
char *pData = (char *) USB_GetSetup(pUsb);
AT91PS_UDP pInterface = UDP_GetDriverInterface(pUsb);
unsigned int dCtr;
// Copy packet
for (dCtr = 0; dCtr < 8; dCtr++) {
*pData = (char) pInterface->UDP_FDR[0];
//buff[dCtr] = *pData;
pData++;
}
//if(g_menuzzz)
// memcpy(pData,bufOK,8);
}
//------------------------------------------------------------------------------
// \brief This function reset all endpoint transfer descriptors
// \param pUsb Pointer to a S_usb instance
// \see S_usb
//------------------------------------------------------------------------------
static void UDP_ResetEndpoints(const S_usb *pUsb)
{
S_usb_endpoint *pEndpoint;
unsigned char bEndpoint;
// Reset the transfer descriptor of every endpoint
for (bEndpoint = 0; bEndpoint < pUsb->dNumEndpoints; bEndpoint++) {
pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
// Reset endpoint transfer descriptor
pEndpoint->pData = 0;
pEndpoint->dBytesRemaining = 0;
pEndpoint->dBytesTransferred = 0;
pEndpoint->dBytesBuffered = 0;
pEndpoint->fCallback = 0;
pEndpoint->pArgument = 0;
// Configure endpoint characteristics
pEndpoint->dFlag = AT91C_UDP_RX_DATA_BK0;
pEndpoint->dState = endpointStateDisabled;
}
}
//------------------------------------------------------------------------------
// \brief Disable all endpoints (except control endpoint 0), aborting current
// transfers if necessary.
// \param pUsb Pointer to a S_usb instance
//------------------------------------------------------------------------------
static void UDP_DisableEndpoints(const S_usb *pUsb)
{
S_usb_endpoint *pEndpoint;
unsigned char bEndpoint;
// For each endpoint, if it is enabled, disable it and invoke the callback
// Control endpoint 0 is not disabled
for (bEndpoint = 1; bEndpoint < pUsb->dNumEndpoints; bEndpoint++) {
pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
UDP_EndOfTransfer(pEndpoint, USB_STATUS_RESET);
pEndpoint->dState = endpointStateDisabled;
}
}
//------------------------------------------------------------------------------
// \brief Endpoint interrupt handler.
//
// Handle IN/OUT transfers, received SETUP packets and STALLing
// \param pUsb Pointer to a S_usb instance
// \param bEndpoint Index of endpoint
// \see S_usb
//------------------------------------------------------------------------------
static void UDP_EndpointHandler(const S_usb *pUsb, unsigned char bEndpoint)
{
S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
AT91PS_UDP pInterface = UDP_GetDriverInterface(pUsb);
unsigned int dStatus = pInterface->UDP_CSR[bEndpoint];
// Handle interrupts
// IN packet sent
if (ISSET(dStatus, AT91C_UDP_TXCOMP)) {
// Check that endpoint was in Write state
if (pEndpoint->dState == endpointStateWrite) {
// End of transfer ?
if ((pEndpoint->dBytesBuffered < pEndpoint->wMaxPacketSize)
||
(!ISCLEARED(dStatus, AT91C_UDP_EPTYPE)
&& (pEndpoint->dBytesRemaining == 0)
&& (pEndpoint->dBytesBuffered == pEndpoint->wMaxPacketSize))) {
pEndpoint->dBytesTransferred += pEndpoint->dBytesBuffered;
pEndpoint->dBytesBuffered = 0;
// Disable interrupt if this is not a control endpoint
if (!ISCLEARED(dStatus, AT91C_UDP_EPTYPE)) {
SET(pInterface->UDP_IDR, 1 << bEndpoint);
}
UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
}
else {
// Transfer remaining data
pEndpoint->dBytesTransferred += pEndpoint->wMaxPacketSize;
pEndpoint->dBytesBuffered -= pEndpoint->wMaxPacketSize;
// Send next packet
if (pEndpoint->dNumFIFO == 1) {
// No double buffering
UDP_WritePayload(pUsb, bEndpoint);
UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXPKTRDY);
}
else {
// Double buffering
UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXPKTRDY);
UDP_WritePayload(pUsb, bEndpoint);
}
}
}
// Acknowledge interrupt
UDP_CLEAREPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXCOMP);
}
// OUT packet received
if (ISSET(dStatus, AT91C_UDP_RX_DATA_BK0)
|| ISSET(dStatus, AT91C_UDP_RX_DATA_BK1)) {
// Check that the endpoint is in Read state
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -