cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U575 UART issue when switching from MSI->HSE at same sysclock and peripheral clocks

mrjohnlloyd
Visitor

Found a bit of an odd issue when switching from MSI (with a 160Mhz sysclock) to HSE (also with a 160Mhz sysclock).

We're using the HAL_UART and its giving a error callback with a zero value uart->ErrorCode.

The cause of it seems to be in the library HAL HAL_UART_IRQHandler()

 
        if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))  

        {

#if !defined(USART_DMAREQUESTS_SW_WA)

          /* Disable the UART DMA Rx request if enabled */

          ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);

 

#endif /* !USART_DMAREQUESTS_SW_WA */

          /* Abort the UART DMA Rx channel */

          if (huart->hdmarx != NULL)

          {

            /* Set the UART DMA Abort callback :

               will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */

            huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError;

 

            /* Abort DMA RX */

            if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)

            {

              /* Call Directly huart->hdmarx->XferAbortCallback function in case of error */

              huart->hdmarx->XferAbortCallback(huart->hdmarx);

            }

          }

          else

          {

            /* Call user error callback */

#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)

            /*Call registered error callback*/

            last_call = 1;

            huart->ErrorCallback(huart); //<- this is the error callback we see

(1) we are not using DMA so is correctly huart->hdmarx, but also we should not see USART_CR3_DMAR set
(2) when running on the MSI 160Mhz with the same peripheral clocks and baudates we do not the same issue, it only appear once we switch to HSE 160Mhz

That is - the identical code with only the sysclock source changed seems to behave in a different fashion. 

We've sidestepped the issue by ignoring any errorcallback with a zero uart->ErrorCode, but that does not explain why it is happening.

Posting here in case anybody has any ideas, it is always nice to know why things happen.

1 ACCEPTED SOLUTION

Accepted Solutions
mrjohnlloyd
Visitor

I know what is going on, but I don't know why it is more prevalent with HSE. The 10ppm vs 1% accuracy of the two clocks is likely part of it.

The USART is picking up a NE on the protocol from the other device.

    if (huart->ErrorCode != HAL_UART_ERROR_NONE)
    {
      /* UART in mode Receiver --------------------------------------------------*/
      if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U)
          && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U)
              || ((cr3its & USART_CR3_RXFTIE) != 0U)))
      {
        if (huart->RxISR != NULL)
        {
          huart->RxISR(huart);
        }
      }


This error is cleared in UART_RxISR_8BIT via huart->RxISR(huartleading to a non-blocking error, and 

USART_CR3_DMAR was not being set after all. 

In the snippet above I mistakenly highlighted the wrong huart->ErrorCallback(huart); it looks like it was the one 8 lines further down, and I've been chasing the wrong call.

I'll mark this as solved. Thanks.

View solution in original post

3 REPLIES 3
TDK
Guru

Set up a hardware watchpoint on the CR3 register to find out what is changing it.

Create an expression for it then right click -> add watchpoint.

If you feel a post has answered your question, please click "Accept as Solution".

Normally I'd agree, and I'd have already done it.

But we are using JTAG/JLINK and debugging via the Marus cortex Visual Code plugin - assuming I can get the early version of cortex live watch I have to accept the memory location (not so far) I would be limited to polling it via JTAG at very significant chunks of a second or more. So yes - I might catch it, but I would not have the capability to backtrace far enough to learn what is going on

Its not ideal!

mrjohnlloyd
Visitor

I know what is going on, but I don't know why it is more prevalent with HSE. The 10ppm vs 1% accuracy of the two clocks is likely part of it.

The USART is picking up a NE on the protocol from the other device.

    if (huart->ErrorCode != HAL_UART_ERROR_NONE)
    {
      /* UART in mode Receiver --------------------------------------------------*/
      if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U)
          && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U)
              || ((cr3its & USART_CR3_RXFTIE) != 0U)))
      {
        if (huart->RxISR != NULL)
        {
          huart->RxISR(huart);
        }
      }


This error is cleared in UART_RxISR_8BIT via huart->RxISR(huartleading to a non-blocking error, and 

USART_CR3_DMAR was not being set after all. 

In the snippet above I mistakenly highlighted the wrong huart->ErrorCallback(huart); it looks like it was the one 8 lines further down, and I've been chasing the wrong call.

I'll mark this as solved. Thanks.