STM 라이브러리에서 제공하는 Clock 초기화 관련 함수들을 이용해서 72MHz의 시스템 클럭을 설정하는 방법에 대하여 알아보았다.
먼저 STMicroelectronics 홈페이지에 가서 라이브러리를 다운 받는다.
Link : http://www.st.com/mcu/devicedocs-STM32F103RB-110.html
#if !defined (STM32F10X_LD) && !defined (STM32F10X_MD) && !defined (STM32F10X_HD) && !defined (STM32F10X_CL)
/* #define STM32F10X_LD */ /*!< STM32F10X_LD: STM32 Low density devices */
#define STM32F10X_MD /*!< STM32F10X_MD: STM32 Medium density devices */
/* #define STM32F10X_HD */ /*!< STM32F10X_HD: STM32 High density devices */
/* #define STM32F10X_CL */ /*!< STM32F10X_CL: STM32 Connectivity line devices */
#endif
STM32F103RB는 medium density devices이므로 STM32F10X_MD를 활성화 해주어야 한다.
세번째,
stm32f10x.h 파일에 아래와 같이 추가한다.
/**
* @brief In the following line adjust the value of External High Speed oscillator (HSE)
used in your application
Tip: To avoid modifying this file each time you need to use different HSE, you
can define the HSE value in your toolchain compiler preprocessor.
*/
#define EXT_CLOCK_SOURCE_12M
#if !defined HSE_Value
#ifdef STM32F10X_CL
#define HSE_Value ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
#else
#ifdef EXT_CLOCK_SOURCE_12M
#define HSE_Value ((uint32_t)12000000) /*!< Value of the External oscillator in Hz */
#else
#define HSE_Value ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
#endif
#endif /* STM32F10X_CL */
#endif /* HSE_Value */
현재 사용중인 보드는 외부에 12MHz의 crystal을 사용하므로 HSE_Value를 12000000으로 설정하고 나중에 사용하게 된다.
네번째,
system_stm32f10x.c 파일을 아래와 같이 수정한다.
/* #define SYSCLK_FREQ_HSE HSE_Value */
/* #define SYSCLK_FREQ_24MHz 24000000 */
/* #define SYSCLK_FREQ_36MHz 36000000 */
/* #define SYSCLK_FREQ_48MHz 48000000 */
/* #define SYSCLK_FREQ_56MHz 56000000 */
#define SYSCLK_FREQ_72MHz 72000000
SYSCLK_FREQ_72MHz를 72000000으로 설정해 놓았으므로,
SetSysClockTo72()함수가 호출된다.
다섯번째,
system_stm32f10x.c 파일의 SetSysClockTo72() 함수를 아래와 같이 수정한다.
#elif defined SYSCLK_FREQ_72MHz
/**
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 2 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK/2 */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL9);
#else
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
/* if EXT_CLOCK_SOURCE_12M, PLL configuration: PLLCLK = HSE * 6 = 72 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
#ifdef EXT_CLOCK_SOURCE_12M
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6);
#else
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
#endif
#endif /* STM32F10X_CL */
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
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 */
/* Go to infinite loop */
while (1)
{
}
}
}
#endif
외부에 12MHz의 crystal을 사용하므로 PLLMUL6으로 하여 12000000MHz * 6 = 72000000MHz를 사용할 수 있게 된다.
모든 설정이 끝나면 다시 빌드하여 프로그램을 실행해 본다.
[STM32F10x_StdPeriph_Driver] void SetSysClock(void) 함수 (0) | 2009.12.10 |
---|---|
[STM32F10x_StdPeriph_Driver] void SystemInit(void) 함수 (0) | 2009.12.10 |
STM32F10xxx Cortex-M3 programming manual (0) | 2009.12.06 |
An Introduction to the ARM Cortex-M3 Processor (0) | 2009.12.04 |
The STM32 Primer Commnity (0) | 2009.12.03 |