본문으로 바로가기

Introduction to different clock sources

1. 마이크로컨트롤러의 주요 클럭 개념

  • 시스템 클럭(SYSCLK): 마이크로컨트롤러의 기본 클럭이며, 다른 모든 클럭(HCLK, PCLK, USB, 이더넷, 타이머 등)의 기반
  • SYSCLK을 얻는 방법:
    1. HSI (High Speed Internal oscillator) - 내부 발진기.
    2. HSE (High Speed External oscillator) - 외부 크리스털 발진기.
    3. PLL (Phase Locked Loop) - 주파수 배수를 통해 클럭 증폭.

2. 보조 클럭 (special requirement)

  • LSI (Low-Speed Internal oscillator, 32kHz): 내부 발진기로 워치독 타이머(Watchdog Timer)와 RTC(Real-Time Clock) 구동 가능. LSE 미지원일 경우 사용.
  • LSE (Low-Speed External oscillator, 32.768kHz): 외부 크리스털 발진기로 RTC를 보다 안정적이고 정확하게 구동. 우선적으로 사용.

3. STM32F446RE (NUCLEO-F446RE 보드 기준)

  • HSI: 16MHz (내부).
  • HSE: 8MHz (외부, ST-Link 회로에서 공급됨).
  • PLL: 최대 180MHz 클럭 생성 가능.
  • LSI: 32kHz (내부).
  • LSE: 32.768kHz (외부, RTC용).

4. 초기 클럭 상태 (리셋 후)

  • 기본적으로 HSI(16MHz) 만 활성화됨.
  • HSE, PLL, LSI, LSE는 기본적으로 꺼져 있으며, 코드로 직접 활성화해야 함.
  • 따라서 마이크로컨트롤러는 기본적으로 16MHz HSI 클럭에서 실행됨.

5. HSI vs. HSE

HSI는 마이크로컨트롤러가 STOP 또는 STANBY 모드에서 깨어날 때, 또는 HSE가 실패할 경우 시스템 clock source로 사용됨

저전력 모드(STOP/STANDBY)에서 복귀할 때도 기본적으로 HSI로 전환

  • HSI의 장점: 내부 발진기라 추가 부품이 필요 없음 → 저비용, 빠른 시작.
  • HSI의 단점: 온도 및 환경 변화에 따라 주파수 정확도가 낮음.
    • 섭씨 25도에서 벗어나면 점차 정확도 감소
  • HSE의 장점: 외부 크리스털이므로 더 정확한 주파수 제공.
  • HSE의 단점: 추가 부품이 필요하고 비용 증가

 

Configure the SYSCLK

1. 필요한 클럭 활성화

  • 기본적으로 마이크로컨트롤러는 HSI(High-Speed Internal) 클럭을 사용
  • HSC(High-Speed External) 클럭이 필요하다면 이를 활성화
  • PLL(Phase-Locked Loop) 이 필요한 경우, 원하는 클럭 주파수에 맞게 PLL을 설정한 후 활성화

2. CPU 및 버스 클럭 초기화

  • CPU 클럭, AHB(Advanced High-performance Bus) 클럭, APB(Advanced Peripheral Bus) 클럭을 설정
  • USB를 사용하는 경우, USB 클럭도 설정
  • 프리스케일러(Prescaler) 값을 설정할 때는 최대 한계를 초과하지 않도록 주의

3. 플래시 레이턴시(Flash Latency) 설정

  • 플래시 메모리와 버스 간의 통신을 보장하기 위해 필요한 클럭 사이클 수
  • 올바르게 설정하지 않으면 플래시 메모리와 CPU 간의 데이터 전송이 원활하지 않을 수 있음
  • 레이턴시 설정을 위해서는 레퍼런스 매뉴얼을 참고

4. 새로 활성화한 클럭을 시스템 클럭으로 설정

  • 모든 초기화 과정이 끝나면 새로 활성화한 클럭을 시스템 클럭(System Clock) 으로 변경

5. STM32 큐브 레이어의 주요 클럭 API

STM32 Cube 레이어에서는 클럭 설정을 위한 두 가지 주요 API를 제공

  • HAL_RCC_OscConfig: 오실레이터(발진기) 설정
  • HAL_RCC_ClockConfig: 시스템 및 버스 클럭 설정

