systemclock - withrobot/myCortex-STM32F4 GitHub Wiki
myCortex-STM32F4 μμ λ STM32F4 MCUμ 168MHz ν΄λμΌλ‘ ꡬμ±λμ΄ μμ΅λλ€.
STM32 MCUμ ν΄λμ SYSCLKλΌ λΆλ¦¬λ μμ€ν ν΄λμ κΈ°λ°μΌλ‘ κ²°μ λ©λλ€. μμμ λ§ν 168MHzκ° SYSCLK μ λλ€. SYSCLKλ₯Ό κ²°μ νλ κ²μ ν΄λμμ€, PLL λ±μ΄ μμ΅λλ€.
μ°μ ν΄λ μμ€λ‘ μ¬μ©λ μ μλ κ²μ μλμ κ°μ΅λλ€.
- λ΄μ₯ RC μ€μ€λ μ΄ν°(HSI)
- 16MHz λ°μ§νλ‘κ° λ΄μ₯λμ΄ μμ΅λλ€.
- λ³λμ μΈλΆ νλ‘κ° νμνμ§ μμ΅λλ€.
- RC μ€μ€λ μ΄ν°μ΄λ―λ‘ μ λ°ν λμμλ μ ν©νμ§ μμ΅λλ€. -4~+4% μ λμ μ€μ°¨ λ²μλ₯Ό κ°μ§κ³ μμ΅λλ€.
- μΈμ₯ μ€μ€λ μ΄ν°(HSE)
- MCU λ΄λΆμ Pierce μ€μ€λ μ΄ν°κ° λ΄μ₯λμ΄ μμ΄ μΈλΆμ ν¬λ¦¬μ€νΈκ³Ό load capacitorλ§ μΆκ°νλ©΄ λ©λλ€.
- νΉμ μΈλΆμ μ체 λ°μ§νλ μ€μ€λ μ΄ν°λ₯Ό μ¬μ©ν΄λ λ©λλ€.
- μΈμ₯ μ€μ€λ μ΄ν°λ 1
50MHz λ²μμ ν΄λμ μ¬μ©ν μ μμ΅λλ€. ν¬λ¦¬μ€νΈμ΄λ λ μ‘°λ€μ΄ν°λ₯Ό μ¬μ©νλ κ²½μ°μλ 426MHz ν΄λμ μ¬μ©ν μ μμ΅λλ€.
μ λ ν΄λ μμ€λ λͺ¨λ κ·Έλλ‘ SYSCLKλ‘ μ¬μ©λ μ μμ΅λλ€. λν μ΄ ν΄λ μμ€λ₯Ό PLL νλ‘μ μ λ ₯μ μ°κ²°νμ¬ λ³΄λ€ λμ ν΄λμ ꡬνν μλ μμ΅λλ€. STM32F407VEμ PLLμ μ΅λ 168MHzμ μΆλ ₯ ν΄λμ μ§μν©λλ€.
PLLμ 1MHzμ ν΄λ μ λ ₯μ λ°μ μ΄λ₯Ό μ΅λ 336MHzλ‘ λμΈ ν μ΅μ’ μ μΌλ‘ 168MHz ν΄λμ μΆλ ₯ν©λλ€.
SYSCLKλ HSI, HSE, PLL μΆλ ₯ μ€ νλλ‘ μ€μ λ μ μμ΅λλ€.
μλ κ·Έλ¦Όμ STM32F4μ ν΄λμ μμ½ν κ²μ λλ€. MCUλ₯Ό μ λλ‘ μ¬μ©νκΈ° μν΄μλ ν΄λ μμ€ν μ μ΄ν΄νλ κ²μ΄ κ°μ₯ μ€μνλ©°, μ΄ κ·Έλ¦Όμ μμΌλ‘ μμ£Ό λ³΄κ² λ κ²μ λλ€.
myCortex-STM32F4μ μμ μμ€μμλ drv/system_stm32f4xx.c νμΌμ SetSysClock() ν¨μμμ SYSCLK μ€μ μ ν©λλ€. 보λμ μ₯μ°©λ 8MHz ν¬λ¦¬μ€νΈμ μ΄μ©ν΄ HSE μ€μ€λ μ΄ν°λ₯Ό κΈ°λνκ³ , μ΄λ₯Ό PLL μ λ ₯μΌλ‘ μ°κ²°ν΄μ μ΅μ’ μ μΌλ‘ 168MHz ν΄λ μΆλ ₯μ SYSCLKλ‘ μ¬μ©ν©λλ€.
static void SetSysClock(void)
{
/******************************************************************************/
/* PLL (clocked by HSE) used as System clock source */
/******************************************************************************/
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* Enable HSE */
#if FEATURE_HSE_OSC16
RCC->CR |= ((uint32_t)(RCC_CR_HSEON | RCC_CR_HSEBYP));
HSEStatus = (uint32_t)0x01;
#else
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
HSE μ€μ€λ μ΄ν°λ₯Ό enable μν΅λλ€.
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
μ€μ€λ μ΄ν°κ° enable λ λ€μμλ μ€μ€λ μ΄ν°κ° μμ ν λ λ κΉμ§ μ μ μκ°μ΄ νμν©λλ€. μμ ν λλ©΄ κ΄λ ¨ flagκ° μλμΌλ‘ set λμ΄ μ μ μμ΅λλ€.
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
#endif // FEATURE_HSE_OSC16
if (HSEStatus == (uint32_t)0x01)
{
HSEκ° μ±κ³΅μ μΌλ‘ λμνλ©΄ μ΄κ³³μΌλ‘ μ§μ ν©λλ€.
/* Select regulator voltage output Scale 1 mode */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
PWR->CR |= PWR_CR_VOS;
MCU coreλ₯Ό μν λ κ·€λ μ΄ν°λ₯Ό μ€μ νλ μ½λμ λλ€.
/* HCLK = SYSCLK / 1*/
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
HCLKλ SYSCLK κ·Έλλ‘ μ¬μ©ν©λλ€.
#if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx)
/* PCLK2 = HCLK / 2*/
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
/* PCLK1 = HCLK / 4*/
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
#endif /* STM32F40_41xxx || STM32F427_437x || STM32F429_439xx */
PCLK1μ HCLK/4 μ¦ 168/4=42MHzλ₯Ό, PCLK2λ HCLK/2 μ¦ 84MHzλ₯Ό μ¬μ©νκ² λ€κ³ μ€μ νμ΅λλ€. PCLKλ peripheral bus clockμ΄λ©°, RCC μ€μ μ APB1, APB2μ μ¬μ©λλ ν΄λμ μλ―Έν©λλ€.
#if defined (STM32F401xx)
/* PCLK2 = HCLK / 2*/
RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK / 4*/
RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;
#endif /* STM32F401xx */
μ΄ μ½λλ μ¬μ©λμ§ μλ λΆλΆμ λλ€.
/* Configure the main PLL */
RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
/* Enable the main PLL */
RCC->CR |= RCC_CR_PLLON;
PLL μ€μ μ νκ³ PLLμ on μν΅λλ€. PLL μ λ ₯μ 1MHzμ¬μΌ ν©λλ€. κ·Έλμ HSE 8MHzλ₯Ό 8λΆμ£Όν΄μ 1MHzλ₯Ό λ§λλλ€. PLL_Mμ 8λΆμ£Όλ₯Ό μ€μ ν©λλ€.
PLL_Nμ PLL λ΄λΆμμ μμ±ν ν΄λμ μλ―Έν©λλ€. μ΅λ 336MHzκΉμ§ κ°λ₯ν©λλ€.
PLL_Pλ PLL λ΄λΆμμ μμ±λ 336MHz ν΄λμ λ€μ λΆμ£Όν΄μ SYSCLKλ‘ μ¬μ©νλλ‘ ν©λλ€. STM32F4λ SYSCLKμ μ΅λ 168MHz κΉμ§ μ¬μ©ν μ μμ΅λλ€. 336MHzλ₯Ό 2λΆμ£Όνλ©΄ 168MHzκ° λ§λ€μ΄μ§λλ€.
RCC_PLLCFGR_PLLSRC_HSEλ PLL μ λ ₯ μμ€λ‘ HSE ν΄λμ μ¬μ©νκ² λ€λ μλ―Έμ λλ€.
PLL_Qλ APB1, APB2κ° μλ μ μ© ν΄λμ μ¬μ©νλ μ₯μΉλ₯Ό μν λ³λ ν΄λ λΌμΈμ μν λΆμ£Όνλ‘μ λλ€. μ΄λ° μ₯μΉμλ USB, SDIO, RNG λ±μ΄ μμ΅λλ€.
/* Wait till the main PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
PLLμ΄ μμ ν λ λ κΉμ§ κΈ°λ€λ Έλ€κ° μ§νν©λλ€.
#if defined (STM32F427_437xx) || defined (STM32F429_439xx)
/* Enable the Over-drive to extend the clock frequency to 180 Mhz */
PWR->CR |= PWR_CR_ODEN;
while((PWR->CSR & PWR_CSR_ODRDY) == 0)
{
}
PWR->CR |= PWR_CR_ODSWEN;
while((PWR->CSR & PWR_CSR_ODSWRDY) == 0)
{
}
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
#endif /* STM32F427_437x || STM32F429_439xx */
μ μ½λλ μ¬μ©νμ§ μλ μ½λμ λλ€.
#if defined (STM32F40_41xxx)
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
// 20131217 hwpark. errata sheet. rev.A
if (DBGMCU->IDCODE & DBGMCU_IDCODE_REV_ID == 0x20000000) // revision A
FLASH->ACR = FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS;
else // revision Z or later
FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
#endif /* STM32F40_41xxx */
μΊμ¬ λ©λͺ¨λ¦¬ κ΄λ ¨ μ€μ μ λλ€. STM32F4 MCUμ μ΄κΈ° λ²μ μλ μΉ©μ λ²κ·Έκ° μμ΄ prefetch κΈ°λ₯μ μ¬μ©ν μ μμμ΅λλ€. νμ§λ§ μ§κΈμ μ΄ κΈ°λ₯μ μ μμ μΌλ‘ μ¬μ©ν μ μμ΅λλ€. μ΄ μ½λλ μΉ© 리λΉμ μ λ°λΌ prefetch κΈ°λ₯μ μ΄λ¦¬κ±°λ μ£½μ΄λ μ½λμ λλ€.
#if defined (STM32F401xx)
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;
#endif /* STM32F401xx */
/* Select the main PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_PLL;
μ΄μ PLL ν΄λμ΄ μ μμ μΌλ‘ λ§λ€μ΄ μ§κ³ μμΌλ PLL μΆλ ₯ ν΄λμ SYSCLKλ‘ μ§μ ν©λλ€.
/* Wait till the main PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
{
}
}
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 */
}
}