cancel
Showing results for 
Search instead for 
Did you mean: 

UART TX DMA issues

aa bb
Associate II
Posted on November 19, 2017 at 18:16

Hi,

I am trying to set up a uart TX using DMA to send data (mostly strings).

I am using FREERTOS. The semaphore is taken when I want to send the data and released when the UART_EndTransmit_IT() function is called.

The issue is that I have to add delay between data sent (~10ms).otherwise the strings sent are not complete. 

I don't understand why this is necessary..

I ma using: HAL_UART_Transmit_DMA() to send data.

Anyone witht the same problem?

Cheers,

A

9 REPLIES 9
S.Ma
Principal
Posted on November 19, 2017 at 20:47

Do you wait for the DMA transfer completion before the next string is pushed in?

A FIFO behaviour is what seems best for UART Tx, or a DMA block FIFO...

aa bb
Associate II
Posted on November 19, 2017 at 22:18

Yes, I release the semaphore when this function is called: 

UART_EndTransmit_IT()

Posted on November 20, 2017 at 08:13

Try to activate the DMA only when the UART TX is ready to proceed (status register of UART) as extra security.

aa bb
Associate II
Posted on November 20, 2017 at 18:13

This is the function I call everytime I want to send data using DMA:

HAL_UART_Transmit_DMA(&huart1, pBuffer, length);

nothing else. 

aa bb
Associate II
Posted on November 23, 2017 at 19:02

Hi, 

Still not working, I can't figure out what's wrong. That must be a very stupid thing..

Posted on November 23, 2017 at 19:23

Crystal ball hazy here.

The semaphore is taken when I want to send the data and released when the UART_EndTransmit_IT() function is called.

What semaphore? Is it some code of yours inserted into Cube sources, into UART_EndTransmi_IT() function? If not, what do you exactly mean by it? What exactly is the consequence of 'semaphore taken' and 'released'?

The issue is that I have to add delay between data sent (~10ms).otherwise the strings sent are not complete. 

Where did you add the delay exactly? How exactly are the strings not complete?

JW

Posted on November 23, 2017 at 19:30

Okay, here it is my sending function:

void Console_PrintFmt(const char *fmt, ...)

{

    if (fmt == NULL)

    return;

if (xSemaphoreTake(consolePrint_mutex, osWaitForever) == pdTRUE)

{

    int n;

    int size = CONSOLE__MAX_BUFFER_LENGTH - 1;

    char pBuffer[size+1];

    va_list va;

    TimerMsType timeNow = TimerMs_GetTimeMs();

    memset(pBuffer, 0, size+1);

    n = snprintf(pBuffer, size, '[%d.%03d]:', (int)timeNow / 1000, (int)timeNow % 1000);

    va_start(va,fmt);

    n += vsnprintf(pBuffer + n, size - n, fmt, va);

    va_end(va);

    if ((0 < n) && (n < size))

   {

        HAL_UART_Transmit_DMA(&huart1, (uint8_t* )pBuffer, n);

       osDelay(20);

    }

    else

    {

         xSemaphoreGive(consolePrint_mutex);

    }

  }

}

Mu mutex is released when HAL_UART_TxCpltCallback() is called. 

void HAL_UART_TxCpltCallback(UART_HandleTypeDef * huart)

{

    portBASE_TYPE higherPriorityWoken = pdFALSE;

    xSemaphoreGiveFromISR(consolePrint_mutex, NULL);

    if (higherPriorityWoken)

    {

         portYIELD_FROM_ISR(higherPriorityWoken);

     }

}

I have do add the delay just after calling 

HAL_UART_Transmit_DMA()...

Sorry but the <p> code </p> doesn't work...

Posted on November 23, 2017 at 22:56

You appear to be transmitting a buffer which lives on the stack. I don't use HAL but this is probably bad. Your delay presumably gives the hardware time to shift the data before it goes out of scope. With no delay, I would expect this code to send n bytes of which the last m (<= n) are garbage. What happens if you make pBuffer static and remove the delay?

I think you'd be better off creating a data structure to hold a number of pending DMA transfers. You only need a critical section while you add (in the write function) or remove (in the ISR) transfers. The transfer complete interrupt would start the next transfer as each one is completed. Or something a bit like you have - poll the transfer complete flag instead of using a delay - don't see much point in having DMA in this case.

Locking a mutex in one function and releasing it sometime maybe never later in a callback function... I don't recommend it.
Posted on November 27, 2017 at 18:22

Thanks a lot. I can't beleive I didn't see this!!!

Sometimes it is good to share code with someonelse