プロセッサ・アーキテクチャ

クロック周波数

CPUの動作速度。高いほど速いが消費電力も増える。

概要

クロック周波数(Clock Frequency)は、プロセッサが1秒間に実行できるクロックサイクル数を表し、単位はHz(ヘルツ)を用います。マイコンでは数MHz〜数百MHz、高性能プロセッサでは数GHz(1GHz = 10億Hz)が一般的です。

クロック周波数が高いほどCPUは速く動作できますが、消費電力は周波数に比例して増加し、発熱も大きくなります(CMOS回路の消費電力は P ≈ α × C × V² × f の式に従い、周波数fに比例)。組み込みシステムでは処理速度・消費電力・発熱のバランスを取った適切なクロック設定が重要です。

クロック周波数だけが性能を決めるわけではなく、パイプラインの段数・IPC(Instructions Per Clock: 1クロックで実行できる命令数)・キャッシュ効率・メモリアクセスレイテンシなども大きく影響します。同じ100MHzでもCortex-M4とCortex-M0では実効性能が大きく異なります。

歴史・背景

マイクロプロセッサのクロック周波数は、半導体技術の進化とともに飛躍的に上昇してきました:

  • 1971年: Intel 4004 — 108kHz
  • 1974年: Intel 8080 — 2MHz
  • 1978年: Intel 8086 — 5〜10MHz
  • 1993年: Intel Pentium — 60〜66MHz
  • 2000年: Intel Pentium 4 — 1.3GHz
  • 2004年: Intel Pentium 4 Prescott — 3.8GHz(熱の壁に直面)
  • 2006年以降: マルチコア化へ移行(周波数向上から効率向上へ)

組み込みマイコンでは:

  • 1970年代: 1〜4MHz(8ビットマイコン)
  • 1990年代: 8〜40MHz(16ビットマイコン)
  • 2000年代: 72〜200MHz(32ビットARM Cortex-M)
  • 2010年代以降: 240MHz〜1GHz(高性能マイコン・低コストSoC)

現代のx86デスクトップCPU(Core i9等)は5GHz超のターボクロックに達しましたが、消費電力・発熱の問題から「クロック周波数の競争」は一段落し、電力効率とコアあたりのIPCの向上が主戦場となっています。

技術仕様

クロックソース

組み込みシステムのクロックソースの種類:

クロックソース精度消費電力用途
内蔵RC発振器±1〜3%起動・低速動作
外付け水晶発振子(XTAL)±20〜50ppm高精度クロック
外付けセラミック発振子±0.2〜0.5%コスト重視
内蔵PLL(Phase Locked Loop)XTAL基準で高精度中〜高高速クロック生成
外付けTCXO±1〜5ppm温度補償・通信
外付けOCXO±0.01〜0.1ppm計測・基地局

PLLによるクロック逓倍

現代のマイコンはPLL(Phase Locked Loop)を使って低速な外付け水晶から高速クロックを生成します:

外部XTAL(8MHz)

   PLL逓倍器
(M=2, N=72, P=2)

システムクロック(SYSCLK = 8 / 2 × 72 / 2 = 144MHz)

AHBバス(/1 → 144MHz)
AHBバス(/2 → 72MHz)
APB1バス(/4 → 36MHz)ペリフェラル
APB2バス(/2 → 72MHz)高速ペリフェラル

STM32F4(Cortex-M4)の例:RCC_PLLConfig(RCC_PLLSource_HSE, 8, 336, 2, 7) でHSE 8MHzから168MHzを生成。

代表的なマイコンのクロック周波数

マイコンコア最大クロック備考
STM32L0Cortex-M0+32MHz超低消費電力
STM32F103Cortex-M372MHz汎用定番
STM32F407Cortex-M4168MHz高性能
STM32H743Cortex-M7480MHz最高性能Mシリーズ
nRF52840Cortex-M464MHzBLE旗艦
ESP32Xtensa LX6240MHzWi-Fi+BT
ESP32-S3Xtensa LX7240MHzAI命令
Raspberry Pi 4Cortex-A721.8GHzSBC

消費電力とクロック周波数の関係

CMOS回路の動的消費電力の式:

P_dynamic = α × C × V_DD² × f

α: スイッチング活性率(0〜1)
C: ゲート容量
V_DD: 電源電圧
f: クロック周波数

重要な点として:

  • 消費電力は周波数fに比例(2倍のクロック→2倍の消費電力)
  • 消費電力は電圧V_DDの2乗に比例(電圧低減が最も効果的)
  • 電圧を下げながら周波数も下げるDVFS(動的電圧・周波数スケーリング)が省電力に有効
例: 3.3V 72MHz → 1.8V 36MHz
電圧低減効果: (1.8/3.3)² = 0.298(約1/3)
周波数低減効果: 36/72 = 0.5
合計: 0.298 × 0.5 ≈ 0.15(消費電力が約1/7に削減)

動作原理

クロック分配ツリー

SoC内部ではクロックを各ブロックに分配するクロックツリーが構築されています:

水晶発振子(XTAL)

   PLL/FLL

 システムクロック(HCLK)
   ├── CPU コア
   ├── AHBバスクロック
   │     ├── DMAコントローラ
   │     ├── フラッシュコントローラ
   │     └── USBコントローラ
   ├── APB1クロック(低速ペリフェラル)
   │     ├── UART
   │     ├── I2C
   │     ├── SPI
   │     └── タイマー
   └── APB2クロック(高速ペリフェラル)
         ├── ADC
         └── SPI1

クロックゲーティング(使わないブロックへのクロック供給を停止)で動的消費電力を削減します。

タイミング制約とセットアップ・ホールド時間

