diff --git a/src/main/startup/system_stm32h7xx.c b/src/main/startup/system_stm32h7xx.c index 49ba5584ab..00a1011ae6 100644 --- a/src/main/startup/system_stm32h7xx.c +++ b/src/main/startup/system_stm32h7xx.c @@ -183,31 +183,55 @@ void HandleStuckSysTick(void) } } -// HSE clock configuration taken from +typedef struct pllConfig_s { + uint16_t clockMhz; + uint8_t m; + uint16_t n; + uint8_t p; + uint8_t q; + uint8_t r; + uint32_t vos; +} pllConfig_t; + +/* + PLL1 configuration for different silicon revisions. + + Note for future overclocking support. + + - Rev.Y (and Rev.X), nominal max at 400MHz, runs stably overclocked to 480MHz. + - Rev.V, nominal max at 480MHz, runs stably at 540MHz, but not to 600MHz (VCO probably out of operating range) + + - A possible frequency table would look something like this, and a revision + check logic would place a cap for Rev.Y and V. + + 400 420 440 460 (Rev.Y & V ends here) 480 500 520 540 + */ + +// 400MHz for Rev.Y (and Rev.X) +pllConfig_t pll1ConfigRevY = { + .clockMhz = 400, + .m = 4, + .n = 400, + .p = 2, + .q = 8, + .r = 5, + .vos = PWR_REGULATOR_VOLTAGE_SCALE1 +}; + +// 480MHz for Rev.V +pllConfig_t pll1ConfigRevV = { + .clockMhz = 480, + .m = 4, + .n = 480, + .p = 2, + .q = 8, + .r = 5, + .vos = PWR_REGULATOR_VOLTAGE_SCALE0 +}; + +// HSE clock configuration, originally taken from // STM32Cube_FW_H7_V1.3.0/Projects/STM32H743ZI-Nucleo/Examples/RCC/RCC_ClockConfig/Src/main.c -/** - * @brief Switch the PLL source from CSI to HSE , and select the PLL as SYSCLK - * source. - * System Clock source = PLL (HSE BYPASS) - * SYSCLK(Hz) = 400000000 (CPU Clock) - * HCLK(Hz) = 200000000 (AXI and AHBs Clock) - * AHB Prescaler = 2 - * D1 APB3 Prescaler = 2 (APB3 Clock 100MHz) - * D2 APB1 Prescaler = 2 (APB1 Clock 100MHz) - * D2 APB2 Prescaler = 2 (APB2 Clock 100MHz) - * D3 APB4 Prescaler = 2 (APB4 Clock 100MHz) - * HSE Frequency(Hz) = 8000000 - * PLL_M = 4 - * PLL_N = 400 - * PLL_P = 2 - * PLL_Q = 5 - * PLL_R = 8 - * VDD(V) = 3.3 - * Flash Latency(WS) = 4 - * @param None - * @retval None - */ static void SystemClockHSE_Config(void) { RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; @@ -227,6 +251,18 @@ static void SystemClockHSE_Config(void) } #endif + pllConfig_t *pll1Config = (HAL_GetREVID() == REV_ID_V) ? &pll1ConfigRevV : &pll1ConfigRevY; + + // Configure voltage scale. + // It has been pre-configured at PWR_REGULATOR_VOLTAGE_SCALE1, + // and it may stay or overridden by PWR_REGULATOR_VOLTAGE_SCALE0 depending on the clock config. + + __HAL_PWR_VOLTAGESCALING_CONFIG(pll1Config->vos); + + while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) { + // Empty + } + /* -2- Enable HSE Oscillator, select it as PLL source and finally activate the PLL */ #define USE_H7_HSERDY_SLOW_WORKAROUND @@ -254,11 +290,11 @@ static void SystemClockHSE_Config(void) RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; - RCC_OscInitStruct.PLL.PLLM = 4; - RCC_OscInitStruct.PLL.PLLN = 400; // 8M / 4 * 400 = 800 (PLL1N output) - RCC_OscInitStruct.PLL.PLLP = 2; // 400 - RCC_OscInitStruct.PLL.PLLQ = 8; // 100, SPI123 - RCC_OscInitStruct.PLL.PLLR = 5; // 160, no particular usage yet. (See note on PLL2/3 below) + RCC_OscInitStruct.PLL.PLLM = pll1Config->m; + RCC_OscInitStruct.PLL.PLLN = pll1Config->n; + RCC_OscInitStruct.PLL.PLLP = pll1Config->p; + RCC_OscInitStruct.PLL.PLLQ = pll1Config->q; + RCC_OscInitStruct.PLL.PLLR = pll1Config->r; RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE; RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2; @@ -311,6 +347,9 @@ static void SystemClockHSE_Config(void) // For HCLK=200MHz with VOS1 range, ST recommended flash latency is 2WS. // RM0433 (Rev.5) Table 12. FLASH recommended number of wait states and programming delay + // + // For higher HCLK frequency, VOS0 is available on RevV silicons, with FLASH wait states 4WS + // AN5312 (Rev.1) Section 1.2.1 Voltage scaling Table.1 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { /* Initialization Error */ @@ -330,19 +369,17 @@ static void SystemClockHSE_Config(void) void SystemClock_Config(void) { - /**Supply configuration update enable - */ MODIFY_REG(PWR->CR3, PWR_CR3_SCUEN, 0); - /**Configure the main internal regulator output voltage - */ + // Pre-configure voltage scale to PWR_REGULATOR_VOLTAGE_SCALE1. + // SystemClockHSE_Config may configure PWR_REGULATOR_VOLTAGE_SCALE0. + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); - while ((PWR->D3CR & (PWR_D3CR_VOSRDY)) != PWR_D3CR_VOSRDY) - { + while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) { + // Empty } - SystemClockHSE_Config(); /*activate CSI clock mondatory for I/O Compensation Cell*/