📄 usbdrv.c
字号:
CLEAR_STALL_EP0;
request_length = min(fifo_sizes[ep_num], RX_EP_COUNTER(ep_num));
/*-------------------------
* Receive request from hub
*-------------------------*/
for(i=0; i<request_length; i++)
request_buffer[i] = EP_FIFO_READ(ENDPOINT_0);
control_receive_buffer.data = (byte *)request_buffer;
control_receive_buffer.bytes_counter = request_length;
FLUSH_TXEP(ENDPOINT_0);
FLUSH_RXEP(ENDPOINT_0);
USB_device_req_handler();
}
/*------------------------------------------------------------
* OUT packet of Status stage in control read/write sequence
*----------------------------------------------------------*/
else
{
/*--------------------
* Re-enable receiving
*-------------------*/
FLUSHTX0;
FLUSHRX0;
ENABLE_RX(ENDPOINT_0);
clear_control_buffer(&control_send_buffer);
}
break;
case RX_FIFO1:
/*-------------------
* endpoint 2 bulk OUT
*-------------------*/
ep_num = ENDPOINT_2;
rxstat = EP_RXSTATUS(ep_num);
if (rxstat & RX_ERR)
{
/*-------------------
* receive media error
*--------------------*/
FLUSH_RXEP(ep_num);
ENABLE_RX(ep_num);
break;
}
Toggle = endpoint_stat[ep_num]->toggle_bit;
Toggle <<= 5;
if ((rxstat & RX_LAST) && ((rxstat & RX_TOGL) == Toggle ))
{
/*-------------------------
* received data is correct
*-------------------------*/
endpoint_stat[ep_num]->toggle_bit = endpoint_stat[ep_num]->toggle_bit ? 0 : 1;
send_event(EVT_USB_BULK_RX);
}
else
{
/*--------------------------------
* response to the toggle bit error
* response to the receive error
*--------------------------------*/
FLUSH_RXEP(ep_num);
ENABLE_RX(ep_num);
}
break;
case RX_FIFO2:
/*----------------
* endpoint 4
* isochronous OUT
*----------------*/
rxstat = EP_RXSTATUS(ENDPOINT_4);
if ((rxstat & RX_ERR) &&!(rxstat & RX_LAST))
{
/*-------------------
* receive media error
*--------------------*/
FLUSH_RXEP(ENDPOINT_4);
ENABLE_RX(ENDPOINT_4);
break;
}
/*-------------------------
* received data is correct
*-------------------------*/
send_event(EVT_USB_ISO_RX);
break;
case RX_FIFO3:
break;
case RX_OVRN0:
break;
case RX_OVRN1:
break;
case RX_OVRN2:
break;
case RX_OVRN3:
break;
default:
/*------------------------------
* No event with this event mask
*------------------------------*/
break;
}
rx_event &= ~evnt_mask;
evnt_mask = evnt_mask << 1;
}
}
/*=====================================================================
* Usb module external interface implementations
*=====================================================================*/
/*----------------------------------------------------------------------------------------------
* Prototype
* void USB_Transmit_Data (int data_size, BYTE* data_ptr, endpoint_t ep_num)
*
* Parameters
* data_size - size of data (in bytes) to be sent
* data_ptr - pointer to data to be sent
* ep_num - number of transmit endpoint
*
* Returns
* Number of byes that was write to the fifo
*
* Description
* Fill corresponding endpoint with the new data. The data size to be written to the FIFO
* is the minimum between requested size and FIFO size.
-------------------------------------------------------------------------------------------------*/
byte USB_Transmit_Data (int data_size, BYTE* data_ptr, endpoint_t ep_num)
{
byte i;
byte size;
_disable_();
FLUSH_TXEP(ep_num);
/*-------------------------------------------------
* assure that data size is no more then fifo length
*--------------------------------------------------*/
size = min(data_size, fifo_sizes[ep_num]);
/*-------------------------------------------
* Now data size is no more than the fifo length,
* transfer the data directly to the fifo
*--------------------------------------------*/
USBADDR = usbn9604_tx_endpoint_addr[ep_num];
for (i=0;i<size;i++)
/*-----------------------------------
* transfer data directly to the fifo
* address updating is not needed
*-----------------------------------*/
USBDATA = data_ptr[i];
/*---------------------------
* enable data transmittion
*---------------------------*/
usbn9604_tx_enable(ep_num);
_enable_();
return size;
}
/*----------------------------------------------------------------------------------------------
* Prototype
* void USB_Receive_Data (BYTE* data_ptr, endpoint_t ep_num)
*
* Parameters
* data_ptr - pointer to the local buffer
* ep_num - number of receive endpoint
*
* Returns
* Number of byes that was read from the FIFO.
*
* Description
* Read whole corresponding endpoint to the local buffer.
-------------------------------------------------------------------------------------------------*/
byte USB_Receive_Data (byte* data_ptr,endpoint_t ep_num)
{
byte bytes_count;
byte bytes_sum = 0;
int i;
_disable_();
/*-------------------------------------------
* Read data from the fifo until it's empty
*-------------------------------------------*/
do
{
/*-----------------------------------------
* Read count of bytes presently in the FIFO
*-----------------------------------------*/
bytes_count = RX_EP_COUNTER(ep_num);
/*---------------------------------------
* update address register in the Voyager
* with address of Receive Data register
*---------------------------------------*/
USBADDR = usbn9604_rx_endpoint_addr[ep_num];
for(i=0;i<bytes_count;i++)
{
/*-----------------------------------
* read data directly from the fifo
* address updating is not needed
*-----------------------------------*/
*(data_ptr ++) = USBDATA;
}
bytes_sum += bytes_count;
}
/*-----------------------------------------------------
* If the FIFO containes more than 15 bytes, a value 15 is
* reported in the counter. Therefore continue reading from the
* fifo until the counter is less then 15.
*------------------------------------------------------*/
while (bytes_count == 0xf);
/*----------------------------------------------
* Flush the fifo and re-enable receive operation
*-----------------------------------------------*/
FLUSH_RXEP(ep_num);
ENABLE_RX(ep_num);
_enable_();
return bytes_sum;
}
/*=====================================================================
* Usb module services implementations
*=====================================================================*/
/*----------------------------------------------------------------------------------------------
* Prototype
* void send_control_data(byte *data_ptr, int data_size)
*
* Parameters
* data_ptr - pointer to the data buffer to be send
* data_size - data buffer size
*
* Returns
* None
*
* Description
* Sends data through the control pipe
-------------------------------------------------------------------------------------------------*/
void send_control_data(byte *data_ptr, int data_size)
{
FLUSHTX0;
control_send_buffer.data = data_ptr;
control_send_buffer.bytes_counter = data_size;
fill_control_fifo();
usbn9604_tx_enable(ENDPOINT_0);
}
/*-------------------------------------------------------------
* Prototype
* void zero_length_data_response(endpoint_t ep_num)
*
* Parameters
* ep_num - endpoint number
*
* Returns
* None
*
* Description
* Generates zero length data packet
----------------------------------------------------------------*/
void zero_length_data_response(endpoint_t ep_num)
{
FLUSH_TXEP(ep_num);
// FLUSH_RXEP(ep_num);
usbn9604_tx_enable(ep_num);
}
/*------------------------------------------------------------------------------
* Prototype
* void fill_control_fifo()
*
* Parameters
* None
*
* Returns
* None
*
* Description
* Transfers data from the control buffer to zero endpoint control fifo.
----------------------------------------------------------------------------*/
void fill_control_fifo()
{
byte *data_ptr = control_send_buffer.data;
/*-----------------------------------
* number of bytes actually to be sent
*-----------------------------------*/
int count = min(control_send_buffer.bytes_counter, EP0_FIFO_SIZE);
FLUSH_RXEP(ENDPOINT_0);
FLUSH_TXEP(ENDPOINT_0);
/*----------------------------------
* update control buffer parameters
*----------------------------------*/
control_send_buffer.data += count;
control_send_buffer.bytes_counter -= count;
while(count--)
EP_FIFO_WRITE(ENDPOINT_0, *data_ptr++);
}
/*------------------------------------------------------------------------------
* Prototype
* void usbn9604_tx_enable(int ep_num)
*
* Parameters
* ep_num - endpoin number
*
* Returns
* None
*
* Description
* Enable tx endpoint transmission
----------------------------------------------------------------------------*/
void usbn9604_tx_enable(int ep_num)
{
byte Toggle = endpoint_stat[ep_num]->toggle_bit;
/*-------------------------------------------
* update toggle bit of appropriate endpoint
*-------------------------------------------*/
endpoint_stat[ep_num]->toggle_bit = !endpoint_stat[ep_num]->toggle_bit;
Toggle = Toggle << 2;
switch (ep_num){
case ENDPOINT_0:
write_usb(EP_TXC(ep_num), Toggle|TX_EN);
write_usb(EP_RXC(ENDPOINT_0), 0x0);
break;
case ENDPOINT_1:
case ENDPOINT_5:
write_usb(EP_TXC(ep_num), Toggle|TX_LAST|TX_EN);
break;
case ENDPOINT_3: /* isochronous */
write_usb(EP_TXC(ep_num), Toggle|TX_LAST|IGN_ISOMSK|TX_EN);
break;
}
}
/*------------------------------------------------------------------------------
* Prototype
* void usbn9604_tx_retransmit_enable(int ep_num)
*
* Parameters
* ep_num - endpoin number
*
* Returns
* None
*
* Description
* Enable tx data retransmission
----------------------------------------------------------------------------*/
void usbn9604_tx_retransmit_enable(int ep_num)
{
/*------------------------------
* use previous toggle bit value
*------------------------------*/
byte Toggle = endpoint_stat[ep_num]->toggle_bit;
Toggle = Toggle << 2;
if (ep_num == ENDPOINT_0)
/*-------------------------------------------------
* there is no retransmission from the endpoint zero
*------------------------------------------------*/
return;
else
write_usb(EP_TXC(ep_num), Toggle|TX_LAST|TX_EN|RFF);
}
/*----------------------------------------------------------------------------------------------
* Prototype
* void USB_init_dma(endpoint_t endPoint)
*
* Parameters
* endPoint - Number of Endpoint for DMA support
*
* Returns
* None
*
* Description
* This is a sample code for dma initialization. This function should be called before starting
* DMA operation.
----------------------------------------------------------------------------------------------*/
extern USB_endpoint_desc_t *usb_dev_endpoints[];
void USB_init_dma(endpoint_t endPoint)
{
byte dmaControl = 0; /* value of DMA control register */
DMA_ep = endPoint;
/*-------------------------------
* update DMA source field
*-------------------------------*/
dmaControl = ((endPoint - 1)&3);
/*----------------------------------
* update DMA Toggle bit if needeed
*-----------------------------------*/
if (IS_EP_ISO(endPoint))
{
/*----------------------
* Isochronous endpoint.
*-----------------------*/
if (IS_EP_IN(endPoint))
/*------------------------------------------------
* Transmit endpoint
* It seems that in this mode ISO Mask should
* better be ignored.
*-----------------------------------------------*/
write_usb(EP_TXC(endPoint), IGN_ISOMSK);
else
/*------------------------------------------------
* Receive endpoint
* It seems that in this mode toggle compare should
* better be disabled.
*-----------------------------------------------*/
dmaControl |= IGNRXTGL;
}
else
{
/*----------------------------------
* update DMA Toggle bit if needeed
*-----------------------------------*/
if (endpoint_stat[endPoint]->toggle_bit)
dmaControl |= DMA_DTGL;
}
/*------------------------------
* write to DMA control register
*------------------------------*/
write_usb(DMACNTRL,dmaControl);
/*--------------------------------
* clear all dma events to be sure
*--------------------------------*/
write_usb(DMAEV,0x00);
/*-------------------------------------
* do automatic error handling if needed
*------------------------------------*/
write_usb(DMAERR,0x88);
/*-------------------------
* enable DMA interrupts
*-----------------------*/
write_usb(DMAMSK,(DMA_DCNT|DMA_DSIZ|DMA_DERR |DMA_DSHLT ));
/*-----------------------------------------------
* enable DMA Request interrupt for DMA emulation
*------------------------------------------------*/
// ICU_UNMASK_INT(DRQ_INT);
}
/*----------------------------------------------------------------------------------------------
* Prototype
* void USB_start_dma(byte DCOUNT)
*
* Parameters
* DCOUNT - (Number of packets to transfer)
*
* Returns
* None
*
* Description
* This sample code for strat dma process. Call this function each time DMA fills/empties a page.
* Note, after calling this function you must set endpoint Enable bit of respective endpoint
* using ENABLE_EP(endpoint number) macro.
* Before starting DMA process, disable interrupt of respective endpoint using
* DISABLE_TX_INTS(TX_FIFO[number of FIFO]) for transfer operations or
* DISABLE_RX_INTS(RX_FIFO[number of FIFO]) for receive operations
----------------------------------------------------------------------------------------------*/
void USB_start_dma(int DCOUNT)
{
byte dmaControl = 0; /* value of DMA control register */
/*-----------------------------------
* write number of packets to transfer
* to DMA count register
*----------------------------------*/
write_usb(DMACNT,(DCOUNT -1));
/*----------------------------------------------
* Set Atomatic DMA Mode and enable DMA operation
*------------------------------------------------*/
dmaControl = read_usb(DMACNTRL);
dmaControl |= (DMA_ADMA | DMA_DEN);
write_usb(DMACNTRL,dmaControl);
}
/*----------------------------------------------------
* For test use
*----------------------------------------------------*/
#pragma interrupt(usb_drq_handler)
void usb_drq_handler(void)
{
// ICU_clear_int(DRQ_INT);
_disable_();
ICU_MASK_INT(DRQ_INT);
PFDOUT = (PFDOUT & 0x7f);
while (ICU_STATUS_INT(DRQ_INT))
USBDATA = 0x14;
PFDOUT = (PFDOUT | 0x80);
ICU_UNMASK_INT(DRQ_INT);
_enable_();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -