📄 usbd_udp.c
字号:
Parameters:
eptnum - Endpoint number.
data - Pointer to a buffer with the data to send.
size - Size of the data buffer.
callback - Optional callback function to invoke when the transfer is
complete.
argument - Optional argument to the callback function.
Returns:
USBD_STATUS_SUCCESS if the transfer has been started; otherwise, the
corresponding error status code.
*/
char USBD_Write(unsigned char eptnum,
const void *data,
unsigned int size,
TransferCallback callback,
void *argument)
{
Endpoint *endpoint = &(endpoints[eptnum]);
Transfer *transfer = &(endpoint->transfer);
// Check that the endpoint is in Idle state
if (endpoint->state != UDP_ENDPOINT_IDLE) {
return USBD_STATUS_LOCKED;
}
trace_LOG(trace_INFO, "Write%d(%d) ", eptnum, size);
// Setup the transfer descriptor
transfer->data = (void *) data;
transfer->remaining = size;
transfer->buffered = 0;
transfer->transferred = 0;
transfer->callback = callback;
transfer->argument = argument;
// Send the first packet
endpoint->state = UDP_ENDPOINT_SENDING;
UDP_WritePayload(eptnum);
SET_CSR(eptnum, AT91C_UDP_TXPKTRDY);
// If double buffering is enabled and there is data remaining,
// prepare another packet
if ((BOARD_USB_ENDPOINTS_BANKS(eptnum) > 1) && (transfer->remaining > 0)) {
UDP_WritePayload(eptnum);
}
// Enable interrupt on endpoint
AT91C_BASE_UDP->UDP_IER |= 1 << eptnum;
return USBD_STATUS_SUCCESS;
}
/*
Function: USBD_Read
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*.
Parameters:
eptnum - Endpoint number.
data - Pointer to a data buffer.
size - Size of the data buffer in bytes.
callback - Optional end-of-transfer callback function.
argument - Optional argument to the callback function.
Returns:
USBD_STATUS_SUCCESS if the read operation has been started; otherwise,
the corresponding error code.
*/
char USBD_Read(unsigned char eptnum,
void *data,
unsigned int size,
TransferCallback callback,
void *argument)
{
Endpoint *endpoint = &(endpoints[eptnum]);
Transfer *transfer = &(endpoint->transfer);
// Return if the endpoint is not in IDLE state
if (endpoint->state != UDP_ENDPOINT_IDLE) {
return USBD_STATUS_LOCKED;
}
trace_LOG(trace_INFO, "Read%d(%d) ", eptnum, size);
// Endpoint enters Receiving state
endpoint->state = UDP_ENDPOINT_RECEIVING;
// Set the transfer descriptor
transfer->data = data;
transfer->remaining = size;
transfer->buffered = 0;
transfer->transferred = 0;
transfer->callback = callback;
transfer->argument = argument;
// Enable interrupt on endpoint
AT91C_BASE_UDP->UDP_IER |= 1 << eptnum;
return USBD_STATUS_SUCCESS;
}
/*
Function: USBD_Halt
Sets the HALT feature on the given endpoint (if not already in this
state).
Parameters:
eptnum - Endpoint number.
*/
void USBD_Halt(unsigned char eptnum)
{
Endpoint *endpoint = &(endpoints[eptnum]);
// Check that endpoint is enabled and not already in Halt state
if ((endpoint->state != UDP_ENDPOINT_DISABLED)
&& (endpoint->state != UDP_ENDPOINT_HALTED)) {
trace_LOG(trace_INFO, "Halt%d ", eptnum);
// Abort the current transfer if necessary
UDP_EndOfTransfer(eptnum, USBD_STATUS_ABORTED);
// Put endpoint into Halt state
SET_CSR(eptnum, AT91C_UDP_FORCESTALL);
endpoint->state = UDP_ENDPOINT_HALTED;
// Enable the endpoint interrupt
AT91C_BASE_UDP->UDP_IER |= 1 << eptnum;
}
}
/*
Function: USBD_Unhalt
Clears the Halt feature on the given endpoint.
Parameters:
eptnum - Endpoint number.
*/
void USBD_Unhalt(unsigned char eptnum)
{
Endpoint *endpoint = &(endpoints[eptnum]);
// Check if the endpoint is enabled
if (endpoint->state != UDP_ENDPOINT_DISABLED) {
trace_LOG(trace_INFO, "Unhalt%d ", eptnum);
// Return endpoint to Idle state
endpoint->state = UDP_ENDPOINT_IDLE;
// Clear FORCESTALL flag
CLEAR_CSR(eptnum, AT91C_UDP_FORCESTALL);
// Reset Endpoint Fifos, beware this is a 2 steps operation
AT91C_BASE_UDP->UDP_RSTEP |= 1 << eptnum;
AT91C_BASE_UDP->UDP_RSTEP &= ~(1 << eptnum);
}
}
/*
Function: USBD_IsHalted
Returns the current Halt status of an endpoint.
Parameters:
eptnum - Endpoint number.
Returns:
1 if the endpoint is currently halted; otherwise 0.
*/
unsigned char USBD_IsHalted(unsigned char eptnum)
{
Endpoint *endpoint = &(endpoints[eptnum]);
if (endpoint->state == UDP_ENDPOINT_HALTED) {
return 1;
}
else {
return 0;
}
}
/*
Function: USBD_Stall
Causes the given endpoint to acknowledge the next packet it receives
with a STALL handshake.
Parameters:
eptnum - Endpoint number.
Returns:
USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED.
*/
unsigned char USBD_Stall(unsigned char eptnum)
{
Endpoint *endpoint = &(endpoints[eptnum]);
// Check that endpoint is in Idle state
if (endpoint->state != UDP_ENDPOINT_IDLE) {
trace_LOG(trace_WARNING, "USBD_Stall: Endpoint%d locked\n\r", eptnum);
return USBD_STATUS_LOCKED;
}
trace_LOG(trace_INFO, "Stall%d ", eptnum);
SET_CSR(eptnum, AT91C_UDP_FORCESTALL);
return USBD_STATUS_SUCCESS;
}
/*
Function: USBD_RemoteWakeUp
Starts a remote wake-up procedure.
*/
void USBD_RemoteWakeUp()
{
UDP_EnablePeripheralClock();
UDP_EnableUsbClock();
UDP_EnableTransceiver();
trace_LOG(trace_INFO, "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;
}
/*
Function: USBD_SetAddress
Sets the device address to the given value.
Parameters:
address - New device address.
*/
void USBD_SetAddress(unsigned char address)
{
trace_LOG(trace_INFO, "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;
}
}
/*
Function: USBD_SetConfiguration
Sets the current device configuration.
Parameters:
cfgnum - Configuration number to set.
*/
void USBD_SetConfiguration(unsigned char cfgnum)
{
trace_LOG(trace_INFO, "SetCfg(%d) ", cfgnum);
// If the configuration number if non-zero, the device enters the
// Configured state
if (cfgnum != 0) {
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();
}
}
/*
Function: USBD_Connect
Connects the pull-up on the D+ line of the USB.
*/
void USBD_Connect()
{
trace_LOG(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
}
/*
Function: USBD_Disconnect
Disconnects the pull-up from the D+ line of the USB.
*/
void USBD_Disconnect()
{
trace_LOG(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;
}
}
/*
Function: USBD_Init
Initializes the USB driver.
*/
void USBD_Init()
{
trace_LOG(trace_INFO, "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_IER = AT91C_UDP_WAKEUP;
// Configure interrupts
USBDCallbacks_Initialized();
}
/*
Function: USBD_GetState
Returns the current state of the USB device.
Returns:
Device current state.
*/
unsigned char USBD_GetState()
{
return deviceState;
}
//------------------------------------------------------------------------------
/// 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;
}
#endif //#if defined(BOARD_USB_UDP)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -