cancel
Showing results for 
Search instead for 
Did you mean: 

Why are my uarts not working after rcc clock configuration?

NGros
Associate III

Hi all,

I got a strange issue. I'd like to use USART3 or UART5 on my STM32F446 chip. We have the chip on a pcb, so I am not talking about the nucleo board.

The issue is when I do the system_clock_config(), the listed uarts does not work.

void init()
{
    // Loop forever on error such that the error can be diagnosed with a debugger.
    auto loop_forever = []() { while (true) {} };
 
    if (HAL_Init() != HAL_OK) { loop_forever(); }
    if (system_clock_config() != HAL_OK) { loop_forever(); }
    gpio_config();
}

auto system_clock_config()
{
    RCC_ClkInitTypeDef rcc_clk_init {};
    RCC_OscInitTypeDef rcc_osc_init {};
 
    /* Enable Power Control clock */
    __HAL_RCC_PWR_CLK_ENABLE();
 
    /* Max frequency of the chip is 168MHz (voltage scale 1, normal mode)
     * or 180Mhz (voltage scale 1, overdrive mode)
     * Lower power consumption and heat can be achieved if the internal voltage regulator
     * is set to a lower level.
     * With a scale factor of 3, the lowest voltage across the two ceramic condensators
     * of the oscillator is configured. The maximum frequency for a scale factor 3 is 120MHz.
     * The RCC frequency HCLK (SystemCoreClock) is configured to 80MHz, which results in
     * even lower energy consumption.
     * It must be taken into account that the TSIC506 of this sensorhub is based on timer
     * configuration for data bit reading. Configuring HCLK below 80MHz is therefore not considered.
     * To update the voltage scaling value regarding system frequency,
     * refer to product datasheet and the CubeMX graphical clock configuration tool.
     */
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
 
    /* Enable HSI Oscillator and activate PLL with HSI as source */
    rcc_osc_init.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    rcc_osc_init.HSIState = RCC_HSI_ON;
    rcc_osc_init.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    rcc_osc_init.LSIState = RCC_LSI_ON;
    rcc_osc_init.PLL.PLLState = RCC_PLL_ON;
    rcc_osc_init.PLL.PLLSource = RCC_PLLSOURCE_HSI;
    rcc_osc_init.PLL.PLLM = 8;
    rcc_osc_init.PLL.PLLN = 80;
    rcc_osc_init.PLL.PLLP = RCC_PLLP_DIV2;
    if (const auto ret = HAL_RCC_OscConfig(&rcc_osc_init); ret != HAL_OK)
    {
        return ret;
    }
 
    /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
         clocks dividers */
    rcc_clk_init.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |
                              RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
    rcc_clk_init.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    rcc_clk_init.AHBCLKDivider = RCC_SYSCLK_DIV1;
    rcc_clk_init.APB1CLKDivider = RCC_HCLK_DIV2;
    rcc_clk_init.APB2CLKDivider = RCC_HCLK_DIV2;
    if (const auto ret = HAL_RCC_ClockConfig(&rcc_clk_init, FLASH_LATENCY_3); ret != HAL_OK)
    {
        return ret;
    }
    return HAL_OK;
}

I went deeper into this and found out it is only HAL_RCC_ClockConfig() and the configured struct which makes uarts not workable. Makes also sense since HAL_RCC_OscConfig() has no direct influence on the peripherials. Anyway, if I just leave system_clock_config() out and only do HAL_Init(), the uarts work but all our I2C and Timer related sensor measurements will fail.

I saw in the manual there is a mapping table and it says that APB1 covers UART2-5 (plus Timers and all I2Cs) and APB2 "only" covers UART1 and 6. If I execute system_clock_config(), UART1 still works (thats the uart we have been operating the whole time on this board, it was our only needed uart. UART 3 or 5 is now our extension. And they fail with our standart initialisation "system_clock_config()").

I hope I can make you my issue plus or minus clear, it has been a long day...

Thank you very much in advance.

KR

1 ACCEPTED SOLUTION

Accepted Solutions

>> does not work.

It's a bit nebulous, not work how? Don't clock, clock at the wrong speed? Sending a 0x55 or 'U' pattern looks wrong on the scope?

You have APB1 and APB2 clocking at 40 MHz, still faster than the 16 MHz default of HSI

If the function itself is not failing, perhaps the VOS settings? Comment them out. Use bisection methods, perhaps use code examples for the UART.

Use a debugger to understand the peripheral register settings.

Check the U(S)ART and GPIO configurations.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

5 REPLIES 5
TDK
Guru

UART "not working" is usually caused by a mismatch in clocks. Since that's what you're changing here, that would make sense.

You haven't included UART initialization code and you're not using CubeMX generated code, at least not directly, so it's anyone's guess as to what's going on in your program.

Get a logic analyzer or scope on the pins to determine clock speed going out.

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

>> does not work.

It's a bit nebulous, not work how? Don't clock, clock at the wrong speed? Sending a 0x55 or 'U' pattern looks wrong on the scope?

You have APB1 and APB2 clocking at 40 MHz, still faster than the 16 MHz default of HSI

If the function itself is not failing, perhaps the VOS settings? Comment them out. Use bisection methods, perhaps use code examples for the UART.

Use a debugger to understand the peripheral register settings.

Check the U(S)ART and GPIO configurations.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Seeing init(), I'd wager a bet that this is arduino, and also that this is Clive's favourite incorrect HSE frequency constant (which I still don't remember how it's called).

[EDIT] OK I found it, HSE_VALUE

[EDIT2] /* Enable HSI Oscillator and activate PLL with HSI as source */

Oh OK so I've lost... :|

JW

I had to double check the HSI frequency myself, but PLL looks Ok

HSE_VALUE lives in stm32f4xx_hal_conf.h, although HSI is used here, so really just an up-clocking via the PLL

Wait states look Ok

C syntax a bit different, but likely not the issue.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

OK and what about our all-time favourite, the local uninitialized init struct? Namely, rcc_osc_init.PLL.PLLQ?

It does not explain the "USART1 works, USART2 not", though. And it appears to blow only the Q and R taps anyway.

Shall we proceed to reading out and checking the RCC/UART registers content?

JW