HSE Exercise

  • SYSCLK → 8MHz
  • AHB 클럭 (HCLK) → 4MHz
  • APB1 클럭 (PCLK1) → 2MHz
  • APB2 클럭 (PCLK2) → 2MHz
  1. 기본적으로 MCU는 리셋 후 HSI 사용
    • 초기 설정에서는 HSI가 기본 시스템 클럭으로 설정되어 있으며, AHB/APB 프리스케일러가 모두 1이므로 기본 클럭 값은 16MHz
  2. HSE를 이용한 클럭 설정을 위해 HAL_RCC_OscConfig()와 HAL_RCC_ClockConfig() API를 사용한다.
    • HAL_RCC_OscConfig() → RCC 오실레이터 초기화
    • HAL_RCC_ClockConfig() → CPU, AHB, APB 클럭 설정
  3. 데이터시트와 CubeMX를 참고하여 클럭 트리를 확인하고 적절한 설정을 적용
  4. RCC 관련 드라이버(rcc.c, rcc_ex.c)에서 API를 찾아 확인하고, 해당 API의 구조체 멤버를 분석

 

HSE Bypass

  • 일반적으로 HSE는 외부 크리스털 오실레이터를 사용하지만, Nucleo 보드에서는 크리스털이 없음
  • 대신 ST-Link 디버깅 마이크로컨트롤러(STM32F103)가 MCO(Microcontroller Clock Output)를 통해 HSE 클럭을 공급
  • 따라서, osc_init.HSEState = HSE_BYPASS 설정 필요.

int main(void)
{
	RCC_OscInitTypeDef osc_init;
	RCC_ClkInitTypeDef clk_init;

	HAL_Init();

	UART2_Init();

	memset(&osc_init, 0, sizeof(osc_init));
	osc_init.OscillatorType = RCC_OSCILLATORTYPE_HSE;
	// Nucleo 보드에서는 외부 크리스털 대신 내부 MCO 클럭을 사용하므로 HSE_BYPASS를 설정
	osc_init.HSEState = RCC_HSE_BYPASS;
	
	if(HAL_RCC_OscConfig(&osc_init) != HAL_OK) Error_Handler();

	while(1);
	return 0;
}

 

여기까지가 HSE를 켜는 설정이고, HAL_RCC_ClockConfig API 설정까지 마쳐야 SYSCLK 이 HSE 를 클럭소스로 사용하게 됨

 

Clock Configuration (클럭 소스, AHB, APB 프리스케일러 설정)

Clock Tree

  • AHB 도메인에 대한 클럭인 HCLK가 AHB 프리스케일러를 사용하여 SYSCLK에서 파생됨. 프리스케일러는 clock divider 임
    • 만약 프리스케일러를 8로 설정하면 HCLK는 1Mhz가 됨. (8 나누기 8)
    • AHB 클록을 설정할 때, HCLK의 최대값인 180MHz를 초과하지 않도록 프리스케일러를 설정
    • HCLK의 값을 적절히 줄여야 전력 소비를 줄일 수 있음
  • APB 는 저속 페리페럴을 위한 버스. 고속 버스인 AHB 보다 훨씬 느림 ⇒ HCLK를 직접 받지 않고 최대 속도를 초과하지 않도록 클록 조절
    • APB1은 45MHz, APB2는 90MHz까지 지원

  • Flash Latency 설정: HCLK가 높으면 플래시 메모리가 그 속도를 따라가지 못할 수 있으므로, FLASH_ACR_LATENCY를 설정

  • 레퍼런스 문서를 보면 우리가 사용하는 mc의 전압 범위가 2.7~3.6V이고 HCLK가 30MHz 미만이면 레이턴시가 0 필요. 하지만 150MHz~180MHz 면 플래시 메모리는 6개의 CPU사이클을 대기해야함
  • 지금은 HCLK가 4MHz 이므로 레이턴시는 0
  • HSI 비활성화: HSE가 SYSCLK 소스로 사용되면, 더 이상 HSI를 사용할 필요가 없으므로 HSI를 비활성화하여 전력을 절약

 

