From 43e1ee025bc464d9a95eb5d88e5b6675ef294ad8 Mon Sep 17 00:00:00 2001 From: jflyper Date: Mon, 11 Feb 2019 23:40:43 +0900 Subject: [PATCH] [H7] Apply HAL VCP TX fix Apply changes equivalent to F7's fix: VCP HAL transmit buffer fixes #7563 Further refactoring based on ledvinap's comments on #7563 is advised. --- src/main/vcph7/usbd_cdc_interface.c | 89 +++++++++++++++++------------ src/main/vcph7/usbd_cdc_interface.h | 2 +- 2 files changed, 54 insertions(+), 37 deletions(-) diff --git a/src/main/vcph7/usbd_cdc_interface.c b/src/main/vcph7/usbd_cdc_interface.c index 78af349042..e641a8bb16 100644 --- a/src/main/vcph7/usbd_cdc_interface.c +++ b/src/main/vcph7/usbd_cdc_interface.c @@ -59,11 +59,16 @@ #include "usbd_cdc_interface.h" #include "stdbool.h" +#include "drivers/nvic.h" +#include "build/atomic.h" + /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ #define APP_RX_DATA_SIZE 2048 #define APP_TX_DATA_SIZE 2048 +#define APP_TX_BLOCK_SIZE 512 + /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ USBD_CDC_LineCodingTypeDef LineCoding = @@ -74,12 +79,12 @@ USBD_CDC_LineCodingTypeDef LineCoding = 0x08 /* nb. of bits 8*/ }; -uint8_t UserRxBuffer[APP_RX_DATA_SIZE];/* Received Data over USB are stored in this buffer */ -uint8_t UserTxBuffer[APP_TX_DATA_SIZE];/* Received Data over UART (CDC interface) are stored in this buffer */ +volatile uint8_t UserRxBuffer[APP_RX_DATA_SIZE];/* Received Data over USB are stored in this buffer */ +volatile uint8_t UserTxBuffer[APP_TX_DATA_SIZE];/* Received Data over UART (CDC interface) are stored in this buffer */ uint32_t BuffLength; -uint32_t UserTxBufPtrIn = 0;/* Increment this pointer or roll it back to +volatile uint32_t UserTxBufPtrIn = 0;/* Increment this pointer or roll it back to start address when data are received over USART */ -uint32_t UserTxBufPtrOut = 0; /* Increment this pointer or roll it back to +volatile uint32_t UserTxBufPtrOut = 0; /* Increment this pointer or roll it back to start address when data are sent over USB */ uint32_t rxAvailable = 0; @@ -138,8 +143,8 @@ static int8_t CDC_Itf_Init(void) } /*##-5- Set Application Buffers ############################################*/ - USBD_CDC_SetTxBuffer(&USBD_Device, UserTxBuffer, 0); - USBD_CDC_SetRxBuffer(&USBD_Device, UserRxBuffer); + USBD_CDC_SetTxBuffer(&USBD_Device, (uint8_t *)UserTxBuffer, 0); + USBD_CDC_SetRxBuffer(&USBD_Device, (uint8_t *)UserRxBuffer); ctrlLineStateCb = NULL; baudRateCb = NULL; @@ -244,35 +249,42 @@ static int8_t CDC_Itf_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length) */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { - if (htim->Instance != TIMusb) return; + if (htim->Instance != TIMusb) { + return; + } - uint32_t buffptr; uint32_t buffsize; + static uint32_t lastBuffsize = 0; - if (UserTxBufPtrOut != UserTxBufPtrIn) - { - if (UserTxBufPtrOut > UserTxBufPtrIn) /* Roll-back */ - { - buffsize = APP_RX_DATA_SIZE - UserTxBufPtrOut; - } - else - { - buffsize = UserTxBufPtrIn - UserTxBufPtrOut; - } + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)USBD_Device.pCDC_ClassData; - buffptr = UserTxBufPtrOut; - - USBD_CDC_SetTxBuffer(&USBD_Device, (uint8_t*)&UserTxBuffer[buffptr], buffsize); - - if (USBD_CDC_TransmitPacket(&USBD_Device) == USBD_OK) - { - UserTxBufPtrOut += buffsize; - if (UserTxBufPtrOut == APP_TX_DATA_SIZE) - { + if (hcdc->TxState == 0) { + // endpoint has finished transmitting previous block + if (lastBuffsize) { + // move the ring buffer tail based on the previous succesful transmission + UserTxBufPtrOut += lastBuffsize; + if (UserTxBufPtrOut == APP_TX_DATA_SIZE) { UserTxBufPtrOut = 0; } + lastBuffsize = 0; } - } + if (UserTxBufPtrOut != UserTxBufPtrIn) { + if (UserTxBufPtrOut > UserTxBufPtrIn) { /* Roll-back */ + buffsize = APP_TX_DATA_SIZE - UserTxBufPtrOut; + } else { + buffsize = UserTxBufPtrIn - UserTxBufPtrOut; + } + if (buffsize > APP_TX_BLOCK_SIZE) { + buffsize = APP_TX_BLOCK_SIZE; + } + + USBD_CDC_SetTxBuffer(&USBD_Device, (uint8_t*)&UserTxBuffer[UserTxBufPtrOut], buffsize); + + if (USBD_CDC_TransmitPacket(&USBD_Device) == USBD_OK) { + lastBuffsize = buffsize; + } + } + } } /** @@ -369,7 +381,13 @@ uint32_t CDC_Send_FreeBytes(void) (APP_Rx_ptr_out > APP_Rx_ptr_in ? APP_Rx_ptr_out - APP_Rx_ptr_in : APP_RX_DATA_SIZE - APP_Rx_ptr_in + APP_Rx_ptr_in) but without the impact of the condition check. */ - return ((UserTxBufPtrOut - UserTxBufPtrIn) + (-((int)(UserTxBufPtrOut <= UserTxBufPtrIn)) & APP_TX_DATA_SIZE)) - 1; + uint32_t freeBytes; + + ATOMIC_BLOCK(NVIC_BUILD_PRIORITY(6, 0)) { + freeBytes = ((UserTxBufPtrOut - UserTxBufPtrIn) + (-((int)(UserTxBufPtrOut <= UserTxBufPtrIn)) & APP_TX_DATA_SIZE)) - 1; + } + + return freeBytes; } /** @@ -382,16 +400,15 @@ uint32_t CDC_Send_FreeBytes(void) */ uint32_t CDC_Send_DATA(const uint8_t *ptrBuffer, uint32_t sendLength) { - USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)USBD_Device.pCDC_ClassData; - while (hcdc->TxState != 0); - - for (uint32_t i = 0; i < sendLength; i++) - { - UserTxBuffer[UserTxBufPtrIn] = ptrBuffer[i]; - UserTxBufPtrIn = (UserTxBufPtrIn + 1) % APP_TX_DATA_SIZE; + for (uint32_t i = 0; i < sendLength; i++) { while (CDC_Send_FreeBytes() == 0) { + // block until there is free space in the ring buffer delay(1); } + ATOMIC_BLOCK(NVIC_BUILD_PRIORITY(6, 0)) { // Paranoia + UserTxBuffer[UserTxBufPtrIn] = ptrBuffer[i]; + UserTxBufPtrIn = (UserTxBufPtrIn + 1) % APP_TX_DATA_SIZE; + } } return sendLength; } diff --git a/src/main/vcph7/usbd_cdc_interface.h b/src/main/vcph7/usbd_cdc_interface.h index d56191ef07..a9d592981f 100644 --- a/src/main/vcph7/usbd_cdc_interface.h +++ b/src/main/vcph7/usbd_cdc_interface.h @@ -65,7 +65,7 @@ /* Periodically, the state of the buffer "UserTxBuffer" is checked. The period depends on CDC_POLLING_INTERVAL */ -#define CDC_POLLING_INTERVAL 10 /* in ms. The max is 65 and the min is 1 */ +#define CDC_POLLING_INTERVAL 5 /* in ms. The max is 65 and the min is 1 */ /* Exported typef ------------------------------------------------------------*/ /* The following structures groups all needed parameters to be configured for the