cancel
Showing results for 
Search instead for 
Did you mean: 

stm32h743 HAL PClock1 Calculation

Danish1
Lead III

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?

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

> 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.

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

View solution in original post

6 REPLIES 6
Saket_Om
ST Employee

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).

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar
TDK
Guru

> 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.

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

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.

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.

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar
Danish1
Lead III

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?"

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.

 

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar