1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-19 22:35:23 +03:00

[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.
This commit is contained in:
jflyper 2019-02-11 23:40:43 +09:00
parent a8e9dd94e8
commit 43e1ee025b
2 changed files with 54 additions and 37 deletions

View file

@ -59,11 +59,16 @@
#include "usbd_cdc_interface.h" #include "usbd_cdc_interface.h"
#include "stdbool.h" #include "stdbool.h"
#include "drivers/nvic.h"
#include "build/atomic.h"
/* Private typedef -----------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/
#define APP_RX_DATA_SIZE 2048 #define APP_RX_DATA_SIZE 2048
#define APP_TX_DATA_SIZE 2048 #define APP_TX_DATA_SIZE 2048
#define APP_TX_BLOCK_SIZE 512
/* Private macro -------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/
USBD_CDC_LineCodingTypeDef LineCoding = USBD_CDC_LineCodingTypeDef LineCoding =
@ -74,12 +79,12 @@ USBD_CDC_LineCodingTypeDef LineCoding =
0x08 /* nb. of bits 8*/ 0x08 /* nb. of bits 8*/
}; };
uint8_t UserRxBuffer[APP_RX_DATA_SIZE];/* Received Data over USB are stored in this buffer */ volatile 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 UserTxBuffer[APP_TX_DATA_SIZE];/* Received Data over UART (CDC interface) are stored in this buffer */
uint32_t BuffLength; 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 */ 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 */ start address when data are sent over USB */
uint32_t rxAvailable = 0; uint32_t rxAvailable = 0;
@ -138,8 +143,8 @@ static int8_t CDC_Itf_Init(void)
} }
/*##-5- Set Application Buffers ############################################*/ /*##-5- Set Application Buffers ############################################*/
USBD_CDC_SetTxBuffer(&USBD_Device, UserTxBuffer, 0); USBD_CDC_SetTxBuffer(&USBD_Device, (uint8_t *)UserTxBuffer, 0);
USBD_CDC_SetRxBuffer(&USBD_Device, UserRxBuffer); USBD_CDC_SetRxBuffer(&USBD_Device, (uint8_t *)UserRxBuffer);
ctrlLineStateCb = NULL; ctrlLineStateCb = NULL;
baudRateCb = 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) void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{ {
if (htim->Instance != TIMusb) return; if (htim->Instance != TIMusb) {
return;
}
uint32_t buffptr;
uint32_t buffsize; uint32_t buffsize;
static uint32_t lastBuffsize = 0;
if (UserTxBufPtrOut != UserTxBufPtrIn) USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)USBD_Device.pCDC_ClassData;
{
if (UserTxBufPtrOut > UserTxBufPtrIn) /* Roll-back */
{
buffsize = APP_RX_DATA_SIZE - UserTxBufPtrOut;
}
else
{
buffsize = UserTxBufPtrIn - UserTxBufPtrOut;
}
buffptr = UserTxBufPtrOut; if (hcdc->TxState == 0) {
// endpoint has finished transmitting previous block
USBD_CDC_SetTxBuffer(&USBD_Device, (uint8_t*)&UserTxBuffer[buffptr], buffsize); if (lastBuffsize) {
// move the ring buffer tail based on the previous succesful transmission
if (USBD_CDC_TransmitPacket(&USBD_Device) == USBD_OK) UserTxBufPtrOut += lastBuffsize;
{ if (UserTxBufPtrOut == APP_TX_DATA_SIZE) {
UserTxBufPtrOut += buffsize;
if (UserTxBufPtrOut == APP_TX_DATA_SIZE)
{
UserTxBufPtrOut = 0; 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) (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. 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) uint32_t CDC_Send_DATA(const uint8_t *ptrBuffer, uint32_t sendLength)
{ {
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)USBD_Device.pCDC_ClassData; for (uint32_t i = 0; i < sendLength; i++) {
while (hcdc->TxState != 0);
for (uint32_t i = 0; i < sendLength; i++)
{
UserTxBuffer[UserTxBufPtrIn] = ptrBuffer[i];
UserTxBufPtrIn = (UserTxBufPtrIn + 1) % APP_TX_DATA_SIZE;
while (CDC_Send_FreeBytes() == 0) { while (CDC_Send_FreeBytes() == 0) {
// block until there is free space in the ring buffer
delay(1); delay(1);
} }
ATOMIC_BLOCK(NVIC_BUILD_PRIORITY(6, 0)) { // Paranoia
UserTxBuffer[UserTxBufPtrIn] = ptrBuffer[i];
UserTxBufPtrIn = (UserTxBufPtrIn + 1) % APP_TX_DATA_SIZE;
}
} }
return sendLength; return sendLength;
} }

View file

@ -65,7 +65,7 @@
/* Periodically, the state of the buffer "UserTxBuffer" is checked. /* Periodically, the state of the buffer "UserTxBuffer" is checked.
The period depends on CDC_POLLING_INTERVAL */ 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 ------------------------------------------------------------*/ /* Exported typef ------------------------------------------------------------*/
/* The following structures groups all needed parameters to be configured for the /* The following structures groups all needed parameters to be configured for the