UART TX DMA issues
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-19 09:16 AM
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-19 11:47 AM
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...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-19 02:18 PM
Yes, I release the semaphore when this function is called:
UART_EndTransmit_IT()
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-20 12:13 AM
Try to activate the DMA only when the UART TX is ready to proceed (status register of UART) as extra security.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-20 10:13 AM
This is the function I call everytime I want to send data using DMA:
HAL_UART_Transmit_DMA(&huart1, pBuffer, length);
nothing else.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-23 10:02 AM
Hi,
Still not working, I can't figure out what's wrong. That must be a very stupid thing..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-23 11:23 AM
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-23 11:30 AM
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...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-23 02:56 PM
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-11-27 10:22 AM
Thanks a lot. I can't beleive I didn't see this!!!
Sometimes it is good to share code with someonelse