不確定特異点

広く深く、ところどころ超深く

STM32F4 Discovery の開発環境 (3)

SystemInit

前回端折った SystemInit は system_stm32f4xx.c で定義されている関数です。これはクロックソースを HSI という内部発振子に設定して、割り込み禁止、例外ベクタハンドラのアドレス設定(VTOR) をしてます。リセット後に初期状態に戻すために使うとよさそう。

168MHz にクロックアップ

SystemInit で設定した状態だと HSI クロックが使われるため、システム全体は 16 MHz で動作する状態のままですが、STM32F4 の実力を発揮させるために、PLL を使って 168MHz まで高速化させます。

PLL を使うには SystemInit 後に以下の処理が必要になります。

  • HSE を有効化
  • 電源電圧設定
  • AHB/APB2/APB1 分周設定
  • PLL の設定
  • Flash の設定
  • クロック切り替え

色々設定しなきゃで面倒…。

PLL の逓倍・分周設定は次のようになります。

PLLCLK = CLKIN / M * N / P

CLKIN は PLL へ入力するクロックソースです。内部発振子の HSI 16MHz や外部クリスタルの HSE 8MHz が使えますが、HSE の方が精度が高いのでこちらを使います。実際にオシロで測定してみると HSI はクロックが揺らぐのに対して、HSE はドンピシャで一定でした。

上式の M, N, P はパラメータで決めることになります。N 逓倍は PLL の VCO の周波数で、これはある範囲におさめる必要があります。データシートによると、192 <= N <= 432 のようです。ターゲットは 168 MHz なので、M=8, N=336, P=2 に設定します。

また、AHB, APB2, APB1 のクロックも制約があるため、その上限を狙った分周設定をします。

AHB = SYSCLK / 1 = 168MHz

APB2= SYSCLK / 2 = 84MHz

APB1 = SYSCLK / 4 = 42MHz

(その他の電源や Flash の設定は長くなりそうなので省略…)

クロック周波数の測定

168MHz のクロック周波数をそのまま測定するには速すぎるので、タイマーで分周した結果を測定する事にします。

LED blinking with timer interrupt

やっている事は、

  • GPIO と TIM2 にクロック供給
  • GPIO を出力モードに設定
  • TIM2 のオートリロード値を設定
  • TIM2 割り込みハンドラで GPIO の出力値を反転

だけです。TIM2 のカウンタが 0 〜 ARR(オートリロード値)まで回ると、TIM2 の割り込みが発生します。ここで注意が必要なのは、TIM2 のクロックドメインです。APB1 のペリフェラルなので、42 MHz になるのかと思いきや、リファレンスマニュアル(RM0090 P216) にこう書いてあります。

The timer clock frequencies are automatically set by hardware. There are two cases:

  1. If the APB prescaler is 1, the timer clock frequencies are set to the same frequency as that of the APB domain to which the timers are connected.

  2. Otherwise, they are set to twice (×2) the frequency of the APB domain to which the timers are connected.

つまり、今回の場合、TIM2 のクロックドメインである APB1 は SYSCLK/4 なので、その 2 倍である SYSCLK/2 = 84MHz でカウンタが回るということになります。APB のバスクロックとカウンタのクロックは別系統なんですね。(最初これを知らずに 42 MHz で回ると思い込んでいて、タイマ周期が 2 倍あわずにかなりハマった…)

したがって、今回の場合、ARR を 84000 に設定すると 1KHz で割り込みがかかる事になります。本当にそうなるか、実際に測定してみました。

f:id:tanakahx:20150823070243j:plain

f:id:tanakahx:20150823164644p:plain

ぴったり 500 Hz です。1 KHz 周期で GPIO を反転させているので、辻褄があってますね。というわけで、足回りの設定も終わり、at speed で動作できるようになったので、ようやく機能の実装をする準備が整いました。