SYSTICK_Config 구성 (Systick이 1ms 마다 인터럽트 생성하도록 설정)

  • SysTick 타이머를 초기화하고, 인터럽트를 활성화하며, SysTick 타이머를 시작
  • CMSIS(Core) 에서 제공
  • 인터럽트가 발생할 주기를 결정하는 tick 수를 설정 (HCLK 주기에 따라 계산)
    • SysTick 타이머는 지정된 횟수(tick)만큼 카운트다운한 후 인터럽트를 발생
    • 따라서, 1ms(밀리초)마다 인터럽트를 발생시키려면 "1ms 동안 몇 번의 tick이 발생하는지"를 계산
    • HCLK (CPU 클럭): 4MHz (즉, 4,000,000Hz)
    • 1 Tick의 시간 = 1 / HCLK = 1 / 4,000,000 초 = 0.25μs (마이크로초)
    • 4000 ticks를 설정해야 1ms 후 인터럽트 발생함

 

UART 재설정

원래 UART Baud Rate 가 APB클럭(16MHz) 기반으로 설정되어있었는데 이제 APB클럭이 2MHz로 변경되었으므로 UART_init() 을 그 이후에 다시 호출해야함

int main(void)
{
	RCC_OscInitTypeDef osc_init;
	RCC_ClkInitTypeDef clk_init;
	char msg[100];

	HAL_Init();

	memset(&osc_init, 0, sizeof(osc_init));
	osc_init.OscillatorType = RCC_OSCILLATORTYPE_HSE;
	osc_init.HSEState = RCC_HSE_BYPASS;

	if(HAL_RCC_OscConfig(&osc_init) != HAL_OK) Error_handler();

	clk_init.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
	clk_init.SYSCLKSource = RCC_SYSCLKSOURCE_HSE; // 클럭 소스 설정
	clk_init.AHBCLKDivider = RCC_SYSCLK_DIV2; // 프리스케일러 설정
	clk_init.APB1CLKDivider = RCC_HCLK_DIV2;
	clk_init.APB2CLKDivider = RCC_HCLK_DIV2;

	HAL_RCC_ClockConfig(&clk_init, FLASH_ACR_LATENCY_0WS); // 레이턴시 설정

	__HAL_RCC_HSI_DISABLE(); // HSI 비활성화

	HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

	HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

	UART2_Init(); // UART 재설정

	// CLK 프리퀀시 출력
	memset(msg, 0, sizeof(msg));
	sprintf(msg, "SYSCLK    :  %ld\r\n", HAL_RCC_GetSysClockFreq());
	HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);

	memset(msg, 0, sizeof(msg));
	sprintf(msg, "HCLK    :  %ld\r\n", HAL_RCC_GetHCLKFreq());
	HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);

	memset(msg, 0, sizeof(msg));
	sprintf(msg, "PCLK1    :  %ld\r\n", HAL_RCC_GetPCLK1Freq());
	HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);

	memset(msg, 0, sizeof(msg));
	sprintf(msg, "PCLK2    :  %ld\r\n", HAL_RCC_GetPCLK2Freq());
	HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);

	while(1);
	return 0;
}

 

 

실행 결과

 


HSI Exercise

Understanding HSI calibration

  • HSI 오실레이터의 온도 영향
    • HSI 오실레이터의 정확도는 25°C에서 ±1% 수준
    • 온도가 40°C ~ 105°C 범위로 변하면 정확도가 크게 저하됨(4.5% 이상)
    • 통신 주변장치(UART, SPI, I2C 등)에서 HSI를 사용할 경우, 환경에 따라 동작이 달라질 수 있음
    • STMicroelectronics는 HSI 주파수를 동적으로 조정할 수 있도록 HSI 보정 기능을 제공
    • RCC 제어 레지스터(RCC_CR)의 HSITRIM 필드(5비트)를 사용하여 보정
  • HSITRIM을 통한 주파수 조정
    • 공장 출하 시 HSITRIM 값은 16(0b10000)으로 설정
    • 값 증가(17~31): HSI 주파수 증가.
    • 값 감소(0~15): HSI 주파수 감소
    • 한 단계(1) 조정 시 주파수 변화량:80kHz(0.5% of 16MHz)
    • 예시: HSITRIM 값을 16 → 17로 변경 시 16MHz + 80kHz = 16.08MHz
    • HSI 주파수 측정 및 보정 절차
      • 타이머 입력 캡처 기능을 이용해 HSI 주파수를 측정
      • 원하는 주파수와 비교 후, HSITRIM 값을 조정하여 보정
      • 예: 측정된 주파수가 160kHz 높다면, HSITRIM 값을 2 감소시켜 보정
반응형