#include "STM32F0x1.h" #include "system.h" #if !defined (HSE_VALUE) #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ #endif /* HSE_VALUE */ #if !defined (HSI_VALUE) #define HSI_VALUE ((uint32_t)8000000) /*!< Value of the Internal High Speed oscillator in Hz. */ #endif /* HSI_VALUE */ #define HSE_STARTUP_TIMEOUT ((uint16_t)0x5000) /*!< Time out for HSE start up */ //! [EnumExampleSW_EN_Def] typedef enum { USEHSI = 0, USEHSE, USEPLL } SW_EN; //! [EnumExampleSW_EN_Def] typedef enum { RCC_CFGR_PLLMUL2 = 0, RCC_CFGR_PLLMUL3, RCC_CFGR_PLLMUL4, RCC_CFGR_PLLMUL5, RCC_CFGR_PLLMUL6, RCC_CFGR_PLLMUL7, RCC_CFGR_PLLMUL8, RCC_CFGR_PLLMUL9, RCC_CFGR_PLLMUL10, RCC_CFGR_PLLMUL11, RCC_CFGR_PLLMUL12, RCC_CFGR_PLLMUL13, RCC_CFGR_PLLMUL14, RCC_CFGR_PLLMUL15, RCC_CFGR_PLLMUL16, } PLLML_EN; /* Select the PLL clock source */ //#define PLL_SOURCE_HSI // HSI (~8MHz) used to clock the PLL, and the PLL is used as system clock source #define PLL_SOURCE_HSE // HSE (8MHz) used to clock the PLL, and the PLL is used as system clock source //#define PLL_SOURCE_HSE_BYPASS // HSE bypassed with an external clock (8MHz, coming from ST-Link) used to clock // the PLL, and the PLL is used as system clock source uint32_t SystemCoreClock = 48000000; const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; static void SetSysClock (void); /** * @brief Setup the microcontroller system. * Initialize the Embedded Flash Interface, the PLL and update the * SystemCoreClock variable. * @param None * @retval None */ extern "C" void SystemInit (void) { /* Set HSION bit */ RCC.CR.R |= (uint32_t) 0x00000001; /* Reset SW[1:0], HPRE[3:0], PPRE[2:0], ADCPRE and MCOSEL[2:0] bits */ RCC.CFGR.R &= (uint32_t) 0xF8FFB80C; /* Reset HSEON, CSSON and PLLON bits */ RCC.CR.R &= (uint32_t) 0xFEF6FFFF; /* Reset HSEBYP bit */ RCC.CR.R &= (uint32_t) 0xFFFBFFFF; /* Reset PLLSRC, PLLXTPRE and PLLMUL[3:0] bits */ RCC.CFGR.R &= (uint32_t) 0xFFC0FFFF; /* Reset PREDIV1[3:0] bits */ RCC.CFGR2.R &= (uint32_t) 0xFFFFFFF0; /* Reset USARTSW[1:0], I2CSW, CECSW and ADCSW bits */ RCC.CFGR3.R &= (uint32_t) 0xFFFFFEAC; /* Reset HSI14 bit */ RCC.CR2.R &= (uint32_t) 0xFFFFFFFE; /* Disable all interrupts */ RCC.CIR.R = 0x00000000u; /* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */ SetSysClock(); } /** * @brief Update SystemCoreClock according to Clock Register Values * The SystemCoreClock variable contains the core clock (HCLK), it can * be used by the user application to setup the SysTick timer or configure * other parameters. * * @note Each time the core clock (HCLK) changes, this function must be called * to update SystemCoreClock variable value. Otherwise, any configuration * based on this variable will be incorrect. * * @note - The system frequency computed by this function is not the real * frequency in the chip. It is calculated based on the predefined * constant and the selected clock source: * * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) * * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) * * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) * or HSI_VALUE(*) multiplied/divided by the PLL factors. * * (*) HSI_VALUE is a constant defined in stm32f0xx.h file (default value * 8 MHz) but the real value may vary depending on the variations * in voltage and temperature. * * (**) HSE_VALUE is a constant defined in stm32f0xx.h file (default value * 8 MHz), user has to ensure that HSE_VALUE is same as the real * frequency of the crystal used. Otherwise, this function may * have wrong result. * * - The result of this function could be not correct when using fractional * value for HSE crystal. * @param None * @retval None */ extern "C" void SystemCoreClockUpdate (void) { uint32_t prediv1factor, pllmull; //! [EnumExampleSW_EN_Use] switch (RCC.CFGR.B.SWS) { case USEHSI: /* HSI used as system clock */ SystemCoreClock = HSI_VALUE; break; case USEHSE: /* HSE used as system clock */ SystemCoreClock = HSE_VALUE; break; case USEPLL: /* PLL used as system clock */ /* Get PLL clock source and multiplication factor */ pllmull = RCC.CFGR.B.PLLMUL + 2u; // ... //! [EnumExampleSW_EN_Use] if (RCC.CFGR.B.PLLSRC == RESET) { /* HSI oscillator clock divided by 2 selected as PLL clock entry */ SystemCoreClock = (HSI_VALUE >> 1) * pllmull; } else { prediv1factor = RCC.CFGR2.B.PREDIV + 1; /* HSE oscillator clock selected as PREDIV1 clock entry */ SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; } break; default: /* HSI used as system clock */ SystemCoreClock = HSI_VALUE; break; } /* Compute HCLK clock frequency */ /* Get HCLK prescaler */ pllmull = AHBPrescTable[RCC.CFGR.B.HPRE]; /* HCLK clock frequency */ SystemCoreClock >>= pllmull; } /** * @brief Configures the System clock frequency, AHB/APBx prescalers and Flash * settings. * @note This function should be called only once the RCC clock configuration * is reset to the default reset state (done in SystemInit() function). * @param None * @retval None */ static void SetSysClock (void) { /* SYSCLK, HCLK, PCLK configuration */ #if defined (PLL_SOURCE_HSI) /* At this stage the HSI is already enabled */ /* Enable Prefetch Buffer and set Flash Latency */ Flash.ACR.setbit([] (auto & r) -> auto { // C++14 r.B.PRFTBE = SET; r.B.LATENCY = SET; return r.R; }); RCC.CFGR.modify([] (auto & r) -> auto { r.B.HPRE = 0; r.B.PPRE = 0; r.B.PLLSRC = RESET; r.B.PLLXTPRE = RESET; r.B.PLLMUL = RCC_CFGR_PLLMUL12; return r.R; }); /* Enable PLL */ RCC.CR.B.PLLON = SET; /* Wait till PLL is ready */ while ((RCC.CR.B.PLLRDY) == RESET); /* Select PLL as system clock source */ RCC.CFGR.B.SW = USEPLL; /* Wait till PLL is used as system clock source */ while (RCC.CFGR.B.SWS != USEPLL); #else #if defined (PLL_SOURCE_HSE) /* Enable HSE */ RCC.CR.B.HSEON = SET; #elif defined (PLL_SOURCE_HSE_BYPASS) /* HSE oscillator bypassed with external clock */ RCC.CR.B.HSEON = SET; RCC.CR.B.HSEBYP = SET; #endif /* PLL_SOURCE_HSE */ __IO uint32_t StartUpCounter = 0; __IO uint32_t HSEStatus; /* Wait till HSE is ready and if Time out is reached exit */ do { HSEStatus = RCC.CR.B.HSERDY; StartUpCounter++; } while ((HSEStatus == RESET) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); HSEStatus = RCC.CR.B.HSERDY; if (HSEStatus == SET) { /* Enable Prefetch Buffer and set Flash Latency */ Flash.ACR.setbit([] (auto & r) -> uint32_t { r.B.PRFTBE = SET; r.B.LATENCY = SET; return r.R; }); RCC.CFGR.modify([] (auto & r) -> uint32_t { r.B.HPRE = 0; r.B.PPRE = 0; r.B.PLLSRC = SET; r.B.PLLXTPRE = RESET; r.B.PLLMUL = RCC_CFGR_PLLMUL12; return r.R; }); /* Enable PLL */ RCC.CR.B.PLLON = SET; /* Wait till PLL is ready */ while ((RCC.CR.B.PLLRDY) == RESET); /* Select PLL as system clock source */ RCC.CFGR.B.SW = USEPLL; /* Wait till PLL is used as system clock source */ while (RCC.CFGR.B.SWS != USEPLL); } else { /* If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error */ } #endif /* PLL_SOURCE_HSI */ }