From 4d515034681f8f842221c55f24ef1a1c39d1af07 Mon Sep 17 00:00:00 2001 From: Venelin Efremov Date: Sun, 17 Feb 2019 19:08:42 -0800 Subject: [PATCH 1/5] Do not block writes to USBSerial if CDC interface is not connected --- cores/arduino/USBSerial.cpp | 2 ++ cores/arduino/stm32/usb/cdc/usbd_cdc_if.c | 5 +++++ cores/arduino/stm32/usb/cdc/usbd_cdc_if.h | 1 + 3 files changed, 8 insertions(+) diff --git a/cores/arduino/USBSerial.cpp b/cores/arduino/USBSerial.cpp index 92ba1b60da..72b2c35ce1 100644 --- a/cores/arduino/USBSerial.cpp +++ b/cores/arduino/USBSerial.cpp @@ -83,6 +83,8 @@ size_t USBSerial::write(const uint8_t *buffer, size_t size) buffer += portion; // After storing data, start transmitting process CDC_continue_transmit(); + } else if (!CDC_connected()) { + return size; } } return size; diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c index f55b74aea2..184866d96d 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c @@ -245,6 +245,11 @@ void CDC_deInit(void) } } +uint8_t CDC_connected() +{ + return hUSBD_Device_CDC.dev_state == USBD_STATE_CONFIGURED; +} + void CDC_continue_transmit(void) { uint16_t size; diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h index 155b61b973..507dc75809 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h @@ -50,6 +50,7 @@ void CDC_continue_transmit(void); void CDC_resume_receive(void); void CDC_init(void); void CDC_deInit(void); +uint8_t CDC_connected(); #ifdef __cplusplus } From 60e4d4a32c5ed4a23ad422be374fd625e0d7849e Mon Sep 17 00:00:00 2001 From: Venelin Efremov Date: Sun, 17 Feb 2019 19:14:02 -0800 Subject: [PATCH 2/5] Return the correct bytes written --- cores/arduino/USBSerial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/arduino/USBSerial.cpp b/cores/arduino/USBSerial.cpp index 72b2c35ce1..09502925e3 100644 --- a/cores/arduino/USBSerial.cpp +++ b/cores/arduino/USBSerial.cpp @@ -84,7 +84,7 @@ size_t USBSerial::write(const uint8_t *buffer, size_t size) // After storing data, start transmitting process CDC_continue_transmit(); } else if (!CDC_connected()) { - return size; + return size - rest; } } return size; From 5e0da73fc0e18cb8bab044a60fa2491859f61476 Mon Sep 17 00:00:00 2001 From: Venelin Efremov Date: Mon, 18 Feb 2019 01:00:16 -0800 Subject: [PATCH 3/5] Check the DTR value when deciding to drop data --- cores/arduino/stm32/usb/cdc/usbd_cdc_if.c | 4 ++-- cores/arduino/stm32/usb/cdc/usbd_cdc_if.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c index 184866d96d..e06b4b076c 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c @@ -245,9 +245,9 @@ void CDC_deInit(void) } } -uint8_t CDC_connected() +bool CDC_connected() { - return hUSBD_Device_CDC.dev_state == USBD_STATE_CONFIGURED; + return hUSBD_Device_CDC.dev_state == USBD_STATE_CONFIGURED && lineState; } void CDC_continue_transmit(void) diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h index 507dc75809..32f47e6beb 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h @@ -50,7 +50,7 @@ void CDC_continue_transmit(void); void CDC_resume_receive(void); void CDC_init(void); void CDC_deInit(void); -uint8_t CDC_connected(); +bool CDC_connected(); #ifdef __cplusplus } From 93734621c1b5af8ab9a518f95a7dcc42e4b545e4 Mon Sep 17 00:00:00 2001 From: Venelin Efremov Date: Mon, 18 Feb 2019 03:43:52 -0800 Subject: [PATCH 4/5] Check if the last packet we tried to transfer is taking too long --- cores/arduino/USBSerial.cpp | 4 ++-- cores/arduino/stm32/usb/cdc/usbd_cdc_if.c | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/cores/arduino/USBSerial.cpp b/cores/arduino/USBSerial.cpp index 09502925e3..291f411fd5 100644 --- a/cores/arduino/USBSerial.cpp +++ b/cores/arduino/USBSerial.cpp @@ -84,10 +84,10 @@ size_t USBSerial::write(const uint8_t *buffer, size_t size) // After storing data, start transmitting process CDC_continue_transmit(); } else if (!CDC_connected()) { - return size - rest; + break; } } - return size; + return size - rest; } int USBSerial::available(void) diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c index e06b4b076c..0372ef9170 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c @@ -32,6 +32,15 @@ #define CDC_MAX_PACKET_SIZE USB_MAX_EP0_SIZE #endif +/* + * The value USB_CDC_TRANSMIT_TIMEOUT is defined in terms of HAL_GetTick() units. + * Typically it is 1ms value. The timeout determines when we would consider the + * host "too slow" and threat the USB CDC port as disconnected. + */ +#ifndef USB_CDC_TRANSMIT_TIMEOUT +#define USB_CDC_TRANSMIT_TIMEOUT 3 +#endif + /* USBD_CDC Private Variables */ /* USB Device Core CDC handle declaration */ USBD_HandleTypeDef hUSBD_Device_CDC; @@ -43,6 +52,7 @@ CDC_TransmitQueue_TypeDef TransmitQueue; CDC_ReceiveQueue_TypeDef ReceiveQueue; __IO uint32_t lineState = 0; __IO bool receivePended = true; +static uint32_t transmitStart = 0; /** USBD_CDC Private Function Prototypes */ @@ -212,6 +222,7 @@ static int8_t USBD_CDC_Receive(uint8_t *Buf, uint32_t *Len) static int8_t USBD_CDC_Transferred(void) { + transmitStart = 0; CDC_TransmitQueue_CommitRead(&TransmitQueue); CDC_continue_transmit(); return (USBD_OK); @@ -247,7 +258,13 @@ void CDC_deInit(void) bool CDC_connected() { - return hUSBD_Device_CDC.dev_state == USBD_STATE_CONFIGURED && lineState; + uint32_t transmitTime = 0; + if (transmitStart) { + transmitTime = HAL_GetTick() - transmitStart; + } + return hUSBD_Device_CDC.dev_state == USBD_STATE_CONFIGURED + && transmitTime < USB_CDC_TRANSMIT_TIMEOUT + && lineState; } void CDC_continue_transmit(void) @@ -266,6 +283,7 @@ void CDC_continue_transmit(void) if (hcdc->TxState == 0U) { buffer = CDC_TransmitQueue_ReadBlock(&TransmitQueue, &size); if (size > 0) { + transmitStart = HAL_GetTick(); USBD_CDC_SetTxBuffer(&hUSBD_Device_CDC, buffer, size); /* * size never exceed PMA buffer and USBD_CDC_TransmitPacket make full From eea20cec68631344af28c02ecab0432d5c8b9074 Mon Sep 17 00:00:00 2001 From: Venelin Efremov Date: Tue, 12 Mar 2019 20:33:00 -0700 Subject: [PATCH 5/5] Reset transmit timeout on terminal re-connect. --- cores/arduino/USBSerial.cpp | 4 +--- cores/arduino/stm32/usb/cdc/usbd_cdc_if.c | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cores/arduino/USBSerial.cpp b/cores/arduino/USBSerial.cpp index 291f411fd5..256b5a1df8 100644 --- a/cores/arduino/USBSerial.cpp +++ b/cores/arduino/USBSerial.cpp @@ -66,7 +66,7 @@ size_t USBSerial::write(uint8_t ch) size_t USBSerial::write(const uint8_t *buffer, size_t size) { size_t rest = size; - while (rest > 0) { + while (rest > 0 && CDC_connected()) { // Determine buffer size available for write auto portion = (size_t)CDC_TransmitQueue_WriteSize(&TransmitQueue); // Truncate it to content size (if rest is greater) @@ -83,8 +83,6 @@ size_t USBSerial::write(const uint8_t *buffer, size_t size) buffer += portion; // After storing data, start transmitting process CDC_continue_transmit(); - } else if (!CDC_connected()) { - break; } } return size - rest; diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c index 0372ef9170..3e57ed27e5 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c @@ -179,6 +179,9 @@ static int8_t USBD_CDC_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length) case CDC_SET_CONTROL_LINE_STATE: lineState = (((USBD_SetupReqTypedef *)pbuf)->wValue & 0x01) != 0; // Check DTR state + if (lineState) { // Reset the transmit timeout when the port is connected + transmitStart = 0; + } break; case CDC_SEND_BREAK: