Introduction to different clock sources
1. 마이크로컨트롤러의 주요 클럭 개념
- 시스템 클럭(SYSCLK): 마이크로컨트롤러의 기본 클럭이며, 다른 모든 클럭(HCLK, PCLK, USB, 이더넷, 타이머 등)의 기반
- SYSCLK을 얻는 방법:
- HSI (High Speed Internal oscillator) - 내부 발진기.
- HSE (High Speed External oscillator) - 외부 크리스털 발진기.
- 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
- 기본적으로 MCU는 리셋 후 HSI 사용
- 초기 설정에서는 HSI가 기본 시스템 클럭으로 설정되어 있으며, AHB/APB 프리스케일러가 모두 1이므로 기본 클럭 값은 16MHz
- HSE를 이용한 클럭 설정을 위해 HAL_RCC_OscConfig()와 HAL_RCC_ClockConfig() API를 사용한다.
- HAL_RCC_OscConfig() → RCC 오실레이터 초기화
- HAL_RCC_ClockConfig() → CPU, AHB, APB 클럭 설정
- 데이터시트와 CubeMX를 참고하여 클럭 트리를 확인하고 적절한 설정을 적용
- 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 프리스케일러 설정)
- 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 감소시켜 보정
반응형
'ComputerScience & Embedded > NUCLEO & CAN Tranceiver' 카테고리의 다른 글
Timers (Polling mode / Interrupt mode) (0) | 2025.03.01 |
---|---|
PLL Programming (0) | 2025.03.01 |
STM32 HAL Peripheral data handling APIs (0) | 2025.03.01 |
Peripheral High/Low Level Initialization (0) | 2025.03.01 |
Low-level Processor specific hardware initialization (0) | 2025.03.01 |