NuttX에서 CPU freq/clock 가져오는 방법
임베디드 개발에서 성능 분석을 하다 보면 반드시 마주치는 질문이 있다.
"지금 CPU가 몇 MHz로 동작하고 있는가?"
특히 LVGL, UI 렌더링, 프레임 드랍 분석을 하려면 CPU 클럭 정보는 거의 필수다.
하지만 중요한 사실 하나:
NuttX에는 CPU 클럭을 가져오는 표준 API가 없다
이 글에서는 NuttX에서 CPU 클럭을 얻는 모든 방법을 정리한다.
1. 전체 구조 이해
CPU 클럭을 얻는 방법은 다음 4단계로 나뉜다.
- NuttX 공통 레벨
- Board / BSP 레벨
- SoC 클럭 드라이버
- Hardware Register 직접 접근
2. NuttX 공통 레벨 (거의 불가능)
clock_gettime()
가능한 것: - 시간 측정
불가능한 것: - CPU 클럭 확인
3. Board / BSP 레벨
보드에서 board_cpu_frequency() 같은 API를 제공해줄 수 있다. 문제는 보드마다 다를 수 있다는거..
4. SoC 클럭 드라이버 (추천)
SoC에서도 API를 제공해줄 수 있는데, DVFS도 반영되어있어 이걸 사용하는 것이 좋아보인다.
- clk_get_rate()
- CLOCK_GetFreq()
- SystemCoreClock
5. Hardware Register 직접 읽기
직접 PLL / divider 계산해서 freq를 구하는 것이다. 가장 정확하겠지만, 구현하는게 어렵다.
uint32_t pll = readl(PLL_REG);
uint32_t div = readl(DIV_REG);
freq = pll / div;
장점:
- 가장 정확
단점:
- 구현 어려움
6. BES 계열에서 CPU Clock 가져오기
BES 계열은 보통 CMU (Clock Management Unit) API가 있음.
uint32_t hal_sysfreq_get(void);
아래 처럼 쓸 수 있다.
#include "hal_sysfreq.h"
uint32_t freq = hal_sysfreq_get();
printf("CPU freq: %u\n", freq);
리턴 값은 아래와 같은데,
typedef enum {
HAL_CMU_FREQ_32K,
HAL_CMU_FREQ_26M,
HAL_CMU_FREQ_52M,
HAL_CMU_FREQ_104M,
HAL_CMU_FREQ_208M,
} HAL_CMU_FREQ_T;
이런 식으로 실제 MHz로 변환이 필요하다.
uint32_t freq_to_hz(enum HAL_CMU_FREQ_T f) {
switch (f) {
case HAL_CMU_FREQ_26M: return 26000000;
case HAL_CMU_FREQ_52M: return 52000000;
case HAL_CMU_FREQ_104M: return 104000000;
case HAL_CMU_FREQ_208M: return 208000000;
default: return 0;
}
}
만약 이 API도 제공하고 있다면, 이건 바로 현재의 실제 클럭을 알려준다. 리턴 값을 클럭으로 변환하지 않아도 되고, 더 정확하다고 볼 수 있다.
uint32_t hal_cmu_get_sys_clock(void);
레지스터를 읽어서 계산할 수도 있겠지만, API가 제공되면 API를 사용하자.
pll = readl(PLL_CFG);
div = readl(CPU_DIV);
freq = (XTAL * pll_mult) / div;
상위 레이어의 앱에서는 아래와 같이 하위 레이어의 API를 호출하여 freq를 계산하고 로그로 출력할 수 있다.
void log_frame_info(void)
{
uint32_t freq = hal_sysfreq_get();
uint32_t cycles = DWT->CYCCNT;
printf("freq=%u, cycles=%u\n", freq, cycles);
}
또는,
start = DWT->CYCCNT;
lv_timer_handler();
end = DWT->CYCCNT;
freq = hal_sysfreq_get();
printf("freq=%u Hz, frame_cycles=%u\n", freq, end - start);
CPU 클럭은 높은데, 느린거 같다면? BUS 클럭이 낮을 수도 있다. BUS bottleneck을 의심하자.
7. 결론
- NuttX에는 CPU 클럭 API 없음
- SoC/보드에서 가져와야 함
- 실전은 clk driver + cycle counter 조합