cancel
Showing results for 
Search instead for 
Did you mean: 

Is CDC_Transmit_FS slower than UART with DMA?

SGonz.2
Associate II

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!

1 ACCEPTED SOLUTION

Accepted Solutions
gbm
Lead III

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.

View solution in original post

3 REPLIES 3
gbm
Lead III

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.

SGonz.2
Associate II

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
Lead III

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().