본문 바로가기
임베디드 개발/STM32 (ARM Cortex-M)

STM32 ] Clock 설정, HSI, HSE, PLL, LSI, LSE

by eteo 2023. 2. 5.

 

 

Clock Source 종류

 

일반적으로 Clock을 얘기할 때는 main system clock 을 말한다. 그리고 system clock(SYSCLK)은 다음의 세가지 clock sources 에서 나올 수 있다.

 

  • HSI(High Speed Internal) oscillator clock
  • HSE(High Speed External) oscillator clock
  • Two main PLL(Phased Locked Loop) clock

 

또한 SYSCLK가 아니라 secondary 목적으로 사용되는 clock sources 가 2개 있다.

 

  • 32kHz low-speed internal RC (LSI) : Watchdog에 사용되고, Stop/Standby Mode 에서의 RTC를 사용한 Auto-wakeup 용도로 사용될 수 있다.
  • 32.768kHz low-speed external crystal (LSE) : RTC Clock 에 사용될 수 있다.

보드에 LSE가 안달려있다면 LSI를 대신 사용할 수 있겠지만 LSI가 LSE보다 오차발생률이 높다. HSI와 HSE의 경우도 마찬가지다, HSI가 오차발생률이 높다.

 

 

 

 

 

 

 

 

 

STM32F429ZI Clock

 

STM32F429ZI 보드는 다음의 스펙을 가지고 있다.

 

  • HSI → 16MHz
  • HSE → 8MHz
  • PLL → can generate clock up to 180MHz
  • LSI → 32kHz
  • LSE →32.768kHz

 

그리고 이 보드의 회로도를 살펴보면 on-board HSE는 안달려있지만 ST-LINK 회로에 있는 8MHz를 HSE input으로 사용할 수 있다.

 

 

 

 

 

 

 

 

 

 

Default Clock State

 

MCU 리셋 이후 하드웨어가 자동으로 HSI 를 on 시키지만 나머지 Clock Source는 개발자가 코드를 통해 on시키지 않는 한 default OFF 상태이다.

 

HSI is ON, HSE is OFF, PLL is OFF, LSE is OFF, LSI is OFF

 

즉, HSI 만 on 상태이므로 리셋 직후의 SYSCLK은 16MHz가 된다. 또한 각 클락소스는 필요(Optimization Power Consumption)에 의해 껐다 켤 수 있다.

 

 

 

 

 

HSI

 

  • Startup 이후 하드웨어에 의해 system clock souce로 HSI가 사용된다. 또한 Stop/Standby Mode에서 깨어나거나 HSE의 failure를 detect 한 경우에도 HSI가 바로 system clock으로 사용된다.
  • HSI RC oscillator는 MCU에 내장되므로 저렴한 비용으로 사용할 수 있다는 장점이 있다.
  • HSE crystal oscillator 보다 startup time이 빠르다는 장점이 있다.
  • Calibration을 하더라도 external crystal oscillator나 ceramic resonator보다 frequency 정확도가 떨어진다는 단점이 있다. 정확도는 온도의 영향을 많이 받으므로 사용환경의 온도가 높아지는 경우 HSI의 정확도가 더 많이 떨어진다.
  • HSE에 문제가 생기는 경우를 대비해 HSI를 backup source(Auxiliary clock)으로 사용할 수 있다.

 

 

데이터시트를 확인하면 25°일땐 ±1%의 오차를보이지만 온도의 변화에 크게 영향을 받는것을 알 수 있다.

 

 

 

 

 

 

STM32의 Clock을 다루기 위한 Driver API

 

stm32f4xx_hal_rcc.c

stm32f4xx_hal_rcc_ex.c

stm32f4xx_hal_rcc.h

stm32f4xx_hal_rcc_ex.h

 

에 있다. 여기서 rcc는 Reset and Clock Control을 뜻하고 뒤에 _ex가 붙은 것은 extension을 의미한다.

 

 

 

 

 

 

Clock Configuration 코드 살펴보기

 

CubeMX를 통해 생성된 SystemClock_Config()함수를 살펴보자

 

 

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 180;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Activate the Over-Drive mode
  */
  if (HAL_PWREx_EnableOverDrive() != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

 

 

클락 설정에 아래 구조체를 사용하고

RCC_OscInitTypeDef

RCC_ClkInitTypeDef

 

아래 두 함수를 사용한다.

HAL_RCC_OscConfig(&RCC_OscInitStruct)

HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5)

 

 

1. 먼저 HAL_RCC_OscConfig() 함수를 통해, 필요한 클락을 enable 하고 클락이 ready 상태가 될 때까지 대기한다. 그리고 PLL을 사용하는 경우 PLL에 대한 설정을 한다.

2. 그리고 HAL_RCC_ClockConfig() 함수를 통해 CPU를 initialize 하고 AHB, APB bus 클락 prescaler 값을 설정한다. Flash 메모리에서 데이터를 제대로 읽기 위한 latency(wait time)를 설정하고 지정된 클락 소스를 system 클락으로 선택한 뒤 systick timer를 시작한다.

 

 

 

 

Reference : FastBit Embedded Brain Academy