📄 usbd_udphs.c
字号:
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2007, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the disclaimer below in the documentation and/or
* other materials provided with the distribution.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "USBD.h"
#include "USBDCallbacks.h"
#include "USBDDriver.h"
#include <board.h>
#include <pio/pio.h>
#include <utility/trace.h>
#include <utility/led.h>
#include <usb/common/core/USBEndpointDescriptor.h>
#include <usb/common/core/USBGenericRequest.h>
#include <usb/common/core/USBFeatureRequest.h>
#include <stdio.h>
#ifdef BOARD_USB_UDPHS
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
#define NUM_IT_MAX (AT91C_BASE_UDPHS->UDPHS_IPFEATURES & AT91C_UDPHS_EPT_NBR_MAX)
#define NUM_IT_MAX_DMA ((AT91C_BASE_UDPHS->UDPHS_IPFEATURES & AT91C_UDPHS_DMA_CHANNEL_NBR)>>4)
#define SHIFT_DMA 24
#define SHIFT_INTERUPT 8
#define DMA
/// Max size of the FMA FIFO
#define DMA_MAX_FIFO_SIZE 65536
// Constants: Endpoint states
// UDP_ENDPOINT_DISABLED - Endpoint is disabled.
// UDP_ENDPOINT_HALTED - Endpoint is halted (i.e. STALLs every request).
// UDP_ENDPOINT_IDLE - Endpoint is idle (i.e. ready for transmission).
// UDP_ENDPOINT_SENDING - Endpoint is sending data.
// UDP_ENDPOINT_RECEIVING - Endpoint is receiving data.
#define UDP_ENDPOINT_DISABLED 0
#define UDP_ENDPOINT_HALTED 1
#define UDP_ENDPOINT_IDLE 2
#define UDP_ENDPOINT_SENDING 3
#define UDP_ENDPOINT_RECEIVING 4
//------------------------------------------------------------------------------
// Structures
//------------------------------------------------------------------------------
// Type: UDP transfer
// Describes an ongoing transfer on a UDP endpoint.
//
// Variables:
// data - Pointer to a data buffer used for emission/reception.
// buffered - Number of bytes which have been written into the UDP internal
// FIFO buffers.
// transferred - Number of bytes which have been sent/received.
// remaining - Number of bytes which have not been buffered/transferred yet.
// callback - Optional callback to invoke when the transfer completes.
// argument - Optional argument to the callback function.
typedef struct
{
char *pData;
volatile int buffered;
volatile int transferred;
volatile int remaining;
TransferCallback fCallback;
void *pArgument;
} Transfer;
// Type: UDP endpoint
// Describes the state of an endpoint of the UDP controller.
//
// Variables:
// state - Current endpoint state.
// bank - Current reception bank (0 or 1).
// size - Maximum packet size for the endpoint.
// transfer - Describes an ongoing transfer (if current state is either
// <UDP_ENDPOINT_SENDING> or <UDP_ENDPOINT_RECEIVING>).
typedef struct
{
unsigned char state;
unsigned char bank;
unsigned short size;
Transfer transfer;
} Endpoint;
//------------------------------------------------------------------------------
// Internal variables
//------------------------------------------------------------------------------
// Variables:
// endpoints - Holds the internal state for each endpoint of the UDP.
// deviceState - Device current state.
// suspended - Indicates if device is currently suspended.
static Endpoint endpoints[BOARD_USB_NUMENDPOINTS];
static unsigned char deviceState;
static unsigned char previousDeviceState;
// 7.1.20 Test Mode Support
static const char test_packet_buffer[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // JKJKJKJK * 9
0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA, // JJKKJJKK * 8
0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE, // JJJJKKKK * 8
0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // JJJJJJJKKKKKKK * 8
0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD, // JJJJJJJK * 8
0xFC,0x7E,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0x7E // {JKKKKKKK * 10}, JK
};
//------------------------------------------------------------------------------
// Internal Functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Disables the BIAS of the USB controller
//------------------------------------------------------------------------------
static inline void UDPHS_DisableBIAS( void )
{
// For CAP9, SAM9RL, HS
#if !defined (BOARD_USB_NO_BIAS_COMMAND)
AT91C_BASE_PMC->PMC_UCKR &= ~AT91C_CKGR_BIASEN_ENABLED;
#endif
}
//------------------------------------------------------------------------------
// Enables the BIAS of the USB controller
//------------------------------------------------------------------------------
static inline void UDPHS_EnableBIAS( void )
{
// For CAP9, SAM9RL, HS
#if !defined (BOARD_USB_NO_BIAS_COMMAND)
UDPHS_DisableBIAS();
AT91C_BASE_PMC->PMC_UCKR |= AT91C_CKGR_BIASEN_ENABLED;
#endif
}
//------------------------------------------------------------------------------
// Enable UDPHS clock
// pUsb Pointer to a S_usb instance
//------------------------------------------------------------------------------
static inline void UDPHS_EnableUsbClock( void )
{
#if !defined (PMC_BY_HARD)
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDPHS);
// Enable 480MHZ
AT91C_BASE_CKGR->CKGR_UCKR |= (AT91C_CKGR_PLLCOUNT & (3 << 20)) | AT91C_CKGR_UPLLEN;
// Wait until UTMI PLL is locked
while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKU) == 0);
#endif
}
//------------------------------------------------------------------------------
// Disable UDPHS clock
// pUsb Pointer to a S_usb instance
//------------------------------------------------------------------------------
static inline void UDPHS_DisableUsbClock( void )
{
#if !defined (PMC_BY_HARD)
AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_UDPHS);
// 480MHZ
AT91C_BASE_CKGR->CKGR_UCKR &= ~AT91C_CKGR_UPLLEN;
#endif
}
//------------------------------------------------------------------------------
// Invokes the callback associated with a finished transfer on an
// endpoint
// pEndpoint Pointer to a S_usb_endpoint instance
// bStatus Status code returned by the transfer operation
//------------------------------------------------------------------------------
static void UDPHS_EndOfTransfer( unsigned char bEndpoint, char bStatus )
{
Endpoint *pEndpoint = &(endpoints[bEndpoint]);
Transfer *pTransfer = &(pEndpoint->transfer);
// Check that endpoint was sending or receiving data
if( (pEndpoint->state == UDP_ENDPOINT_RECEIVING)
|| (pEndpoint->state == UDP_ENDPOINT_SENDING) ) {
trace_LOG(trace_DEBUG, "Eo");
// Endpoint returns in Idle state
pEndpoint->state = UDP_ENDPOINT_IDLE;
// Invoke callback is present
if (pTransfer->fCallback != 0) {
((TransferCallback) pTransfer->fCallback)
(pTransfer->pArgument,
bStatus,
pTransfer->transferred,
pTransfer->remaining + pTransfer->buffered);
}
}
}
//------------------------------------------------------------------------------
// Clears the correct RX flag in an endpoint status register
// bEndpoint Index of endpoint
//------------------------------------------------------------------------------
static void UDPHS_ClearRxFlag( unsigned char bEndpoint )
{
AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_RX_BK_RDY;
}
//------------------------------------------------------------------------------
// Transfers a data payload from the current tranfer buffer to the endpoint FIFO
// bEndpoint Index of endpoint
//------------------------------------------------------------------------------
static void UDPHS_WritePayload( unsigned char bEndpoint )
{
Endpoint *pEndpoint = &(endpoints[bEndpoint]);
Transfer *pTransfer = &(pEndpoint->transfer);
char *pFifo;
signed int size;
unsigned int dCtr;
pFifo = (char*)&(AT91C_BASE_UDPHS_EPTFIFO->UDPHS_READEPT0[bEndpoint*16384]);
// Get the number of bytes to send
size = pEndpoint->size;
if (size > pTransfer->remaining) {
size = pTransfer->remaining;
}
// Update transfer descriptor information
pTransfer->buffered += size;
pTransfer->remaining -= size;
// Write packet in the FIFO buffer
dCtr = 0;
while (size > 0) {
pFifo[dCtr] = *(pTransfer->pData);
pTransfer->pData++;
size--;
dCtr++;
}
}
//------------------------------------------------------------------------------
// Transfers a data payload from an endpoint FIFO to the current transfer buffer
// bEndpoint Index of endpoint
// wPacketSize Size of received data packet
//------------------------------------------------------------------------------
static void UDPHS_ReadPayload( unsigned char bEndpoint, int wPacketSize )
{
Endpoint *pEndpoint = &(endpoints[bEndpoint]);
Transfer *pTransfer = &(pEndpoint->transfer);
char *pFifo;
unsigned char dBytes=0;
pFifo = (char*)&(AT91C_BASE_UDPHS_EPTFIFO->UDPHS_READEPT0[bEndpoint*16384]);
// Check that the requested size is not bigger than the remaining transfer
if (wPacketSize > pTransfer->remaining) {
pTransfer->buffered += wPacketSize - pTransfer->remaining;
wPacketSize = pTransfer->remaining;
}
// Update transfer descriptor information
pTransfer->remaining -= wPacketSize;
pTransfer->transferred += wPacketSize;
// Retrieve packet
while (wPacketSize > 0) {
*(pTransfer->pData) = pFifo[dBytes];
pTransfer->pData++;
wPacketSize--;
dBytes++;
}
}
//------------------------------------------------------------------------------
// Transfers a received SETUP packet from endpoint 0 FIFO to the S_usb_request
// structure of an USB driver
//------------------------------------------------------------------------------
static void UDPHS_ReadRequest( USBGenericRequest *pRequest )
{
unsigned int *pData = (unsigned int *)pRequest;
unsigned int fifo;
fifo = (AT91C_BASE_UDPHS_EPTFIFO->UDPHS_READEPT0[0]);
*pData = fifo;
fifo = (AT91C_BASE_UDPHS_EPTFIFO->UDPHS_READEPT0[0]);
pData++;
*pData = fifo;
//trace_LOG(trace_ERROR, "SETUP: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n\r", pData[0],pData[1],pData[2],pData[3],pData[4],pData[5],pData[6],pData[7]);
}
//------------------------------------------------------------------------------
// This function reset all endpoint transfer descriptors
//------------------------------------------------------------------------------
static void UDPHS_ResetEndpoints( void )
{
Endpoint *pEndpoint;
Transfer *pTransfer;
unsigned char bEndpoint;
// Reset the transfer descriptor of every endpoint
for( bEndpoint = 0; bEndpoint < BOARD_USB_NUMENDPOINTS; bEndpoint++ ) {
pEndpoint = &(endpoints[bEndpoint]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -