diff --git a/Source/Core/Inc/system_stm32g4xx.h b/Source/Core/Inc/system_stm32g4xx.h index ed341a8..5a5d55e 100644 --- a/Source/Core/Inc/system_stm32g4xx.h +++ b/Source/Core/Inc/system_stm32g4xx.h @@ -85,6 +85,7 @@ extern const uint8_t APBPrescTable[8]; /*!< APB prescalers table values */ extern void SystemInit(void); extern void SystemCoreClockUpdate(void); +extern void SystemClock_Config(); /** * @} */ diff --git a/Source/Core/Src/system_stm32g4xx.c b/Source/Core/Src/system_stm32g4xx.c index 1ad655f..7260899 100644 --- a/Source/Core/Src/system_stm32g4xx.c +++ b/Source/Core/Src/system_stm32g4xx.c @@ -282,7 +282,63 @@ void SystemCoreClockUpdate(void) * @} */ - +void SystemClock_Config() // STM32G431CBT6 +{ + // 1. Включить тактирование для интерфейса управления питанием (PWR) + // Это действие необходимо совершать одним из первых. + RCC->APB1ENR1 |= RCC_APB1ENR1_PWREN; + + // 2. Установить задержку Flash ПЕРЕД любым увеличением частоты. + // При переключении на PLL 170 МГц и Vcore Range 1 требуется 4 цикла ожидания. + // Безопаснее установить это значение заранее, пока система работает на низкой частоте HSI. + MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, FLASH_ACR_LATENCY_4WS); + + // 3. Включить prefetch buffer, instruction cache и data cache для максимальной производительности. + FLASH->ACR |= FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN; + + // 4. Включить и дождаться готовности HSI (16 МГц). + // Это важно, даже если он уже включен по умолчанию, для явного контроля. + RCC->CR |= RCC_CR_HSION; + while(!(RCC->CR & RCC_CR_HSIRDY)); + + // 5. Настроить масштабирование напряжения на Range 1 (High-performance). + // Это необходимо для работы на высоких частотах. + // ВАЖНО: Делать это ДО включения PLL и переключения на него. + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_CR1_VOS_0); + // Ожидаем готовности регулятора напряжения (ухода флага VOSF). + while ((PWR->SR2 & PWR_SR2_VOSF) != 0); + + // 6. Включить режим Range 1 Boost для частот > 150 МГц. + // Согласно документации (Reference Manual), это нужно делать, когда система + // тактируется от HSI/HSE, ДО включения PLL. + PWR->CR5 |= PWR_CR5_R1MODE; + + // 7. Убедиться, что PLL выключен, перед его настройкой. + RCC->CR &= ~RCC_CR_PLLON; + while(RCC->CR & RCC_CR_PLLRDY); + + // 8. Настроить PLL для получения 170 МГц от HSI. + // SYSCLK = (HSI / M) * N / R = (16МГц / 4) * 85 / 2 = 170 МГц + // VCO = (HSI / M) * N = 4МГц * 85 = 340 МГц (в допустимом диапазоне 64..344 МГц) + RCC->PLLCFGR = (RCC_PLLCFGR_PLLSRC_HSI | // Источник: HSI (16 МГц) + (3 << RCC_PLLCFGR_PLLM_Pos) | // Предделитель M = 4 (записывается 3) + (85 << RCC_PLLCFGR_PLLN_Pos) | // Множитель N = 85 + RCC_PLLCFGR_PLLREN); // Включить главный выход PLL 'R' + // PLLR divider = 2 (по умолчанию, запись 0) + + // 9. Включить PLL и дождаться его готовности. + RCC->CR |= RCC_CR_PLLON; + while(!(RCC->CR & RCC_CR_PLLRDY)); + + // 10. Переключить системные часы (SYSCLK) на PLL. + MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_PLL); + // Ожидаем подтверждения, что система действительно переключилась на PLL. + while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); + + // 11. Обновить глобальную переменную с частотой ядра. + // Это необходимо для корректной работы функций HAL/CMSIS (например, для настройки SysTick). + SystemCoreClock = 170000000UL; +} diff --git a/Source/main.c b/Source/main.c index b771f7c..89e47e7 100644 --- a/Source/main.c +++ b/Source/main.c @@ -30,6 +30,7 @@ void delay_ms(uint32_t ms); int main(void) { + SystemClock_Config(); // 170 MHz __enable_irq();