📄 usbd_udp.c
字号:
}
pEndpoint->state = UDP_ENDPOINT_IDLE;
// Reset Endpoint Fifos
AT91C_BASE_UDP->UDP_RSTEP |= (1 << bEndpoint);
AT91C_BASE_UDP->UDP_RSTEP &= ~(1 << bEndpoint);
// Configure endpoint
SET_CSR(bEndpoint, (unsigned int)AT91C_UDP_EPEDS | (bType << 8) | (bEndpointDir << 10));
if (bType == USBEndpointDescriptor_CONTROL) {
AT91C_BASE_UDP->UDP_IER = (1 << bEndpoint);
}
TRACE_INFO_WP("CfgEpt%d ", bEndpoint);
}
//------------------------------------------------------------------------------
/// Sends data through a USB endpoint. Sets up the transfer descriptor,
/// writes one or two data payloads (depending on the number of FIFO bank
/// for the endpoint) and then starts the actual transfer. The operation is
/// complete when all the data has been sent.
///
/// *If the size of the buffer is greater than the size of the endpoint
/// (or twice the size if the endpoint has two FIFO banks), then the buffer
/// must be kept allocated until the transfer is finished*. This means that
/// it is not possible to declare it on the stack (i.e. as a local variable
/// of a function which returns after starting a transfer).
///
/// \param bEndpoint Endpoint number.
/// \param pData Pointer to a buffer with the data to send.
/// \param dLength Size of the data buffer.
/// \param fCallback Optional callback function to invoke when the transfer is
/// complete.
/// \param pArgument Optional argument to the callback function.
/// \return USBD_STATUS_SUCCESS if the transfer has been started;
/// otherwise, the corresponding error status code.
//------------------------------------------------------------------------------
char USBD_Write( unsigned char bEndpoint,
const void *pData,
unsigned int dLength,
TransferCallback fCallback,
void *pArgument )
{
Endpoint *pEndpoint = &(endpoints[bEndpoint]);
Transfer *pTransfer = &(pEndpoint->transfer);
// Check that the endpoint is 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 the first packet
pEndpoint->state = UDP_ENDPOINT_SENDING;
while((AT91C_BASE_UDP->UDP_CSR[bEndpoint]&AT91C_UDP_TXPKTRDY)==AT91C_UDP_TXPKTRDY);
UDP_WritePayload(bEndpoint);
SET_CSR(bEndpoint, AT91C_UDP_TXPKTRDY);
// If double buffering is enabled and there is data remaining,
// prepare another packet
if ((BOARD_USB_ENDPOINTS_BANKS(bEndpoint) > 1) && (pTransfer->remaining > 0)) {
UDP_WritePayload(bEndpoint);
}
// Enable interrupt on endpoint
AT91C_BASE_UDP->UDP_IER = 1 << bEndpoint;
return USBD_STATUS_SUCCESS;
}
//------------------------------------------------------------------------------
/// 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 size) is received.
///
/// *The buffer must be kept allocated until the transfer is finished*.
/// \param bEndpoint Endpoint number.
/// \param pData Pointer to a data buffer.
/// \param dLength Size of the data buffer in bytes.
/// \param fCallback Optional end-of-transfer callback function.
/// \param pArgument Optional argument to the callback function.
/// \return USBD_STATUS_SUCCESS if the read operation has been started;
/// otherwise, the corresponding error code.
//------------------------------------------------------------------------------
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;
}
// Endpoint enters Receiving state
pEndpoint->state = UDP_ENDPOINT_RECEIVING;
TRACE_DEBUG_WP("Read%d(%d) ", bEndpoint, dLength);
// Set the transfer descriptor
pTransfer->pData = pData;
pTransfer->remaining = dLength;
pTransfer->buffered = 0;
pTransfer->transferred = 0;
pTransfer->fCallback = fCallback;
pTransfer->pArgument = pArgument;
// Enable interrupt on endpoint
AT91C_BASE_UDP->UDP_IER = 1 << bEndpoint;
return USBD_STATUS_SUCCESS;
}
//------------------------------------------------------------------------------
/// Sets the HALT feature on the given endpoint (if not already in this state).
/// \param bEndpoint Endpoint number.
//------------------------------------------------------------------------------
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
UDP_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);
// Put endpoint into Halt state
SET_CSR(bEndpoint, AT91C_UDP_FORCESTALL);
pEndpoint->state = UDP_ENDPOINT_HALTED;
// Enable the endpoint interrupt
AT91C_BASE_UDP->UDP_IER = 1 << bEndpoint;
}
}
//------------------------------------------------------------------------------
/// 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
CLEAR_CSR(bEndpoint, AT91C_UDP_FORCESTALL);
// Reset Endpoint Fifos, beware this is a 2 steps operation
AT91C_BASE_UDP->UDP_RSTEP |= 1 << bEndpoint;
AT91C_BASE_UDP->UDP_RSTEP &= ~(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 );
}
//------------------------------------------------------------------------------
/// Indicates if the device is running in high or full-speed. Always returns 0
/// since UDP does not support high-speed mode.
//------------------------------------------------------------------------------
unsigned char USBD_IsHighSpeed(void)
{
return 0;
}
//------------------------------------------------------------------------------
/// Causes the given endpoint to acknowledge the next packet it receives
/// with a STALL handshake.
/// \param bEndpoint Endpoint number.
/// \return USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED.
//------------------------------------------------------------------------------
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);
SET_CSR(bEndpoint, AT91C_UDP_FORCESTALL);
return USBD_STATUS_SUCCESS;
}
//------------------------------------------------------------------------------
/// Starts a remote wake-up procedure.
//------------------------------------------------------------------------------
void USBD_RemoteWakeUp(void)
{
UDP_EnablePeripheralClock();
UDP_EnableUsbClock();
UDP_EnableTransceiver();
TRACE_INFO_WP("RWUp ");
// Activates a remote wakeup (edge on ESR), then clear ESR
AT91C_BASE_UDP->UDP_GLBSTATE |= AT91C_UDP_ESR;
AT91C_BASE_UDP->UDP_GLBSTATE &= ~AT91C_UDP_ESR;
}
//------------------------------------------------------------------------------
/// Sets the device address to the given value.
/// \param address New device address.
//------------------------------------------------------------------------------
void USBD_SetAddress(unsigned char address)
{
TRACE_INFO_WP("SetAddr(%d) ", address);
// Set address
AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN | address;
// If the address is 0, the device returns to the Default state
if (address == 0) {
AT91C_BASE_UDP->UDP_GLBSTATE = 0;
deviceState = USBD_STATE_DEFAULT;
}
// If the address is non-zero, the device enters the Address state
else {
AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
deviceState = USBD_STATE_ADDRESS;
}
}
//------------------------------------------------------------------------------
/// Sets the current device configuration.
/// \param cfgnum - Configuration number to set.
//------------------------------------------------------------------------------
void USBD_SetConfiguration(unsigned char cfgnum)
{
TRACE_INFO_WP("SetCfg(%d) ", cfgnum);
// If the configuration number if non-zero, the device enters the
// Configured state
if (cfgnum != 0) {
// Enter Configured state
deviceState = USBD_STATE_CONFIGURED;
AT91C_BASE_UDP->UDP_GLBSTATE |= AT91C_UDP_CONFG;
}
// If the configuration number is zero, the device goes back to the Address
// state
else {
deviceState = USBD_STATE_ADDRESS;
AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
// Abort all transfers
UDP_DisableEndpoints();
}
}
//------------------------------------------------------------------------------
/// Connects the pull-up on the D+ line of the USB.
//------------------------------------------------------------------------------
void USBD_Connect(void)
{
TRACE_DEBUG("Conn ");
#if defined(BOARD_USB_PULLUP_EXTERNAL)
const Pin pinPullUp = PIN_USB_PULLUP;
if (pinPullUp.attribute == PIO_OUTPUT_0) {
PIO_Set(&pinPullUp);
}
else {
PIO_Clear(&pinPullUp);
}
#elif defined(BOARD_USB_PULLUP_INTERNAL)
AT91C_BASE_UDP->UDP_TXVC |= AT91C_UDP_PUON;
#elif defined(BOARD_USB_PULLUP_MATRIX)
AT91C_BASE_MATRIX->MATRIX_USBPCR |= AT91C_MATRIX_USBPCR_PUON;
#elif !defined(BOARD_USB_PULLUP_ALWAYSON)
#error Unsupported pull-up type.
#endif
}
//------------------------------------------------------------------------------
/// Disconnects the pull-up from the D+ line of the USB.
//------------------------------------------------------------------------------
void USBD_Disconnect(void)
{
TRACE_DEBUG("Disc ");
#if defined(BOARD_USB_PULLUP_EXTERNAL)
const Pin pinPullUp = PIN_USB_PULLUP;
if (pinPullUp.attribute == PIO_OUTPUT_0) {
PIO_Clear(&pinPullUp);
}
else {
PIO_Set(&pinPullUp);
}
#elif defined(BOARD_USB_PULLUP_INTERNAL)
AT91C_BASE_UDP->UDP_TXVC &= ~AT91C_UDP_PUON;
#elif defined(BOARD_USB_PULLUP_MATRIX)
AT91C_BASE_MATRIX->MATRIX_USBPCR &= ~AT91C_MATRIX_USBPCR_PUON;
#elif !defined(BOARD_USB_PULLUP_ALWAYSON)
#error Unsupported pull-up type.
#endif
// Device returns to the Powered state
if (deviceState > USBD_STATE_POWERED) {
deviceState = USBD_STATE_POWERED;
}
}
//------------------------------------------------------------------------------
/// Initializes the USB driver.
//------------------------------------------------------------------------------
void USBD_Init(void)
{
TRACE_INFO_WP("USBD_Init\n\r");
// Reset endpoint structures
UDP_ResetEndpoints();
// Configure the pull-up on D+ and disconnect it
#if defined(BOARD_USB_PULLUP_EXTERNAL)
const Pin pinPullUp = PIN_USB_PULLUP;
PIO_Configure(&pinPullUp, 1);
#elif defined(BOARD_USB_PULLUP_INTERNAL)
AT91C_BASE_UDP->UDP_TXVC &= ~AT91C_UDP_PUON;
#elif defined(BOARD_USB_PULLUP_MATRIX)
AT91C_BASE_MATRIX->MATRIX_USBPCR &= ~AT91C_MATRIX_USBPCR_PUON;
#elif !defined(BOARD_USB_PULLUP_ALWAYSON)
#error Missing pull-up definition.
#endif
// Device is in the Attached state
deviceState = USBD_STATE_SUSPENDED;
previousDeviceState = USBD_STATE_POWERED;
UDP_EnablePeripheralClock();
UDP_EnableUsbClock();
AT91C_BASE_UDP->UDP_IDR = 0xFE;
AT91C_BASE_UDP->UDP_IER = AT91C_UDP_WAKEUP;
// Configure interrupts
USBDCallbacks_Initialized();
}
//------------------------------------------------------------------------------
/// Returns the current state of the USB device.
/// \return Device current state.
//------------------------------------------------------------------------------
unsigned char USBD_GetState(void)
{
return deviceState;
}
#endif // BOARD_USB_UDP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -