Fix slow CDC OUT by NAKing

This NAKs CDC OUT packets when the ring buffer doesn't have
enough space for it. This makes CDC OUT reliable rather than
allowing overwriting into the ring buffer.
This commit is contained in:
Scott Shawcroft 2019-03-21 14:52:56 -07:00
parent 29b49199be
commit 909891325a
No known key found for this signature in database
GPG Key ID: FD0EDC4B6C53CA59
1 changed files with 33 additions and 6 deletions

View File

@ -87,6 +87,24 @@ typedef struct
//--------------------------------------------------------------------+
CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC] = { { 0 } };
bool pending_read_from_host;
static void _prep_next_transaction(void) {
uint8_t const itf = 0;
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
// skip if previous transfer not complete
if (pending_read_from_host) {
return;
}
// Prepare for incoming data but only allow what we can store in the ring buffer.
uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff);
if (max_read >= CFG_TUD_CDC_EPSIZE) {
dcd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, CFG_TUD_CDC_EPSIZE);
pending_read_from_host = true;
}
}
//--------------------------------------------------------------------+
// APPLICATION API
//--------------------------------------------------------------------+
@ -123,12 +141,19 @@ uint32_t tud_cdc_n_available(uint8_t itf)
char tud_cdc_n_read_char(uint8_t itf)
{
char ch;
return tu_fifo_read(&_cdcd_itf[itf].rx_ff, &ch) ? ch : (-1);
if (!tu_fifo_read(&_cdcd_itf[itf].rx_ff, &ch)) {
ch = -1;
}
_prep_next_transaction();
return ch;
}
uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize)
{
return tu_fifo_read_n(&_cdcd_itf[itf].rx_ff, buffer, bufsize);
uint32_t num_read = tu_fifo_read_n(&_cdcd_itf[itf].rx_ff, buffer, bufsize);
_prep_next_transaction();
return num_read;
}
char tud_cdc_n_peek(uint8_t itf, int pos)
@ -140,6 +165,7 @@ char tud_cdc_n_peek(uint8_t itf, int pos)
void tud_cdc_n_read_flush (uint8_t itf)
{
tu_fifo_clear(&_cdcd_itf[itf].rx_ff);
_prep_next_transaction();
}
//--------------------------------------------------------------------+
@ -207,7 +233,7 @@ void cdcd_init(void)
p_cdc->line_coding.data_bits = 8;
// config fifo
tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, 1, true);
tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, 1, false);
tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, CFG_TUD_CDC_TX_BUFSIZE, 1, false);
#if CFG_FIFO_MUTEX
@ -290,7 +316,8 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t
}
// Prepare for incoming data
TU_ASSERT( dcd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, CFG_TUD_CDC_EPSIZE) );
pending_read_from_host = false;
_prep_next_transaction();
return true;
}
@ -383,8 +410,8 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
// invoke receive callback (if there is still data)
if (tud_cdc_rx_cb && tu_fifo_count(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf);
// prepare for incoming data
TU_ASSERT( dcd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, CFG_TUD_CDC_EPSIZE) );
pending_read_from_host = false;
_prep_next_transaction();
}
// nothing to do with in and notif endpoint