Skip to content

Commit f357a19

Browse files
committed
stmhal: Fix issues with USB CDC init and receive.
Late USB enumeration could clear settings after they had been set. Now fixed by not clearing some settings on init. RX was blocking if received characters were not being processed, so CTRL-C would not be picked up. Now "fixed" by not blocking, but instead discarding incoming characters if they overflow the buffer.
1 parent 9050b2e commit f357a19

1 file changed

Lines changed: 35 additions & 18 deletions

File tree

stmhal/usbd_cdc_interface.c

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646

4747
/* Private typedef -----------------------------------------------------------*/
4848
/* Private define ------------------------------------------------------------*/
49-
#define APP_RX_DATA_SIZE 1024 // I think this must be at least CDC_DATA_FS_OUT_PACKET_SIZE (was 2048)
49+
#define APP_RX_DATA_SIZE 1024 // I think this must be at least CDC_DATA_FS_OUT_PACKET_SIZE=64 (APP_RX_DATA_SIZE was 2048)
5050
#define APP_TX_DATA_SIZE 1024 // I think this can be any value (was 2048)
5151

5252
/* Private macro -------------------------------------------------------------*/
@@ -138,8 +138,13 @@ static int8_t CDC_Itf_Init(void)
138138
UserRxBufCur = 0;
139139
UserRxBufLen = 0;
140140

141+
/* NOTE: we cannot reset these here, because USBD_CDC_SetInterrupt
142+
* may be called before this init function to set these values.
143+
* This can happen if the USB enumeration occurs after the call to
144+
* USBD_CDC_SetInterrupt.
141145
user_interrupt_char = VCP_CHAR_NONE;
142146
user_interrupt_data = NULL;
147+
*/
143148

144149
return (USBD_OK);
145150
}
@@ -252,7 +257,7 @@ void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void) {
252257
{
253258
if(UserTxBufPtrOut > UserTxBufPtrIn) /* rollback */
254259
{
255-
buffsize = APP_RX_DATA_SIZE - UserTxBufPtrOut;
260+
buffsize = APP_TX_DATA_SIZE - UserTxBufPtrOut;
256261
}
257262
else
258263
{
@@ -266,7 +271,7 @@ void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void) {
266271
if(USBD_CDC_TransmitPacket(&hUSBDDevice) == USBD_OK)
267272
{
268273
UserTxBufPtrOut += buffsize;
269-
if (UserTxBufPtrOut == APP_RX_DATA_SIZE)
274+
if (UserTxBufPtrOut == APP_TX_DATA_SIZE)
270275
{
271276
UserTxBufPtrOut = 0;
272277
}
@@ -289,9 +294,20 @@ static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len) {
289294
HAL_UART_Transmit_DMA(&UartHandle, Buf, *Len);
290295
#endif
291296

297+
// TODO improve this function to implement a circular buffer
298+
299+
// if we have processed all the characters, reset the buffer counters
300+
if (UserRxBufCur > 0 && UserRxBufCur >= UserRxBufLen) {
301+
memmove(UserRxBuffer, UserRxBuffer + UserRxBufLen, *Len);
302+
UserRxBufCur = 0;
303+
UserRxBufLen = 0;
304+
}
305+
306+
uint32_t delta_len;
307+
292308
if (user_interrupt_char == VCP_CHAR_NONE) {
293309
// no special interrupt character
294-
UserRxBufLen = *Len;
310+
delta_len = *Len;
295311

296312
} else {
297313
// filter out sepcial interrupt character from the buffer
@@ -310,25 +326,29 @@ static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len) {
310326
}
311327
}
312328

313-
// set length of remaining characters
314-
UserRxBufLen = dest - Buf;
315-
316329
if (char_found) {
317330
// raise exception when interrupts are finished
318331
user_interrupt_char = VCP_CHAR_NONE;
319332
pendsv_nlr_jump(user_interrupt_data);
320333
}
321-
}
322334

323-
// there are new characters at the start of the buffer, so point there
324-
UserRxBufCur = 0;
335+
// length of remaining characters
336+
delta_len = dest - Buf;
337+
}
325338

326-
if (UserRxBufLen == 0) {
327-
// initiate next USB packet transfer now that UserRxBuffer has been drained
328-
USBD_CDC_ReceivePacket(&hUSBDDevice);
339+
if (UserRxBufLen + delta_len + CDC_DATA_FS_MAX_PACKET_SIZE > APP_RX_DATA_SIZE) {
340+
// if we keep this data then the buffer can overflow on the next USB rx
341+
// so we don't increment the length, and throw this data away
342+
} else {
343+
// data fits, leaving room for another CDC_DATA_FS_OUT_PACKET_SIZE
344+
UserRxBufLen += delta_len;
329345
}
330346

331-
return (USBD_OK);
347+
// initiate next USB packet transfer, to append to existing data in buffer
348+
USBD_CDC_SetRxBuffer(&hUSBDDevice, UserRxBuffer + UserRxBufLen);
349+
USBD_CDC_ReceivePacket(&hUSBDDevice);
350+
351+
return USBD_OK;
332352
}
333353

334354
int USBD_CDC_IsConnected(void) {
@@ -366,9 +386,6 @@ int USBD_CDC_RxGet(void) {
366386

367387
// get next character
368388
int c = UserRxBuffer[UserRxBufCur++];
369-
if (UserRxBufCur >= UserRxBufLen) {
370-
// initiate next USB packet transfer now that UserRxBuffer has been drained
371-
USBD_CDC_ReceivePacket(&hUSBDDevice);
372-
}
389+
373390
return c;
374391
}

0 commit comments

Comments
 (0)