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
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...
2017-11-19 02:18 PM
Yes, I release the semaphore when this function is called:
UART_EndTransmit_IT()
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.
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.
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..
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
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...
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.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