STM 라이브러리에서 제공하는 Clock 초기화 관련 함수들을 이용해서 72MHz의 시스템 클럭을 설정하는 방법에 대하여 알아보았다.

먼저 STMicroelectronics 홈페이지에 가서 라이브러리를 다운 받는다. 
Link : http://www.st.com/mcu/devicedocs-STM32F103RB-110.html


위의 링크에 가서 STM32F10x_StdPeriph_Lib 를 다운받으면 된다.

다운로드 후에는 아래와 같이 프로젝트를 생성하고 다음 절차에 따라 진행하면 된다.


첫번째,
system_stm32f10x.c 와 startup_stm32f10x_md.s 을 컴파일러에 포함한다.



두번째,
stm32f10x.h 파일에서 아래 부분을 활성화한다.

/* Uncomment the line below according to the target STM32 device used in your application  */

#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를 사용할 수 있게 된다.



모든 설정이 끝나면 다시 빌드하여 프로그램을 실행해 본다.






Posted by eoseontaek