高いクロック周波数では信号伝播遅延がクロック周期に近づき、タイミング違反が発生しやすくなります:

クロック周期 T = 1 / f

セットアップ時間制約: T_logic_delay + T_setup < T
ホールド時間制約: T_clock_skew < T_hold

例: 100MHz → T = 10ns
   論理段遅延 + Dフリップフロップのセットアップ時間 < 10ns

組み込みマイコンではクロック周波数を上げるとFlashウェイトサイクル(Wait State)を追加する必要があります:

// STM32 Flash待機サイクル設定(168MHz時)
FLASH->ACR = FLASH_ACR_LATENCY_5WS;  // 5ウェイトサイクル必要

クロックの計測と検証

// ソフトウェアでのクロック周波数確認(STM32 HAL)
uint32_t sysclk = HAL_RCC_GetSysClockFreq();  // Hz単位
uint32_t hclk   = HAL_RCC_GetHCLKFreq();
uint32_t pclk1  = HAL_RCC_GetPCLK1Freq();
uint32_t pclk2  = HAL_RCC_GetPCLK2Freq();

printf("SYSCLK: %lu Hz\n", sysclk);   // 例: 168000000
printf("HCLK:   %lu Hz\n", hclk);
printf("PCLK1:  %lu Hz\n", pclk1);
printf("PCLK2:  %lu Hz\n", pclk2);

用途・ユースケース

オーバークロック(OCとRaspberry Pi)

Raspberry Piはconfig.txtでクロックを公式スペックを超えてオーバークロックできます:

# /boot/config.txt
over_voltage=6
arm_freq=2100    # 公式1800MHz → 2100MHzにOC
gpu_freq=700

ただし発熱増加・安定性低下・保証外動作のリスクがあり、産業用途では推奨されません。

アンダークロック(省電力)

バッテリー動作機器では、処理量に合わせてクロックを動的に下げるDVFS(Dynamic Voltage and Frequency Scaling)を実装します:

// STM32での低速クロック切り替え(省電力モード)
// 通常動作: 168MHz
// 省電力: 8MHz(内蔵RC発振器、PLL停止)

void enter_low_power_mode(void) {
    // PLLを止めてHSIクロック(8MHz)に切り替え
    RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_HSI;
    while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI);
    // PLLオフ
    RCC->CR &= ~RCC_CR_PLLON;
}

リアルタイム処理とクロック周波数

RTOSでの処理時間見積もり:

// 1000命令を72MHzで実行する場合の時間概算
// (CPI=1と仮定、実際はパイプラインストール等で変わる)
// t = 命令数 / クロック周波数 = 1000 / 72,000,000 ≈ 13.9µs

// 周期1msのタスクでの処理余裕確認
#define TASK_PERIOD_US  1000
#define MAX_EXEC_TIME_US  500  // 50%の余裕

void periodic_task(void) {
    uint32_t start = DWT->CYCCNT;  // サイクルカウンタ開始
    do_processing();
    uint32_t elapsed = DWT->CYCCNT - start;
    uint32_t elapsed_us = elapsed / (SystemCoreClock / 1000000);
    assert(elapsed_us < MAX_EXEC_TIME_US);
}

実装・開発のポイント

クロック設定の手順(STM32例)

// STM32F4 168MHz設定(HAL使用)
void SystemClock_Config(void) {
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    // 1. 外部水晶(HSE 8MHz)とPLLの設定
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM = 8;    // HSE / 8 = 1MHz
    RCC_OscInitStruct.PLL.PLLN = 336;  // 1MHz × 336 = 336MHz
    RCC_OscInitStruct.PLL.PLLP = 2;    // 336MHz / 2 = 168MHz (SYSCLK)
    RCC_OscInitStruct.PLL.PLLQ = 7;    // 336MHz / 7 = 48MHz (USB)
    HAL_RCC_OscConfig(&RCC_OscInitStruct);

    // 2. バスクロック分周比の設定
    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;   // HCLK = 168MHz
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;    // PCLK1 = 42MHz
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;    // PCLK2 = 84MHz
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}

クロック周波数の計測

オシロスコープでクロック出力ピンを計測するか、ソフトウェアでDWTサイクルカウンタを使います:

// DWTサイクルカウンタで実行時間計測
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;  // デバッグ有効化
DWT->CYCCNT = 0;  // カウンタリセット
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;  // カウンタ有効化

uint32_t start = DWT->CYCCNT;
my_function();
uint32_t end = DWT->CYCCNT;

uint32_t cycles = end - start;
float time_us = (float)cycles / (SystemCoreClock / 1e6f);
printf("実行時間: %.2f µs (%lu サイクル)\n", time_us, cycles);

他技術との比較

クロック周波数 vs IPC

同じクロック周波数でも、コアの設計によって実効性能は大きく異なります。DMIPS(Dhrystone MIPS)で比較:

コアクロックDMIPS/MHz最大DMIPS
Cortex-M032MHz0.8426.9
Cortex-M372MHz1.2590
Cortex-M4168MHz1.25210
Cortex-M7480MHz2.141027
Cortex-A531.8GHz~3.0~5400

Cortex-M7はCortex-M4に対してクロックが約3倍・IPCが約1.7倍で合計約5倍の性能差があります。

クロック周波数とリアルタイム性

高いクロック周波数は必ずしも優れたリアルタイム性を意味しません。割り込みレイテンシ・コンテキストスイッチ時間・ジッタはクロック周波数以外の要因(パイプライン段数・キャッシュミス・バス調停)にも影響されます。確定的な応答時間が最重要の場合は、低クロックでも単純なCortex-M0の方が優れたリアルタイム性を持つ場合があります。

関連用語

参考リンク