2025-02-11 2:11 AM
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?
Solved! Go to Solution.
2025-02-11 12:55 PM - edited 2025-02-11 12:56 PM
> 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.
2025-02-11 6:30 AM
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).
2025-02-11 12:55 PM - edited 2025-02-11 12:56 PM
> 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.
2025-02-12 1:11 AM
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.
2025-02-13 5:24 AM
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.
2025-02-13 5:39 AM
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?"
2025-02-13 6:33 AM
Hello @Danish1
Please refer to user manual UM2217 for better use of the HAL drive.
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.