Skip to main content
Visitor II
August 27, 2020
Solved

Hello, I'm having troubles changing the baudrate of my UART2 configuration. It is initially set to 921600 bps and a bit duration is 1.08us = 1/921600bps, which is fine. However, trying to double this value seems impossible.

  • August 27, 2020
  • 5 replies
  • 6225 views

In MX, at first, I changed the sample rate to 8 bits to double the baudrate. The code was successfully generated, compiled and downloaded. The communication still exists, but the baudrate is still the same as before, with a bit duration of 1.08us.

Then, on MX view, I reverted the sample rate back to 16 bits and introduced manually the new baudrate 1843200. The same as before happened, with the baudrate not being updated.

I tried to update directly the values on the MX_USART2_UART_Init function and the same happened, the baudrate is still 921600bps.

As I suspected this could be a rate compatibility problem, I decided to lower the baudrate to 115200bps, both on MX view and directly on the code. Again, the real baudrate remained at 921600 bps.

On my test setup, I have two MCUs STM32H745IIK6 connected together through their UART2 (no flow control and no baudrate auto-detect). One of the MCUs sends a byte constantly over and over and the other receives it and sends it back. Obviously, the changes in baudrate I preformed were on both MCUs.

Attached goes a printscreen from the oscilloscope of a byte sent (0x71), and cursors measuring the bit width.

Any ideas on what is causing this problems?

Thanks in advance,

