📄 usb_cdc_uart.c
字号:
// Flush_COMbuffers: initialize COM ring buffer
// COMGetByte: read a byte from COM TX buffer
// COMPutByte: write a byte to COM RX buffer
//
// called by USB0 interrupt
//-----------------------------------------------------------------------------
//---------------------------
// SDCC suport
//---------------------------
#if defined SDCC
#pragma save
#pragma nooverlay
#endif // SDCC
void Flush_COMbuffers( void )
{
TXRDIdx = 0;
TXWTIdx = 0;
RXRDIdx = 0;
RXWTIdx = 0;
TXcount = 0;
RXcount = 0;
TXReady = FALSE;
RXReady = TRUE;
cs_Bulk_IN_full_packet = FALSE;
}
//---------------------------
// SDCC suport
//---------------------------
#if defined SDCC
#pragma restore
#endif // SDCC
// TX buffer (host --> UART), UART side
BYTE COMGetByte( void )
{
BYTE dt;
dt = TXBuffer[ TXRDIdx++ ];
if ( TXRDIdx >= TXBUFSIZE ) // at the end of the buffer
TXRDIdx = 0; // go to the head of the buffer
// TXRDIdx &= (TXBUFSIZE - 1); // when TXBUFSIZE is just power of 2
// above two lines are simplied with this line
TXcount--;
TXReady = (TXcount != 0);
return dt;
}
// RX buffer (UART --> host), UART side
void COMPutByte( BYTE dt )
{
RXBuffer[ RXWTIdx++ ] = dt;
if ( RXWTIdx >= RXBUFSIZE ) // at the end of the buffer
RXWTIdx = 0; // go to the head of the buffer
// RXWTIdx &= (RXBUFSIZE - 1); // when RXBUFSIZE is just power of 2
// above two lines are simplied with this line
RXcount++;
RXReady = (RXcount != RXBUFSIZE);
}
//-----------------------------------------------------------------------------
// CDC_Handle_INT_IN
//-----------------------------------------------------------------------------
//
// Interrupt IN EP - Notification element
// Return SerialState notification response (10 bytes) to host
// whenever the status are changed
//
// response
// 0: 0xA1 bmRequestType
// 1: 0x20 bNotification (SERIAL_STATE)
// 2: 0x00 wValue
// 3: 0x00
// 4: 0x00 wIndex (Interface #, LSB first)
// 5: 0x00
// 6: 0x02 wLength (Data length = 2 bytes, LSB first)
// 7: 0x00
// 8: xx UART State Bitmap (16bits, LSB first)
// 9: xx
//
// UART State Bitmap
// 15-8: reserved
// 7: (no spec extra) CTS
// 6: bOverRun overrun error
// 5: bParity parity error
// 4: bFraming framing error
// 3: bRingSignal RI
// 2: bBreak break reception
// 1: bTxCarrier DSR
// 0: bRxCarrier DCD
//
// called by USB0 interrupt
//-----------------------------------------------------------------------------
#define CS_SERIAL_STATE_NUM 0x08
static BYTE code serialStateResponse[ CS_SERIAL_STATE_NUM ] =
{
0xA1, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00
};
//---------------------------
// SDCC suport
//---------------------------
#if defined SDCC
#pragma save
#pragma nooverlay
#endif // SDCC
void CDC_Handle_INT_IN( void )
{
if ( Ep_StatusIN1 == EP_HALT ) return;
if ( cs_Line_State_Update && IN1_FIFO_empty ) // must update and FIFO is empty?
{
cs_Line_State_Update = FALSE;
IN1_FIFO_empty = FALSE;
// Put Serial State Response on Fifo
POLL_WRITE_BYTE(INDEX, 1); // Set index to endpoint 1 registers
FIFO_Write_code(FIFO_EP1, CS_SERIAL_STATE_NUM, serialStateResponse); // send fixed header
USB0DAT = cs_Line_State; // Put UART state bitmap (LSB)
while(USB0ADR & 0x80);
USB0DAT = 0x00; // (MSB)
while(USB0ADR & 0x80);
POLL_WRITE_BYTE(EINCSRL, rbInINPRDY); // validate the FIFO
// Set In Packet ready bit, indicating
// fresh data on Fifo 1
}
}
//---------------------------
// SDCC suport
//---------------------------
#if defined SDCC
#pragma restore
#endif // SDCC
//-----------------------------------------------------------------------------
// CDC_Handle_Bulk_IN
//-----------------------------------------------------------------------------
// Handle bulk IN EP
// - RX buffer (UART --> host), USB side
// - Copy data from RX buffer to bulk IN EP
//
// This routine is called from mainloop
//-----------------------------------------------------------------------------
void CDC_Handle_Bulk_IN( void )
{
BYTE send_cnt, first_cnt, second_cnt;
Trxcnt pos;
bit turnover;
if ( Ep_StatusIN2 == EP_HALT ) return; // If endpoint is ready,
if ( IN2_FIFO_empty && RXcount ) // Is FIFO empty, and any data to send?
{
IN2_FIFO_empty = FALSE;
if ( RXcount > EP2_IN_PACKET_SIZE ) // determine the bytes to send in this transaction
send_cnt = EP2_IN_PACKET_SIZE;
else
send_cnt = (BYTE)RXcount;
pos = RXBUFSIZE - RXRDIdx; // consider on wrap around of ring buffer
if ( send_cnt < pos )
{ // data fits without wrap around
first_cnt = send_cnt;
second_cnt = 0;
turnover = FALSE;
}
else
{ // wrap around is required
first_cnt = (BYTE)pos;
second_cnt = send_cnt - first_cnt;
turnover = TRUE;
}
EIE1 &= ~0x02; // disable USB interrupt
FIFO_WRITE_FUNC( FIFO_EP2, first_cnt, &RXBuffer[ RXRDIdx ] ); // send bytes to FIFO
if ( second_cnt != 0 )
FIFO_WRITE_FUNC( FIFO_EP2, second_cnt, RXBuffer );
POLL_WRITE_BYTE(INDEX, 2); // Set index to endpoint 2 registers
POLL_WRITE_BYTE(EINCSRL, rbInINPRDY); // validate the FIFO
EIE1 |= 0x02; // enable USB interrupt
if ( turnover ) // maintainance of buffer parameters
RXRDIdx = second_cnt;
else
RXRDIdx += send_cnt;
RXcount -= send_cnt;
RXReady = (RXcount != RXBUFSIZE);
// detect full-packet to send ZLP
cs_Bulk_IN_full_packet = (send_cnt == EP2_IN_PACKET_SIZE);
}
}
//-----------------------------------------------------------------------------
// CDC_Handle_Bulk_IN_ZLP
//-----------------------------------------------------------------------------
// When the size of the last packet of the transfer is just the wMaxPacketSize of the EP,
// ZLP is required to terminate the transfer.
//
// called by USB0 interrupt
//-----------------------------------------------------------------------------
//---------------------------
// SDCC suport
//---------------------------
#if defined SDCC
#pragma save
#pragma nooverlay
#endif // SDCC
void CDC_Handle_Bulk_IN_ZLP( void )
{
if ( cs_Bulk_IN_full_packet && IN2_FIFO_empty && (RXcount == 0) )
{ // Send ZLP
POLL_WRITE_BYTE(INDEX, 2); // Set index to endpoint 2 registers
POLL_WRITE_BYTE(EINCSRL, rbInINPRDY); // validate the FIFO without any data
}
}
//---------------------------
// SDCC suport
//---------------------------
#if defined SDCC
#pragma restore
#endif // SDCC
//-----------------------------------------------------------------------------
// CDC_Handle_Bulk_OUT
//-----------------------------------------------------------------------------
// Handle bulk OUT EP
// - TX buffer (host --> UART), USB side
// - Copy data from bulk OUT EP to TX buffer
//
// This routine is called from mainloop
//
//-----------------------------------------------------------------------------
void CDC_Handle_Bulk_OUT( void )
{
BYTE FIFO_Cnt, first_cnt, second_cnt;
Ttxcnt pos;
bit turnover;
if ( Ep_StatusOUT2 == EP_HALT ) return; // If endpoint is ready
if ( OUT2_FIFO_loaded ) // FIFO has data?
{
OUT2_FIFO_loaded = FALSE;
EIE1 &= ~0x02; // disable USB interrupt
POLL_WRITE_BYTE(INDEX, 2); // Set index to endpoint 2 registers
POLL_READ_BYTE(EOUTCNTL, FIFO_Cnt); // read out number of bytes on the FIFO
if ( (TXBUFSIZE - TXcount) >= FIFO_Cnt ) // if any room on the buffer to read out the FIFO
{
pos = TXBUFSIZE - TXWTIdx; // consider on wrap around of ring buffer
if ( FIFO_Cnt < pos )
{
first_cnt = FIFO_Cnt;
second_cnt = 0;
turnover = FALSE;
}
else
{
first_cnt = (BYTE)pos;
second_cnt = FIFO_Cnt - first_cnt;
turnover = TRUE;
}
FIFO_READ_FUNC( FIFO_EP2, first_cnt, &TXBuffer[ TXWTIdx ] ); // read bytes from FIFO
if ( second_cnt != 0 )
FIFO_READ_FUNC( FIFO_EP2, second_cnt, TXBuffer );
POLL_WRITE_BYTE(EOUTCSRL, 0); // Clear Out Packet ready bit
if ( turnover ) // maintainance of buffer parameters
TXWTIdx = second_cnt;
else
TXWTIdx += FIFO_Cnt;
TXcount += FIFO_Cnt;
TXReady = (TXcount != 0);
}
EIE1 |= 0x02; // enable USB interrupt
}
}
//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -