cancel
Showing results for 
Search instead for 
Did you mean: 

Unintentional splitting of messages sent via UART using DMA

grados73
Associate II

Hi, I'm having a problem with unintentionally splitting a message I'm trying to send over the UART using DMA . I am using one function to send the message:

const uint32_t max_value_of_counter_loop = 100; /* in case systick jams */
volatile bool was_u1_tx_cplt = true;
HAL_StatusTypeDef OwnTransmitDma(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)
{
/* Wait on uart to be ready, but no more than 3ms */
uint32_t start_of_try_to_send = HAL_GetTick();
uint32_t counter_while_loop = 0; /* in case systick jams */
while((huart1.gState != HAL_UART_STATE_READY) && (!was_u1_tx_cplt))
{
counter_while_loop++;
uint32_t now_get_tick = HAL_GetTick();
if(now_get_tick > (start_of_try_to_send+2)) break; /* wait no more than 3ms */
if(counter_while_loop > max_value_of_counter_loop) break; /* in case systick jams */
}
was_u1_tx_cplt = false;
return HAL_UART_Transmit_DMA(huart, pData, Size);
}

I call it like this:

uint8_t SendInfoAboutNumberOfStepsMadeByHighPrecisionMotors(uint8_t number_of_axis)
{
int number_of_steps = 0;
uint8_t axis = number_of_axis;

MG_GetNumberOfSteps(axis, &number_of_steps);

Length = sprintf((char*)Message4, "MG%d=%d\n", axis, number_of_steps);
send_status = OwnTransmitDma(&huart1, Message4, Length);

if(send_status != HAL_OK) return RESPONSE_TRY_ERROR;
else return RESPONSE_TRY_OK;
}

 

I set the was_u1_tx_cplt variable in a callback:
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart == &huart1) was_u1_tx_cplt = true;
}


Message4 is a global array located in this file:
uint8_t Message4[16];

Not every message is split, moreover 99% of messages are sent without any problems, but sometimes messages are split into two parts and I don't see the dependency when this happens. I don't use RTOS.
I'm using this DMA only for this UART, but also for TX and RX, at first I thought the RX stream was interrupting the TX stream, but I set the TX stream priority to DMA_PRIORITY_MEDIUM where RX has DMA_PRIORITY_LOW and that didn't help.

UART and DMA configuration:

grados73_0-1695638586953.png

grados73_1-1695638653997.png

Examples of splitting messages:

grados73_2-1695638696291.png

 
 

grados73_5-1695638747552.png

Unfortunately, I have no idea what can cause the fact that the significant majority of messages are sent correctly, but some are sent incorrectly. If you have any ideas, please help me with this issue.
STM32F407VGTx,
STM32CubeIDE Version: 1.13.1

 

 
1 ACCEPTED SOLUTION

Accepted Solutions
MS.9
Associate III

But when you wait for HAL_UART_TxCpltCallback , Message4 already has been loaded with the new message.

The DMA will be merrily transmitting the 'old' contents of Message4 and your code overwrites it part way through then waits for DMA to compelte. Sometimes the DMA will be part way through transmitting it, sometimes not.

View solution in original post

11 REPLIES 11
MS.9
Associate III

looks like you calling sprintf( Message4 ...) while Message4 is still being sent out by DMA.

suggest you wait for DMA to complete before loading the next msg into Message4 

grados73
Associate II

Waiting for HAL_UART_TxCpltCallback doesn't get the job done? Which interrupt should I wait for?

ONadr.1
Senior III

Try to mark this Message array as volatile.

Anad variable was_u1_tx_cplt too.

MS.9
Associate III

But when you wait for HAL_UART_TxCpltCallback , Message4 already has been loaded with the new message.

The DMA will be merrily transmitting the 'old' contents of Message4 and your code overwrites it part way through then waits for DMA to compelte. Sometimes the DMA will be part way through transmitting it, sometimes not.

ONadr.1
I will try.

MS.9
Oki, so I understand that I should wait for the HAL_UART_TxCpltCallback not only before sending, but also before the sprintf() function?

You should check the was_u1_tx_cplt flag before sprintf and set it to false after sprintf and then start Tx with DMA. When the Tx is complete, the flag is set again in the callback.

Is it actually splitting it? Or is this how your receiver times out, buffers, or granularity/resolution there.

Check signals on a scope or logic analyzer.

Expect to have to reconstruct data, and resync, on the host. If there are no additional characters inserted, I'd look at other expectations and synchronization

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..