AnsweredAssumed Answered

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

Question asked by Paul Hankins on Aug 29, 2017
Latest reply on Aug 30, 2017 by Paul Hankins

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

}

Outcomes