Skip to main content
SGonz.2
Associate III
June 5, 2022
Solved

Is CDC_Transmit_FS slower than UART with DMA?

Hello! I'm using a STM32F407VET6 and receiving data through UART with DMA to send it back by the USB using CDC_Transmit_FS.

I tested the UART echoing RX and TX, it worked and showed the data like "@HEAD=TEST1,AAAA,BBBB,CCCC..." which is OK, but now when I send it by USB I only receive "@HEA@HEA@HEA"

This is the function where I call the CDC_Transmit_FS

void UserDataTreatment(UART_HandleTypeDef *huart, uint8_t* pData, uint16_t Size){
 /*
 * This function might be called in any of the following interrupt contexts :
 * - DMA TC and HT events
 * - UART IDLE line event
 *
 * pData and Size defines the buffer where received data have been copied, in order to be processed.
 * During this processing of already received data, reception is still ongoing.
 *
 */
 uint8_t* pBuff = pData;
 uint8_t i;
 
 /* Implementation of loopback is on purpose implemented in direct register access,
 in order to be able to echo received characters as fast as they are received.
 Wait for TC flag to be raised at end of transmit is then removed, only TXE is checked */
 for (i = 0; i < Size; i++){
 //while (!(__HAL_UART_GET_FLAG(huart, UART_FLAG_TXE))) {}
 //huart->Instance->DR = *pBuff;
	//uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);
 CDC_Transmit_FS(pBuff, sizeof(pBuff));
 pBuff++;
 }
 
}

Thank you!

This topic has been closed for replies.
gbm
gbmBest answer
Super User
June 5, 2022

pBuff is a pointer, so sizeof(pBuff) is 4. You get what you ask for, but it's just the first of many problems with your code. Don't call Transmit for single byte - get the data to a bigger buffer and send the whole buffer at once. You must call Transmit from the interrupt of the same priority as USB interrupt. Typically single Transmit call takes approx 1 ms, same for 1..64 bytes; add another ms per every 64 bytes transferred. The subsequent calls to Transmit will fail with the proper error code until the whole buffer is transferred.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

3 replies

gbm
gbmBest answer
Super User
June 5, 2022

pBuff is a pointer, so sizeof(pBuff) is 4. You get what you ask for, but it's just the first of many problems with your code. Don't call Transmit for single byte - get the data to a bigger buffer and send the whole buffer at once. You must call Transmit from the interrupt of the same priority as USB interrupt. Typically single Transmit call takes approx 1 ms, same for 1..64 bytes; add another ms per every 64 bytes transferred. The subsequent calls to Transmit will fail with the proper error code until the whole buffer is transferred.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
SGonz.2
SGonz.2Author
Associate III
June 5, 2022

Thank you for your answer! I changed the pBuff and now send a data package by USB, now my code looks like this and works

void UserDataTreatment(UART_HandleTypeDef *huart, uint8_t* pData, uint16_t Size){
 uint8_t* pBuff = pData;
 uint8_t i;
 uint8_t DataArray[100];
 
 for (i = 0; i < Size; i++){
 DataArray[i] = *pBuff;
 pBuff++;
 }
 CDC_Transmit_FS(DataArray, Size);
}

And thank you for the 64 bytes advice, I haven't implemented it yet, but I will send more data and that will be really usefull

Have a nice day!

gbm
Super User
June 6, 2022

This code will not work. You could simply call Transmit passing it the pData. Transmit call is asynchronous, so the buffer used by Transmit must be present for the whole time of transfer, at least if the size of data exceeds the endpoint size. Array on the stack will disappear when you return from UserDataTreatment().

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice