Skip to main content
Visitor
September 3, 2026
Question

Unable to dynamically change baudrate on STM32F405

  • September 3, 2026
  • 7 replies
  • 42 views

I am using STM32CubeIde, No RTOS, USART1, RX DMA (Circular), TX DMA in normal mode with DMA_IT_HT disabled.

I’ve got main loop periodically outputting a simple message on the USART. System appears to hang when commanded to change baud. 

I’ve tried perhaps dozens of variations that have been recommended by “STM32 Sidekick” and Google AI.  Most work with the debugger connected.  None work without the debugger which is making this difficult to troubleshoot.  Sidekick example shown below. 

			// 1. Wait for any ongoing transmissions to finish safely
// This prevents splitting a character mid-air.
while (__HAL_UART_GET_FLAG(huart, UART_FLAG_TC) == RESET)
{
// Optional: Implement a timeout mechanism here
}

// 2. Temporarily de-initialize the UART peripheral
// This turns off the UART but keeps your GPIO and DMA settings intact.
if (HAL_UART_DeInit(huart) != HAL_OK)
{
return; //HAL_ERROR;
}

// 3. Update the baud rate in the configuration structure
huart->Init.BaudRate = new_baudrate;

// 4. Re-initialize the peripheral with the new configuration
// HAL automatically calculates the correct BRR value using PCLK1/PCLK2 internal maps.
if (HAL_UART_Init(huart) != HAL_OK)
{
return; // HAL_ERROR;
}

// apparently not necessary: SET_BIT(huart->Instance->CR1, (USART_CR1_TE | USART_CR1_RE));

// Restart DMA reception (using Receive-to-Idle for variable length message)
HAL_UARTEx_ReceiveToIdle_DMA(saUartControl[id].pHuart,
saUartControl[id].rx_dma_buffer,
sizeof(saUartControl[id].rx_dma_buffer));

return; // HAL_OK;

 

 

7 replies

Bob S
Super User
September 3, 2026

SideKick is incorrect.  Calling HAL_UART_DeInit() will indeed also de-initialize the DMA and GPIO settings.  Also, when using the HAL UART functions, checking the TC bit does not necessarily mean that the HAL layer is done.  Use the TX complete callback for this.

We need more information.  When running with the debugger, do you have any breakpoints set or single stepping? Or do you just load the program and run?  Find some way to indicate what you code is doing without the debugger connected.  Maybe add some GPIO pins that you can toggle.

Not that the program starts differently when running from the debugger.  When debugging (presumably from CubeIDE), the debugger bypasses the startup vector/stack pointer in the interrupt vector table and forces the PC/SP to the initial values in the ELF file.  The debugger also bypasses the built-in bootloader.

Visitor
September 3, 2026

Hi Bob,

Thanks for the quick reply and your insights

No breakpoints are set.  I just load and run.  I issue my command from this point and it works.  Cycle power, issue command again and it ‘hangs’.

I just changed my code to wait for HAL_UART_TxCpltCallback() which sets a ‘done’ flag for me.  Issue remains.

Adding GPIO is not possible because of the custom board I’m using.  Starting to think that I need to buy an eval board to troubleshoot this one.

Bob S
Super User
September 3, 2026

>  No breakpoints are set.  I just load and run.  I issue my command from this point and it works.  Cycle power, issue command again and it ‘hangs’.

Well there you go - look at power-on reset events.  Double-check power pins and NRST circuit.  Look at the power rails (including VDDA) when NRST goes high and see if they sag.  As I mentioned earlier, the startup sequence is different with the debugger.  There MAY also be some register that the debugger is touching that your code doesn’t correctly configure.

>  Adding GPIO is not possible because of the custom board I’m using.

If all your GPIO are used (or unused ones are inaccessible), can you temporarily re-purpose existing signals?

> Starting to think that I need to buy an eval board to troubleshoot this one.

The Nucleo boards are pretty inexpensive

[EDIT] And you never answered if the “boot loader” was your own custom one (I suspect yes) or the built-in bootloader.

[EDIT #2] And if your custom bootloader, are you going through your bootloader when using the debugger?  Or just starting with your main app?

Visitor
September 3, 2026

A useful approach would be to avoid HAL_UART_DeInit() while DMA is active, since it also affects the DMA/GPIO configuration. I’d stop the RX DMA, wait for the HAL TX-complete callback, update the baud rate, then restart RX DMA. Toggling a GPIO at each step could also show exactly where the standalone run hangs.🏢

Visitor
September 3, 2026

HI Jasoncarter32,

Thanks for the response.

HAL_UART_AbortReceive(huart) was recommended by AI for use when using ReceiveToIdle_DMA.  I added it before the HAL TX-complete as you suggested.  Didn’t help.  I then tried HAL_UART_DMAStop(huart) with the same results.

Adding GPIO is not possible because of the custom board I’m using.  Starting to think that I need to buy an eval board to troubleshoot this one.

MM..1
Super User
September 4, 2026

Try dont complicate simple thinks. Use one line LL func to change speed on right place.