Files
d_power/B-G474E-DPOW1_Keil/Core/Src/board.c
2026-05-23 18:02:41 +03:00

190 lines
4.0 KiB
C

#include "board.h"
#include "app_config.h"
#include <stdbool.h>
#include "stm32g474xx.h"
#define CLOCK_STARTUP_TIMEOUT 1000000UL
static volatile uint32_t s_ms_ticks;
static void SystemClock_Config(void);
static bool wait_mask_set(volatile uint32_t *reg, uint32_t mask);
static bool wait_mask_clear(volatile uint32_t *reg, uint32_t mask);
static bool wait_mask_value(volatile uint32_t *reg, uint32_t mask, uint32_t value);
static bool Flash_SetLatency(uint32_t latency);
static void Clock_UseHsi16(void);
void Board_Init(void)
{
SystemClock_Config();
if (SysTick_Config(SystemCoreClock / 1000U) != 0U)
{
Board_FatalError();
}
}
uint32_t Board_Millis(void)
{
return s_ms_ticks;
}
void Board_DelayMs(uint32_t delay_ms)
{
uint32_t start = Board_Millis();
while ((Board_Millis() - start) < delay_ms)
{
__NOP();
}
}
void Board_FatalError(void)
{
__disable_irq();
while (1)
{
__NOP();
}
}
void SysTick_Handler(void)
{
s_ms_ticks++;
}
static void SystemClock_Config(void)
{
Clock_UseHsi16();
#if CLOCK_USE_PLL_170MHZ
/* Enable PWR and switch the STM32G474 regulator to Range 1 boost. */
RCC->APB1ENR1 |= RCC_APB1ENR1_PWREN;
(void)RCC->APB1ENR1;
PWR->CR1 = (PWR->CR1 & ~PWR_CR1_VOS) | PWR_CR1_VOS_0;
PWR->CR5 &= ~PWR_CR5_R1MODE;
if (!wait_mask_clear(&PWR->SR2, PWR_SR2_VOSF))
{
Clock_UseHsi16();
return;
}
/*
* ST G474 power examples use FLASH_LATENCY_4 for 170 MHz.
* Set only the latency field first, then switch SYSCLK, then enable cache.
*/
if (!Flash_SetLatency(FLASH_ACR_LATENCY_4WS))
{
Clock_UseHsi16();
return;
}
RCC->CR |= RCC_CR_HSION;
if (!wait_mask_set(&RCC->CR, RCC_CR_HSIRDY))
{
Clock_UseHsi16();
return;
}
/* HSI16 / 4 * 85 / 2 = 170 MHz. */
RCC->CR &= ~RCC_CR_PLLON;
if (!wait_mask_clear(&RCC->CR, RCC_CR_PLLRDY))
{
Clock_UseHsi16();
return;
}
RCC->PLLCFGR =
RCC_PLLCFGR_PLLSRC_HSI |
(3UL << RCC_PLLCFGR_PLLM_Pos) |
(85UL << RCC_PLLCFGR_PLLN_Pos) |
RCC_PLLCFGR_PLLREN;
RCC->CR |= RCC_CR_PLLON;
if (!wait_mask_set(&RCC->CR, RCC_CR_PLLRDY))
{
Clock_UseHsi16();
return;
}
RCC->CFGR =
RCC_CFGR_HPRE_DIV1 |
RCC_CFGR_PPRE1_DIV1 |
RCC_CFGR_PPRE2_DIV1 |
RCC_CFGR_SW_PLL;
if (!wait_mask_value(&RCC->CFGR, RCC_CFGR_SWS, RCC_CFGR_SWS_PLL))
{
Clock_UseHsi16();
return;
}
FLASH->ACR |= FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_PRFTEN;
SystemCoreClockUpdate();
#endif
}
static bool wait_mask_set(volatile uint32_t *reg, uint32_t mask)
{
uint32_t timeout = CLOCK_STARTUP_TIMEOUT;
while (((*reg & mask) != mask) && (timeout > 0U))
{
timeout--;
}
return timeout > 0U;
}
static bool wait_mask_clear(volatile uint32_t *reg, uint32_t mask)
{
uint32_t timeout = CLOCK_STARTUP_TIMEOUT;
while (((*reg & mask) != 0U) && (timeout > 0U))
{
timeout--;
}
return timeout > 0U;
}
static bool wait_mask_value(volatile uint32_t *reg, uint32_t mask, uint32_t value)
{
uint32_t timeout = CLOCK_STARTUP_TIMEOUT;
while (((*reg & mask) != value) && (timeout > 0U))
{
timeout--;
}
return timeout > 0U;
}
static bool Flash_SetLatency(uint32_t latency)
{
uint32_t timeout = CLOCK_STARTUP_TIMEOUT;
FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY) | latency;
while (((FLASH->ACR & FLASH_ACR_LATENCY) != latency) && (timeout > 0U))
{
timeout--;
}
return timeout > 0U;
}
static void Clock_UseHsi16(void)
{
RCC->CR |= RCC_CR_HSION;
(void)wait_mask_set(&RCC->CR, RCC_CR_HSIRDY);
(void)Flash_SetLatency(FLASH_ACR_LATENCY_0WS);
RCC->CFGR =
RCC_CFGR_HPRE_DIV1 |
RCC_CFGR_PPRE1_DIV1 |
RCC_CFGR_PPRE2_DIV1 |
RCC_CFGR_SW_HSI;
(void)wait_mask_value(&RCC->CFGR, RCC_CFGR_SWS, RCC_CFGR_SWS_HSI);
SystemCoreClockUpdate();
}