Skip to main content
Graduate
February 11, 2025
Solved

stm32h743 HAL PClock1 Calculation

  • February 11, 2025
  • 3 replies
  • 2082 views

Disclaimer: I don't normally use HAL, but I was trying to learn more about USB hosting so I decided to try out the demonstration application STM32Cube_FW_H7_V1.12.0 STM32H743I-EVAL USB_Host/CDC_Standalone

As I don't have that board, I tried to hook up the LCD output to UART7, but I was surprised to find the baud rate as half what I intended.

The baud rate was set with

 huart7.Instance = UART7;
 huart7.Init.BaudRate = 115200;
 huart7.Init.WordLength = UART_WORDLENGTH_8B;
 huart7.Init.StopBits = UART_STOPBITS_1;
 huart7.Init.Parity = UART_PARITY_NONE;
 huart7.Init.Mode = UART_MODE_TX_RX;
 huart7.Init.HwFlowCtl = UART_HWCONTROL_NONE;
 huart7.Init.OverSampling = UART_OVERSAMPLING_16;
 huart7.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
 huart7.Init.ClockPrescaler = UART_PRESCALER_DIV1;
 huart7.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
 if (HAL_UART_Init(&huart7) != HAL_OK)

and my code for 

void HAL_UART_MspInit(UART_HandleTypeDef* huart)

includes the lines

 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_UART7;
 PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)

 So I'm expecting to use PCLK1, which I intended to be 100 MHz.

In stm32h7xx_hal_uart.c, HAL_StatusTypeDef UART_SetConfig(UART_HandleTypeDef *huart) duly calls 

/**
 * @brief Returns the PCLK1 frequency
 * @note Each time PCLK1 changes, this function must be called to update the
 * right PCLK1 value. Otherwise, any configuration based on this function will be incorrect.
 * @retval PCLK1 frequency
 */
uint32_t HAL_RCC_GetPCLK1Freq(void)
{
#if defined (RCC_D2CFGR_D2PPRE1)
 /* Get HCLK source and Compute PCLK1 frequency ---------------------------*/
 return (HAL_RCC_GetHCLKFreq() >> ((D1CorePrescTable[(RCC->D2CFGR & RCC_D2CFGR_D2PPRE1) >> RCC_D2CFGR_D2PPRE1_Pos]) & 0x1FU));
#else
 /* Get HCLK source and Compute PCLK1 frequency ---------------------------*/
 return (HAL_RCC_GetHCLKFreq() >> ((D1CorePrescTable[(RCC->CDCFGR2 & RCC_CDCFGR2_CDPPRE1) >> RCC_CDCFGR2_CDPPRE1_Pos]) & 0x1FU));
#endif
}

But strangely that seems to return 200 MHz. HAL_RCC_GetHCLKFreq also returns 200MHz.

Looking at the Reference Manual, I see RCC->D2CFGR has a three bit field D2PPRE1 which (in my case) has the binary value 100. Which should correspond to division by 2. And why is the mask 0x1FU for 5 bits?

But the lookup table D1CorePrescTable in system_stm32h7xx.c contains 16 elements, suggesting it is intended for four-bit fields like HPRE in RCC->D1CFGR.

Should be a corresponding D2CorePrescTable, with the values [0, 0, 0, 0, 1, 2, 3, 4]?

Am I doing something wrong, or is this likely to be an error in STM32Cube_FW_H7_V1.12.0?

    This topic has been closed for replies.
    Best answer by TDK

    > STM32Cube_FW_H7_V1.12.0

    This issue is fixed in STM32Cube_FW_H7_V1.12.1 version.

    Garbled Characters Issue in Serial Port 1 with STM... - STMicroelectronics Community

     

    Good catch on the bug.

    3 replies

    Technical Moderator
    February 11, 2025

    Hello @Danish1 

    I have reported your question internally and will get back to you as soon as possible.

    Internal ticket number: 202793 (This is an internal tracking number and is not accessible or usable by customers).

    TDKAnswer
    Super User
    February 11, 2025

    > STM32Cube_FW_H7_V1.12.0

    This issue is fixed in STM32Cube_FW_H7_V1.12.1 version.

    Garbled Characters Issue in Serial Port 1 with STM... - STMicroelectronics Community

     

    Good catch on the bug.

    Danish1Author
    Graduate
    February 12, 2025

    Hi @TDK 

    I have looked at the diff of that "fix", and although it might give better results for PClock1, it gets results wrong for HClock.

    The main change is to D1CorePrescTable which becomes (changes in bold)

    const uint8_t D1CorePrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9};

    That now gives the right result for RCC->D2CFGR field D2PPRE1

    But it now gives wrong results for RCC->D1CFGR fields D1CPRE and HPRE as used by HAL_RCC_GetHCLKFreq for values 0100 to 0111 which should all be divided by 1. (Not sure who would ever use those values)

    The reference manual states for RCC_D1CFGR

    Bits 3:0 HPRE[3:0]: D1 domain AHB prescaler
    Set and reset by software to control the division factor of rcc_hclk3 and rcc_aclk. Changing this
    division ratio has an impact on the frequency of all bus matrix clocks.
    0xxx: rcc_hclk3 = sys_d1cpre_ck (default after reset)
    1000: rcc_hclk3 = sys_d1cpre_ck / 2
    1001: rcc_hclk3 = sys_d1cpre_ck / 4
    1010: rcc_hclk3 = sys_d1cpre_ck / 8
    1011: rcc_hclk3 = sys_d1cpre_ck / 16
    1100: rcc_hclk3 = sys_d1cpre_ck / 64
    1101: rcc_hclk3 = sys_d1cpre_ck / 128
    1110: rcc_hclk3 = sys_d1cpre_ck / 256
    1111: rcc_hclk3 = sys_d1cpre_ck / 512

    @Saket_Om Please could you pass this on to whoever is looking at the ticket.

    Technical Moderator
    February 13, 2025

    Hello @Danish1 

    >> But it now gives wrong results for RCC->D1CFGR fields D1CPRE and HPRE as used by HAL_RCC_GetHCLKFreq for values 0100 to 0111 which should all be divided by 1.

    The values "0100 to 0111" are not allowed when using the HAL RCC driver.

    In fact, the fields D1CPRE and HPRE are written in HAL_RCC_ClockConfig() using assert-protected user inputs for  RCC_ClkInitStruct->SYSCLKDivider and RCC_ClkInitStruct->AHBCLKDivider.

    Predefined macros should be used to write these fields and are listed in stm32h7xx_hal_rcc.h, for example:

    RCC_D1CFGR_HPRE_DIV1 = 0x0
    RCC_D1CFGR_HPRE_DIV2 = 0x8
    Please activate the flag USE_FULL_ASSERT to be able to check the input for peripheral configuration.

    Danish1Author
    Graduate
    February 13, 2025

    Hi @Saket_Om ,

    So what you're telling me is that it is OK for the HAL to give wrong results for situations that have not been set up by HAL.

    That's a valid position. But it is disappointing. Particularly as USE_FULL_ASSERT is OFF by default.

    You could make it always right simply by having another table for D2CorePrescTable, or simply point D2CorePrescTable to &D1CorePrescTable[4]

    Otherwise you'll get someone looking at the code for D1CorePrescTable and thinking "this does not agree with the Reference Manual; which is right?"

    Technical Moderator
    February 13, 2025

    Hello @Danish1 

    Please refer to user manual UM2217 for better use of the HAL drive. 

     

    Saket_Om_0-1739456984444.png

    The full assert functionality detects invalid input values. Therefore, if you don't use input values from the HAL driver, it is important to activate the USE_FULL_ASSERT flag.