📄 usbn960x.c
字号:
status=usbn_read(USBN_TXEV) & USBN_TXMSK_ENABLES;
debug(debug_txb,"T %X ",status);
if (status & 0xF0) {
//TODO: not used by CCS
}
if (bit_test(status,0)) { //sent data out of EP0
txs=usbn_read(USBN_TXS0);
debug(debug_txb,"%X ",txs);
if (bit_test(txs,6)) {
if (USB_dev_req != NONE) { //if we are processing a report then send the next part
usb_isr_tok_in_dne(0);
}
else {
usbn_write(USBN_TXC0, 0x08); //flush TX FIFO, disable TX_EN
usbn_write(USBN_RXC0, 0x08); //flush RX FIFO
usbn_write(USBN_RXC0, 0x01); //enable reception
}
}
else {
usbn_write(USBN_RXC0, 0x01);
}
usb_clear_ep0_buffer();
}
if (bit_test(status,1)) {
txs=usbn_read(USBN_TXS1);
usb_isr_tok_in_dne(usb_epc_in_address[1]);
}
if (bit_test(status,2)) {
txs=usbn_read(USBN_TXS2);
usb_isr_tok_in_dne(usb_epc_in_address[2]);
}
if (bit_test(status,3)) {
txs=usbn_read(USBN_TXS3);
usb_isr_tok_in_dne(usb_epc_in_address[3]);
}
}
/*******************************************************************************
/* usb_check_rxev()
/*
/* Summary: Handles the RX interrupt. This happens when an OUT/SETUP token has happened (HOST -> PIC)
/* and there is data in the RX buffers.
/*
/* If there is data in the EP0 buffer and it is a SETUP token, it is processed by the
/* SETUP token handler. The SETUP token handler is the bulk of this code.
/*
/* If there is data in the EP1-3 buffers then data is placed into RAM on the PIC.
/* (See usb_isr_tok_out_dne(endpoint)).
/*
/* TODO: Not provided by CCS - handle non SETUP data on EP0.
/*
/********************************************************************************/
void usb_check_rxev(void) {
int8 status, rxstatus, len;
status=usbn_read(USBN_RXEV) & USBN_RXMSK_ENABLES;
debug(debug_txb,"R %X ",status);
if (status & 0xF0) {
debug(debug_txb,"O "); //TODO: not used by CCS
}
if (bit_test(status,0)) {
rxstatus=usbn_read(USBN_RXS0);
debug(debug_txb,"%X ",rxstatus);
len=rxstatus & 0x0F;
if ( (len==0) && (bit_test(rxstatus,4)) ) { //skip the zero len packet, get the next one
//I have noticed that if you wait to long to get a packet from the buffer that the USBN960x device
//fails and kills the buffer. The USBN960x crashes the buffer until a reset, and the
//USBN960x then thinks there is a 0 length packet. Sometimes
//it may even think it has a 0 length setup packet (which is not possible). When this starts
//happening the only way I found around the problem was to turn off debugging. Although the
//debugging was coded in a way that it should not interfere with the USB interrupt, sometimes it still
//would. I did not have such a problem with debugging output on the PIC16C7x5 USB part.
}
else if (bit_test(rxstatus,6)) { //setup
usbn_write(USBN_EPC0, usbn_read(USBN_EPC0) & 0x7F); //clear STALL
if (len==USB_MAX_EP0_PACKET_LENGTH) {
usb_get_packet(0, usb_ep0_rx_buffer, len); //should always be a length of 8, but just in case
usbn_write(USBN_TXC0, 0x08); //flush TX FIFO
usb_isr_tok_setup_dne();
}
else {
usbn_write(USBN_RXC0, 0x01); //flush RX FIFO
}
usb_clear_ep0_buffer();
}
else {
//TODO: handle OUT tokens to EP0. CCS only handles SETUP tokens.
usbn_write(USBN_RXC0, 0x08); //flush RX buffer.
usbn_write(USBN_RXC0, 0x01); //re-enable reception
}
}
if (bit_test(status,1)) {usb_isr_tok_out_dne(usb_epc_out_address[1]);}
if (bit_test(status,2)) {usb_isr_tok_out_dne(usb_epc_out_address[2]);}
if (bit_test(status,3)) {usb_isr_tok_out_dne(usb_epc_out_address[3]);}
}
/// END USB Interrupt Service Routine
/// BEGIN USBN960x Functions only used in this File
/*******************************************************************************
/* usbn_write(address, data)
/*
/* Input: address - address of USBN960x register to write to
/* data - data to write to USBN960x
/*
/* Summary: Writes a byte of memory to specified address on USBN960x
/*
/********************************************************************************/
void usbn_write(int8 address, int8 data) {
output_high(USBN_RD);
output_high(USBN_WR);
usbn_bus_out(address);
output_high(USBN_A0);
output_low(USBN_CS);
output_low(USBN_WR);
output_high(USBN_WR);
output_high(USBN_CS);
output_float(USBN_A0);
usbn_bus_out(data);
output_low(USBN_A0);
output_low(USBN_CS);
output_low(USBN_WR);
output_high(USBN_WR);
output_high(USBN_CS);
output_float(USBN_A0);
usbn_bus_float();
}
/*******************************************************************************
/* usbn_read(address)
/*
/* Input: address - address of USBN960x register to read
/* Output: data (byte) in specified address.
/*
/* Summary: Reads a byte of memory from specified address on USBN960x
/*
/********************************************************************************/
int8 usbn_read(int8 address) {
int8 data;
output_high(USBN_RD);
output_high(USBN_WR);
usbn_bus_out(address);
output_high(USBN_A0);
output_low(USBN_CS);
output_low(USBN_WR);
output_high(USBN_WR);
output_high(USBN_CS);
output_float(USBN_A0);
usbn_bus_float();
output_low(USBN_A0);
output_low(USBN_CS);
output_low(USBN_RD);
data=usbn_bus_in();
output_high(USBN_RD);
output_high(USBN_CS);
output_float(USBN_A0);
usbn_bus_float();
return(data);
}
/*******************************************************************************
/* usb_find_epc()
/*
/* Input: endpoint - endpoint to find USBN channel number
/* direction - direction of endpoint. 0 == OUT or CONTROL, 1 == IN
/* Output: returns the USBN960x channel number
/*
/* Summary: The USBN960x has 7 channels (EP0, EP1-3 TX, and EP1-3 RX), but
/* EP1-3 TX/RX can be mapped to any endpoint from 1-15. This function
/* looks up what endpoint is mapped to what channel. See usb_epc_out_address[]
/* and usb_epc_in_address[] on how to map channels to endpoint. CCS defaults to
/* channel 1 <-> endpoint 1, channel 2 <-> endpoint 2, channel 3 <-> endpoint 3.
/*
/********************************************************************************/
int8 usb_find_epc(int8 endpoint, int1 direction) {
int8 epc;
int8 found=0xFF;
for (epc=0;epc<4;epc++) {
if (direction) {
if (usb_epc_in_address[epc]==endpoint) {found=(epc*2); if (epc) {found--;} return(found);} //0,1,3,5
}
else {
if (usb_epc_out_address[epc]==endpoint) {found=epc*2; return(found);} //0,2,4,6
}
}
return(found);
}
/*******************************************************************************
/* usb_reset()
/*
/* Summary: Resetsthe USB token handler code, resets the USBN device (software reset, not hardware),
/* clears all the USBN buffers, clears the local EP0 buffer, enables reception
/* on EP0.
/*
/********************************************************************************/
void usb_reset(void) {
usb_token_reset();
usbn_write(USBN_FAR, 0);
usbn_write(USBN_EPC0,0);
usbn_write(USBN_NFSR, USBN_NFSR_RESET);
usbn_write(USBN_TXC0, 0x08); //flush fifos
usbn_write(USBN_TXC1, 0x08);
usbn_write(USBN_TXC2, 0x08);
usbn_write(USBN_TXC3, 0x08);
usbn_write(USBN_RXC0, 0x08);
usbn_write(USBN_RXC1, 0x08);
usbn_write(USBN_RXC2, 0x08);
usbn_write(USBN_RXC3, 0x08);
usb_clear_ep0_buffer();
usbn_write(USBN_RXC0, 0x01); //enable rx0
}
/*******************************************************************************
/* usb_enable_endpoint()
/*
/* Input: endpoint - endpoint to enable
/* direction - direction of endpoint. 0 == OUT or CONTROL, 1 == IN
/* iso - TRUE if the endpoint is isochronous, FALSE if it is a bulk/interrupt endpoint.
/*
/* Summary: Enables endpoint for receiving / transmitting.
/*
/********************************************************************************/
void usb_enable_endpoint(int8 endpoint, int1 direction, int1 iso) {
int8 epc, address, value;
if ((endpoint < 16)&&(endpoint)) {
epc=usb_find_epc(endpoint,direction);
if (epc!=0xFF) {
address=USBN_EPCx[epc];
value= epc_to_epadd[epc] | 0x10;
if (iso) {value |= 0x20;}
usbn_write(address,value);
if (!direction) {
address=USBN_RX_FIFOx[epc] + 2;
value=usbn_read(address);
value |= 1; //enable reception
usbn_write(address, value);
#if USB_EP1_RX_SIZE
if (endpoint == 1) {
usb_ep1_rx_status.rx = 0;
usb_ep1_rx_status.ov = 0;
}
#endif
#if USB_EP2_RX_SIZE
if (endpoint == 2) {
usb_ep2_rx_status.rx = 0;
usb_ep2_rx_status.ov = 0;
}
#endif
#if USB_EP3_RX_SIZE
if (endpoint == 3) {
usb_ep3_rx_status.rx = 0;
usb_ep3_rx_status.ov = 0;
}
#endif
#if USB_EP4_RX_SIZE
if (endpoint == 4) {
usb_ep4_rx_status.rx = 0;
usb_ep4_rx_status.ov = 0;
}
#endif
#if USB_EP5_RX_SIZE
if (endpoint == 5) {
usb_ep5_rx_status.rx = 0;
usb_ep5_rx_status.ov = 0;
}
#endif
#if USB_EP6_RX_SIZE
if (endpoint == 6) {
usb_ep6_rx_status.rx = 0;
usb_ep6_rx_status.ov = 0;
}
#endif
#if USB_EP7_RX_SIZE
if (endpoint == 7) {
usb_ep7_rx_status.rx = 0;
usb_ep7_rx_status.ov = 0;
}
#endif
#if USB_EP8_RX_SIZE
if (endpoint == 8) {
usb_ep8_rx_status.rx = 0;
usb_ep8_rx_status.ov = 0;
}
#endif
#if USB_EP9_RX_SIZE
if (endpoint == 9) {
usb_ep9_rx_status.rx = 0;
usb_ep9_rx_status.ov = 0;
}
#endif
#if USB_EP10_RX_SIZE
if (endpoint == 10) {
usb_ep10_rx_status.rx = 0;
usb_ep10_rx_status.ov = 0;
}
#endif
#if USB_EP11_RX_SIZE
if (endpoint == 11) {
usb_ep11_rx_status.rx = 0;
usb_ep11_rx_status.ov = 0;
}
#endif
#if USB_EP12_RX_SIZE
if (endpoint == 12) {
usb_ep12_rx_status.rx = 0;
usb_ep12_rx_status.ov = 0;
}
#endif
#if USB_EP13_RX_SIZE
if (endpoint == 13) {
usb_ep13_rx_status.rx = 0;
usb_ep13_rx_status.ov = 0;
}
#endif
#if USB_EP14_RX_SIZE
if (endpoint == 14) {
usb_ep14_rx_status.rx = 0;
usb_ep14_rx_status.ov = 0;
}
#endif
#if USB_EP15_RX_SIZE
if (endpoint == 15) {
usb_ep15_rx_status.rx = 0;
usb_ep15_rx_status.ov = 0;
}
#endif
}
}
}
}
/*******************************************************************************
/* usb_disable_endpoint()
/*
/* Input: endpoint - endpoint to enable
/* direction - direction of endpoint. 0 == OUT or CONTROL, 1 == IN
/*
/* Summary: Disables endpoint. A disabled interrupt does not respond to tokens.
/*
/********************************************************************************/
void usb_disable_endpoint(int8 endpoint, int1 direction) {
int8 epc, address, value;
if ((endpoint != 0)&&(endpoint < 16)) {
epc=usb_find_epc(endpoint,direction);
if (epc!=0xFF) {
address=USBN_EPCx[epc];
value=usbn_read(address);
value &= 0xEF;
usbn_write(address,value);
if (direction) {address=USBN_TX_FIFOx[epc];} else {address=USBN_RX_FIFOx[epc];}
address+=2;
value=usbn_read(address);
value &= 0xFE; //disable TX_EN or RX_EN
usbn_write(address,value);
}
}
}
void usb_clear_ep0_buffer(void) {
int8 i;
for (i=0;i<USB_MAX_EP0_PACKET_LENGTH;i++) {
usb_ep0_rx_buffer[i]=0;
}
}
/// END USBN960x Functions only used in this File
#ENDIF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -