📄 usbdrv.c
字号:
/*----------------------------------------------------------------------------
* Copyright (c) 2001 by National Semiconductor Corporation
* National Semiconductor Corporation
*
* All rights reserved
*
*<<<-------------------------------------------------------------------------
* File Contents:
* usb.c - USB related functions
*
* Project: USB Demo firmware
* Author : Yan Nosovitsky
* Date : Oct 2001
*----------------------------------------------------------------------->>>*/
#include "..\include\all.h"
#define BPTG \
__asm__("push $1,r0"); \
__asm__("movw $0,r0"); \
__asm__("lpr sp,carl"); \
__asm__("lpr r0,carh"); \
__asm__("movw $0xc1,r0"); \
__asm__("lpr r0,dcr"); \
__asm__("pop $1, r0");
/*=====================================================================
* USB Driver Definitions
*=====================================================================*/
extern Device_buffers_t device_buffers;
endpoint_t DMA_ep;
endpoint_status_t tx0_ep_stat;
endpoint_status_t tx1_ep_stat, tx2_ep_stat;
endpoint_status_t rx1_ep_stat, rx2_ep_stat;
endpoint_status_t tx3_ep_stat;
endpoint_status_t *endpoint_stat[] =
{
&tx0_ep_stat,
&tx1_ep_stat,
&rx1_ep_stat,
&tx2_ep_stat,
&rx2_ep_stat,
&tx3_ep_stat,
NULL
};
void endpoint_status_init() {
int i;
for(i=0;i<NUM_OF_ENDPOINTS;i++) {
if (endpoint_stat[i] != NULL) {
endpoint_stat[i]->FIFO_status = EMPTY;
if (i==0)
/*----------------
* control endpoint
*-----------------*/
endpoint_stat[i]->toggle_bit = 0x01;
else
/*----------------------
* tx & rx data endpoints
*-----------------------*/
endpoint_stat[i]->toggle_bit = 0x00;
}
}
}
const int usbn9604_tx_endpoint_addr[] =
{
TXD0, /* Endpoint 0 */
TXD1, /* Endpoint 1 */
0xFF,
TXD2, /* Endpoint 3 */
0xFF,
TXD3, /* Endpoint 5 */
0xFF
};
const int usbn9604_rx_endpoint_addr[] =
{
RXD0, /* Endpoint 0 */
0xFF,
RXD1, /* Endpoint 2 */
0xFF,
RXD2, /* Endpoint 4 */
0xFF,
RXD3 /* Endpoint 6 */
};
const int fifo_sizes[] =
{
EP0_FIFO_SIZE, /* control tx0, rx0 */
TX_BULK_EP_FIFO_SIZE, /* bulk tx */
RX_BULK_EP_FIFO_SIZE, /* bulk rx */
TX_ISO_EP_FIFO_SIZE, /* ISO tx */
RX_ISO_EP_FIFO_SIZE, /* ISO rx */
TX_INTR_EP_FIFO_SIZE, /* interrupt tx */
RX_INTR_EP_FIFO_SIZE /* interrupt rx */
};
const int endpoint_to_fifo[] =
{
TX_FIFO0, /* endpoint0 TX/RX FIFO0 */
TX_FIFO1, /* endpoint1 */
RX_FIFO1, /* endpoint2 */
TX_FIFO2, /* endpoint3 */
RX_FIFO2, /* endpoint4 */
TX_FIFO3, /* endpoint5 */
RX_FIFO3 /* endpoint6 */
};
/*=============================================================================
* Data Buffer Definitions
*=============================================================================*/
control_buffer_t control_send_buffer;
control_buffer_t control_receive_buffer;
byte request_buffer[EP0_FIFO_SIZE];
void clear_control_buffer(control_buffer_t* control_buff) {
control_buff->data = NULL;
control_buff->bytes_counter = 0;
}
/*=====================================================================
* USB Driver Implementations
*=====================================================================*/
/*----------------------------------------------------------------------------------------------
* Prototype
* void usb_node_handler()
*
* Parameters
* None
*
* Returns
* None
*
* Description
* USB interrupt handler.
----------------------------------------------------------------------------------------------*/
#pragma interrupt(usb_node_handler)
void usb_node_handler(void){
byte usbn_event;
PCDOUT &= 0x0;
_disable_();
/*-------------------
* Clear the interrupt
*-------------------*/
ICU_clear_int(USB_NODE_INT);
while(usbn_event = read_usb(MAEV))
{
if (usbn_event & RX_EV)
USBN9604_rx_event_handler();
if (usbn_event & ALT)
USBN9604_alt_event_handler();
if (usbn_event & TX_EV)
USBN9604_tx_event_handler();
if (usbn_event & NAK)
{
if (read_usb(NAKEV) & 0x10)
{/*----------
* NAK OUT
*---------*/
FLUSHTX0;
FLUSHRX0;
/*------------------
* re enable receving
*-------------------*/
DISABLE_TX(ENDPOINT_0);
ENABLE_RX(ENDPOINT_0);
}
}
}
_enable_();
}
/*----------------------------------------------------------------------------------------------
* Prototype
* void USBN9602_tx_event_handler()
*
* Parameters
* None
*
* Returns
* None
*
* Description
* TX event handler
----------------------------------------------------------------------------------------------*/
__inline__ void USBN9604_tx_event_handler(void)
{
volatile byte tx_event = TX_EVENTS;
byte evnt_mask = 1;
byte txstat;
while(tx_event)
{
switch(tx_event & evnt_mask)
{
case TX_FIFO0:
/*-----------
* endpoint 0
* zero tx endpoint
*-----------*/
txstat = EP_TXSTATUS(ENDPOINT_0);
if (txstat & ACK_STAT)
{
/*--------------------------------------
* previous data packet from current
* ep was received successfully by host
*-------------------------------------*/
endpoint_stat[ENDPOINT_0]->FIFO_status = EMPTY;
if (control_send_buffer.bytes_counter > 0)
{
/*-------------------------------------
* there is additional data to be sent
*------------------------------------*/
fill_control_fifo();
usbn9604_tx_enable(ENDPOINT_0);
}
else if (device_buffers.zero_data == 1)
{
/*-------------------
* zero data required
*-------------------*/
device_buffers.zero_data = 0;
FLUSH_TXEP(ENDPOINT_0);
usbn9604_tx_enable(ENDPOINT_0);
}
else
{
FLUSH_TXEP(ENDPOINT_0);
ENABLE_RX(ENDPOINT_0);
}
}
else
/*-------------------
* there is no ACK
* Re-enable receiving
*--------------------*/
ENABLE_RX(ENDPOINT_0);
break;
case TX_FIFO1:
/*----------------
* endpoint 1
* bulk tx endpoint
*----------------*/
txstat = EP_TXSTATUS(ENDPOINT_1);
if (txstat & ACK_STAT)
{
/*-----------------------------------------------------------------------
* previous data packet from current ep was received successfully by host
*-----------------------------------------------------------------------*/
FLUSHTX1;
send_event(EVT_USB_BULK_TX);
}
else
/*------------------------------------
* there is no ACK
* retransmit the previous data packet
*------------------------------------*/
usbn9604_tx_retransmit_enable(ENDPOINT_1);
break;
case TX_FIFO2:
/*-----------------------
* endpoint 3
* isochronous tx endpoint
*-----------------------*/
txstat = EP_TXSTATUS(ENDPOINT_3);
// PCDOUT &= ~0x2;
// PCDOUT |= 0x2;
if (txstat & ACK_STAT)
{
/*-----------------------------------------
* Data was sent in response to an IN token
*-----------------------------------------*/
FLUSHTX2;
send_event(EVT_USB_ISO_TX);
}
else
{
/*------------------------
* ISO frame was discarded
* Do nothing
*------------------------*/
}
break;
case TX_FIFO3:
/*-----------------------
* endpoint 5
* interrupt tx endpoint
*-----------------------*/
txstat = EP_TXSTATUS(ENDPOINT_5);
if (txstat & ACK_STAT)
{
/*-----------------------------------------------------------------------
* previous data packet from current ep was received successfully by host
*-----------------------------------------------------------------------*/
FLUSHTX3;
}
else
/*------------------------------------
* there is no ACK
* retransmit the previous data packet
*------------------------------------*/
usbn9604_tx_retransmit_enable(ENDPOINT_5);
break;
case TX_UDRN0:
case TX_UDRN1:
case TX_UDRN2:
case TX_UDRN3:
break;
default:
/*-------------------------------
* No event with this event mask
*-------------------------------*/
break;
}
tx_event &= ~evnt_mask;
evnt_mask = evnt_mask << 1;
}
}
/*----------------------------------------------------------------------------------------------
* Prototype
* void USBN9604_alt_event_handler()
*
* Parameters
* None
*
* Returns
* None
*
* Description
* ALT event handler
----------------------------------------------------------------------------------------------*/
void USBN9604_alt_event_handler(void)
{
volatile byte alt_event = ALT_EVENTS;
volatile byte dma_event = 0;
byte evnt_mask = 1;
byte tmp = 0;
extern void USB_dev_reset(void);
while(alt_event)
{
switch(alt_event & evnt_mask)
{
case ALT_DMA:
/*------------
* DMA events
*------------*/
dma_event = DMA_EVENTS ;
/*--------------------------------
* clear all dma events to be sure
*--------------------------------*/
write_usb(DMAEV,0x00);
switch (dma_event&0xf){
case DMA_DSIZ:
/*----------------------------------------------------------
* Only for DMA receive operation
* It indicates that a packet has been received which is less
* then the full length of the FIFO. This normally indicates
* the end of transfer.
* ---------------------------------------------------------*/
/*------------------
* update toggle bit
*-------------------*/
if (DMA_NTGL&dma_event)
endpoint_stat[DMA_ep]->toggle_bit = 1;
else
endpoint_stat[DMA_ep]->toggle_bit = 0;
/*------------------------
* Insert your code here
*------------------------*/
break;
case DMA_DCNT:
/*-------------------------------------
* DMA count (DMA Count) regiser is 0
* ADMA is stopped
*------------------------------------*/
/*-----------------
* update toggle bit
*------------------*/
tmp = read_usb(DMACNTRL);
if (DMA_NTGL&dma_event)
{
tmp |= DMA_DTGL;
endpoint_stat[DMA_ep]->toggle_bit = 1;
}
else
{
tmp &= ~DMA_DTGL;
endpoint_stat[DMA_ep]->toggle_bit = 0;
}
/*----------------------------
* re-enable USB DMA operation
------------------------------*/
write_usb(DMACNTRL,tmp);
USB_start_dma(9 /* may be any number from 0 to 255 */);
/*------------------------
* Insert your code here
*------------------------*/
break;
case DMA_DERR:
break;
case DMA_DSHLT:
break;
}
break;
case ALT_RESET:
CLEAR_STALL_EP0;
GOTO_STATE(RST_ST);
/*--------------------
* set default address
*--------------------*/
write_usb(FAR,AD_EN+0);
/*----------------
* enable EP0 only
*----------------*/
write_usb(EPC0, 0x00);
/*---------------
* Go Reset state
*---------------*/
reset_usb();
usb_device_reset();
/*--------------
* Go operational
*---------------*/
GOTO_STATE(OPR_ST);
break;
case ALT_SD3:
case ALT_SD5:
/*------------------
* Enable Resume int
*------------------*/
ENABLE_ALT_INTS(ALT_SD3|ALT_RESET|ALT_RESUME|ALT_DMA);
/*-------------------
* enter suspend state
*------------------*/
GOTO_STATE(SUS_ST);
break;
case ALT_RESUME:
/*------------------
* Disabe Resume int
*------------------*/
ENABLE_ALT_INTS(ALT_SD3|ALT_RESET|ALT_DMA);
/*----------------
* Enable receving
*---------------*/
GOTO_STATE(OPR_ST);
/*-----------------
* Operational state
*-----------------*/
ENABLE_RX(ENDPOINT_0);
break;
case ALT_EOP:
break;
default:
/*------------------------------
* No event with this event mask
*------------------------------*/
break;
}
alt_event &= ~evnt_mask;
evnt_mask = evnt_mask << 1;
}
}
byte ep2diag = 0;
byte mac2 = 0;
/*----------------------------------------------------------------------------------------------
* Prototype
* void USBN9604_rx_event_handler()
*
* Parameters
* None
*
* Returns
* None
*
* Description
* RX event handler
----------------------------------------------------------------------------------------------*/
__inline__ void USBN9604_rx_event_handler(void)
{
volatile byte rx_event = RX_EVENTS;
byte evnt_mask = 1;
volatile byte rxstat;
byte Toggle;
byte i;
int request_length;
endpoint_t ep_num = ENDPOINT_0;
while(rx_event)
{
switch(rx_event & evnt_mask)
{
case RX_FIFO0:
/*-----------
* endpoint 0
*-----------*/
ep_num = ENDPOINT_0;
clear_control_buffer(&control_receive_buffer);
/*-----------------------
* Is this a setup packet?
*-----------------------*/
rxstat = EP_RXSTATUS(ENDPOINT_0);
if (rxstat & SETUP_R)
{
/*----------------------
* Clear STALL condition
*----------------------*/
endpoint_stat[0]->toggle_bit = 0x01;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -