Open
Description
Right now we don't do USB flow control on nRF52840 - this should be as easy as just delaying app_usbd_cdc_acm_read
until we have space for more data, but it doesn't appear to work.
In fact increasing the rx buffer from 1 byte to 64 bytes (which would be sensible) doesn't work either, so I think something strange is going on here.
diff --git a/targets/nrf5x/jshardware.c b/targets/nrf5x/jshardware.c
index b63478fea..7f1eac97b 100644
--- a/targets/nrf5x/jshardware.c
+++ b/targets/nrf5x/jshardware.c
@@ -177,6 +177,10 @@ static char m_tx_buffer[NRF_DRV_USBD_EPSIZE];
static bool m_usb_connected = false;
static bool m_usb_open = false;
static bool m_usb_transmitting = false;
+/** Set to true in cdc_acm_user_ev_handler if we need to call
+ cdc_acm_user_setup_rx when there's sufficient space in our buffer
+ so we ack the transfer and can get more data */
+static volatile bool m_usb_wait_rx_ack = false;
void on_usb_disconnected() {
m_usb_open = false;
@@ -187,6 +191,15 @@ void on_usb_disconnected() {
jshTransmitClearDevice(EV_USBSERIAL); // clear the transmit queue
}
+static ret_code_t cdc_acm_user_setup_rx() {
+ m_usb_wait_rx_ack = false;
+ return app_usbd_cdc_acm_read(&m_app_cdc_acm,
+ m_rx_buffer,
+ sizeof(m_rx_buffer));
+ // we expect ret=NRF_ERROR_IO_PENDING here
+ // jsiConsolePrintf("app_usbd_cdc_acm_read -> %d\n", ret);
+}
+
/**
* @brief User event handler @ref app_usbd_cdc_acm_user_ev_handler_t (headphones)
* */
@@ -204,12 +217,7 @@ static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
m_usb_open = true;
m_usb_transmitting = false;
/*Setup first transfer*/
- ret_code_t ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
- m_rx_buffer,
- sizeof(m_rx_buffer));
- UNUSED_VARIABLE(ret);
- // we expect ret=NRF_ERROR_IO_PENDING here
- // jsiConsolePrintf("app_usbd_cdc_acm_read -> %d\n", ret);
+ cdc_acm_user_setup_rx();
// USB connected - so move console device over to it
if (jsiGetConsoleDevice()!=EV_LIMBO) {
@@ -236,11 +244,12 @@ static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
jshPushIOCharEvents(EV_USBSERIAL, m_rx_buffer, size);
jshHadEvent();
-
- /*Setup next transfer*/
- ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
- m_rx_buffer,
- sizeof(m_rx_buffer));
+ /* If we pass the XOFF threshold, don't request more data and in the idle loop we'll check if we have space and if so will setup the next transfer */
+ if (jshGetEventsUsed() > IOBUFFER_XOFF) {
+ m_usb_wait_rx_ack = true;
+ return;
+ }
+ ret = cdc_acm_user_setup_rx();
} while (ret == NRF_SUCCESS);
break;
}
@@ -653,6 +662,10 @@ void SysTick_Handler(void) {
jsiOneSecondAfterStartup();
}
+ // Kick USB if it's needed after RX fifo overflowed
+ if (m_usb_wait_rx_ack && (jshGetEventsUsed() < IOBUFFER_XON))
+ cdc_acm_user_setup_rx();
+
JsSysTime currTime = jshGetSystemTime();
JsSysTime t = (currTime - lastSysTickTime);
if (t>0xFFFFFFFFU) t = 0xFFFFFFFFU;
When sending with the IDE the reads end up seemingly delayed by several characters.
If we can't fix this we could always turn on XON/XOFF flow control for USB on nRF52840?
Metadata
Metadata
Assignees
Labels
No labels