cancel
Showing results for 
Search instead for 
Did you mean: 

Possible error in Cube4 code function HAL_USART_Transmit(...)

Paul Hankins
Associate II
Posted on August 29, 2017 at 00:01

This is the section of code I think needs changed in  HAL_USART_Transmit(...);

if(husart->Init.WordLength == USART_WORDLENGTH_9B)

....

else

{

if(USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)

{

return HAL_TIMEOUT;

}

husart->Instance->DR = (*pTxData++ & (uint8_t)0xFF);

}

It needs to be changed to something like below I think. What can happen is after checking for the TXE flag, but before you write the DR register, an interrupt can happen. If the interrupt is long enough for the shift to complete and cause the TC flag to be set before you return, writing the DR register will not clear the TC flag. This happens because the shift register finished after you read the SR register, but before you wrote the DR register(this sequence is needed to clears the TC flag). This will cause the function to exit (sees the TC flag) before the last data is finished shifting out. In my case I was using the USART in SPI mode and controlling my chip select lines. So leaving early caused be to take the chip select away before the data was finished shifting out.

The only way I could see to fix that was cause one last read of the SR register before the DR write that was protected by an interrupt disable and enable so the two actions are sure to be back to back.

if(husart->Init.WordLength == USART_WORDLENGTH_9B)

.....

else

{

if(USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)

{

return HAL_TIMEOUT;

}

!!! disable of interrupts needed here

(void)__HAL_USART_GET_FLAG(husart, USART_FLAG_TXE);

husart->Instance->DR = (*pTxData++ & (uint8_t)0xFF);

!!! re-enable interrupts needed here

}

2 REPLIES 2
Posted on August 29, 2017 at 13:08

Hello Paul!

I suposed that you use F4 firmware

This mentioned issue concerns only the last byte transmitted from usart because all other bytes transmitted without checking TC flag, but TXE flag.

The checking  for TC flag is mad after While(..) loop  but the clearing is made at every loop of while(..).

So..   another posible solution for this issue (before made some action from MCD team) is to introduce an 'undesirable delay' after function returns by clearing manualy the TC flag and wait with timeout in case the shift register is not empty

Additionaly i  thing that is better to clear this flag manualy just before writing to DR.

Regards

vf

Posted on August 30, 2017 at 17:44

Yes, it is using F4 firmware v1.16.0. And you are right, it only effects the last byte of the transfer. But my code can hit that little window about 3 times a day. I thought about the manual clear, but the user manual did not recommend to manually clear TC except for one instance. Still even if I did manually clear the TC it still seems like I would need to have the interrupt protection around the two steps of manually clear TC flag and writing the DR register. Other wise I could clear TC, get interrupted away, shift register finishes, return from interrupt and write DR, and still see the TC flag already there.