Machado

    This topic has been closed for replies.
    Best answer by PMach.1

    The problem is solved!

    Trying to figure out in detail, I decided to run the code step-by-step in debug mode. It happens that in this mode I checked the BRR being correctly written (like I wanted). It ended up with the UART running in different baudrates, as ordered. Basically, it works when running step-by-step in debug, but not in normal runtime.

    I decided to run it step-by-step, without stepping into that many functions, so as to not to go too low-level. Gradually, I observed that only stepping over the HAL_UART_Init() function inside MX_USART2_UART_Init() function, resuming the rest of the code to runtime mode would suffice to correctly program the UART into running. I started getting the suspicion that it was some kind of timing issue, that prevented the normal writing into the registers, although some variables were updated with the correct values (like, for example, huart2.Instance.BRR which I was checking, assuming it would correctly write the value on the register, which aparently didn't).

    I came up with the workaround of adding a delay before the function HAL_UART_Init() is brought up. This *****, obviously. Now, anytime I alter the definitions in MX view and generate new code, might have to re-add the delay. My new MX_USART2_UART_Init function is as follows:

    void MX_USART2_UART_Init(void)

    {

     huart2.Instance = USART2;

     huart2.Init.BaudRate = 1843200;

     huart2.Init.WordLength = UART_WORDLENGTH_8B;

     huart2.Init.StopBits = UART_STOPBITS_1;

     huart2.Init.Parity = UART_PARITY_NONE;

     huart2.Init.Mode = UART_MODE_TX_RX;

     huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;

     huart2.Init.OverSampling = UART_OVERSAMPLING_16;

     huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;

     huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;

     huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_RXOVERRUNDISABLE_INIT|UART_ADVFEATURE_DMADISABLEONERROR_INIT;

     huart2.AdvancedInit.OverrunDisable = UART_ADVFEATURE_OVERRUN_DISABLE;

     huart2.AdvancedInit.DMADisableonRxError = UART_ADVFEATURE_DMA_DISABLEONRXERROR;

     HAL_Delay(1);

     if (HAL_UART_Init(&huart2) != HAL_OK)

     {

      Error_Handler();

     }

     if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)

     {

      Error_Handler();

     }

     if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)

     {

      Error_Handler();

     }

     if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)

     {

      Error_Handler();

     }

    }

    Again, I only suspect of a timing issue and do not fully understand why it happens. If anyone knows exactly what the problem might be, or even has a different suspicion, please, feel free to comment.

    Regards

    5 replies

    Super User
    August 27, 2020

    Changing the oversampling from 16 to 8 doesnt affect the baud rate.

    Are you regenerating code after changing the setting?

    You could inspect the BRR register to see what it gets. Note that there is a limit to max baud rate depending on the peripheral clock speed.

    PMach.1Author
    Visitor II
    August 27, 2020

    Hello and thank you for your quick response,

    According to the Reference Manual, at least from what I understood, a oversampling of 8 doubles the baudrate (check pg. 2212, section 51.5.7: https://www.st.com/resource/en/reference_manual/dm00176879-stm32h745755-and-stm32h747757-advanced-armbased-32bit-mcus-stmicroelectronics.pdf)

    I am not forgetting to regenerate the code. I double check on the MX Init function and the baud rate changes, effectivelly. Right now:

    huart2.Init.BaudRate = 1843200;

    (...)

    huart2.Init.OverSampling = UART_OVERSAMPLING_16;

    I went checking the BRR register, did the computations and the value there is correct. I have a 100MHz clock feeding the BR generator with a prescaler of one, thus, 100000000/1843200 = 54.25.

    The BRR register is specifically 54, which seems correct.

    Super User
    August 28, 2020

    I could have been more precise.

    Changing the oversampling from 8 to 16 in CubeMX and then regenerating code won't change the rate, because the initialization code takes care of that for you. It's different if you're just flipping the OVER8 bit manually.

    It doesn't really make sense that the rate would be fixed at 921600 regardless of what you're trying to set it to. I suspect something else may be going on here.

    Super User
    August 27, 2020

    And the real baudrate with BRR set to 54 is how much?

    JW

    PMach.1Author
    Visitor II
    August 28, 2020

    It should be 1843200. It is still 921600

    Super User
    August 28, 2020

    Do you read out the UART registers *after* transmission which measured 921600, and BRR is 45?

    Do you read out the same UART which is used for the transmission?

    JW

    PMach.1Author
    Visitor II
    August 28, 2020

    Hi, waclawek.jan,

    I didn´t understand your question. Anyway, I kind of found the issue, though I could not understand exactly what happens, but for mere suspicions. I'll describe it in detail below.

    PMach.1AuthorAnswer
    Visitor II
    August 28, 2020

    The problem is solved!

    Trying to figure out in detail, I decided to run the code step-by-step in debug mode. It happens that in this mode I checked the BRR being correctly written (like I wanted). It ended up with the UART running in different baudrates, as ordered. Basically, it works when running step-by-step in debug, but not in normal runtime.

    I decided to run it step-by-step, without stepping into that many functions, so as to not to go too low-level. Gradually, I observed that only stepping over the HAL_UART_Init() function inside MX_USART2_UART_Init() function, resuming the rest of the code to runtime mode would suffice to correctly program the UART into running. I started getting the suspicion that it was some kind of timing issue, that prevented the normal writing into the registers, although some variables were updated with the correct values (like, for example, huart2.Instance.BRR which I was checking, assuming it would correctly write the value on the register, which aparently didn't).

    I came up with the workaround of adding a delay before the function HAL_UART_Init() is brought up. This *****, obviously. Now, anytime I alter the definitions in MX view and generate new code, might have to re-add the delay. My new MX_USART2_UART_Init function is as follows:

    void MX_USART2_UART_Init(void)

    {

     huart2.Instance = USART2;

     huart2.Init.BaudRate = 1843200;

     huart2.Init.WordLength = UART_WORDLENGTH_8B;

     huart2.Init.StopBits = UART_STOPBITS_1;

     huart2.Init.Parity = UART_PARITY_NONE;

     huart2.Init.Mode = UART_MODE_TX_RX;

     huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;

     huart2.Init.OverSampling = UART_OVERSAMPLING_16;

     huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;

     huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;

     huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_RXOVERRUNDISABLE_INIT|UART_ADVFEATURE_DMADISABLEONERROR_INIT;

     huart2.AdvancedInit.OverrunDisable = UART_ADVFEATURE_OVERRUN_DISABLE;

     huart2.AdvancedInit.DMADisableonRxError = UART_ADVFEATURE_DMA_DISABLEONRXERROR;

     HAL_Delay(1);

     if (HAL_UART_Init(&huart2) != HAL_OK)

     {

      Error_Handler();

     }

     if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)

     {

      Error_Handler();

     }

     if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)

     {

      Error_Handler();

     }

     if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)

     {

      Error_Handler();

     }

    }

    Again, I only suspect of a timing issue and do not fully understand why it happens. If anyone knows exactly what the problem might be, or even has a different suspicion, please, feel free to comment.

    Regards

    Visitor II
    December 20, 2024

    Just had the same problem. In auto-generated code, the init of UART2 and UART4 are directly after each other. Moving some other init (timer in my case) helped to solve the error.

    Super User
    December 22, 2024

    Very strange.

    IIRC change in some U(S)ART parameters is possible only while it is disabled: bit USART_CR1_UE is 0.

    But HAL_UART_Init() should take care of this.

    Super User
    August 28, 2020

    Not sure I buy that explanation. You're claiming that if you remove the "HAL_Delay(1);" line, the baud rate becomes 921600?

    PMach.1Author
    Visitor II
    August 28, 2020

    No. I may have not been clear.

    If I remove the HAL_Delay(1), I am not able to change any configuration to the UART from then on. As you seen in the latest code, the baudrate is 1843200 (and that's what I measure in my signal). By removing the delay, any alteration to the UART configuration will not be reflected in the signall. If I set the baudrate do 155200, for example, I will still measure a 1843200 bps baudrate on my signal. The same applies to the number of bits of the word length. If I set to 9 bits, it still sends only 8 bits. All of this because I removed the delay.

    The HAL_Delay(1) allows the alterations of the configuration to take place and the signal that is measured. Without the delay, I can't change the signal properties.

    My initial concern for the 921600 bps baudrate was because it was initially set to this throughput. I just couldn't change it this time. This is for a really big project that has been going on for several months. Many, many lines of code have been written since the initial configuration of the UART. I don't really know why I couldn't change this time, maybe some race condition, who knows?

    Super User
    August 28, 2020
    Oh, so you’re calling HAL_UART_Init multiple times. I didnt get that by reading the question.