動作周波数を168Mhzに変更する

さて、前回実はクロックが内部クロックになっていて、しかもどうやら168Mhzではなさそうということがわかりました。
今回は168Mhzで動かすための設定です。

クロック図

何回か前に紹介したこのマイコンのクロックですがもう一度見てみましょう

stm32f4_clock0
出典
: ReferenceManual

これを見ても何が何やらですが、スタートアップスクリプトからどういう設定になっているのかというと。

stm32f4_clock1
出典
: ReferenceManual

こうなっています。
基本的に左が源で右がどこに使われているかなのですが、
この「HCL to AHB bus,core,memory and DMA」というのがマイコンのベースとなるクロックです。1+1がどのぐらいの速度で計算されるかはここで決まるわけです。
そしてスタートアップスクリプトの設定を見るに、ここのクリックが何から来ているかというと16MhzのHSIRCというマイコン内蔵の16Mhzのクロックになっています。
もちろん使えるクロックですが、精度が微妙で正確な何かを作るときにはちょっと使えません。
では、せっかくつながっている制度の良い外部の8Mhzをつかって168Mhzで動かしてみましょう。

じゃあPLLを使わなければ

168Mhzで動かすのに一番簡単なのは168Mhzのクリスタルを買ってきてマイコンにつなぐことです。ただ、168Mhzというクリスタルクロックはありません(あっても入手が難しいし、つなぐのも大変)
そこでこのマイコンに内蔵されているPLLという周波数を増やす回路を使います。つまりプログラム絵設定しなきゃいけない手順としてはこんな感じになるんです

  1. 外部クロックにクロックを切り替える
  2. PLLをONにする
  3. PLLで正しい周波数を設定する
  4. その他プリスケーラなどを設定する

さて、正解を先に見てみましょう。

SetSysClock(void)というのはSTMが他の場所で公開していた168Mhzにするための関数です。僕らのプロジェクトには入ってないのですが、他の場所から引っ張ってきました。
何で先に正解を用意したかというと、さっきのPLLをONにして〜という手順には今はまだ知らなくていいであろういろいろなレジスタが関係してくるのでとりあえず今は168Mhzに出来るようにしておいて、説明を軽くしようと思いました。
この関数を呼べば168Mhzに切り替わるのでmain関数の最初に書いておけばOKです。このまま便利に使いましょう。

どういう流れなのか

とはいえ、ちょっと中身を知っておきましょう。
今回のこのプログラムで設定されている流れはこうなっています。

stm32f4_clock2
出典
: ReferenceManual

8Mhzの入力がHCLKに行くまでにどうなっていっているかというと

  1. 最初のプリスケーラ(分周器)でM分の1にして1Mhzを作る
  2. 1MhzをN倍して366MHzを作る
  3. 分周器でN分の1にして168Mhzを作る
  4. AHBプリスケーラをそのまま1倍で通過してHCLKとして使う。

という感じです。図で表すと

IMG_0673

何故こんなややこしいことになっているかというと、いくつか制限があります。
まず回路的な制限として

  1. VCOの入力は1~2Mhz
  2. VCOの出力は100~432Mhz(100以下も可能ではあるが注意が必要)
  3. Pの出力は180Mhzが上限

そして、それぞれ M N Pという値がありますが、それらも設定できる値が決まっていて

  1. M = 2〜63
  2. N = 2〜432
  3. P = 2,4,6,8

この条件で考えると、8Mhzの入力に対して M=8, N=366,P=2の設定で168Mhzを作るのが良さそうとなるわけです。
ちなみに168Mhzでなく180Mhzでも動くわけですが、168Mhzにしているのはいつか使うであろうUSBの48Mhzを作るためにVCOを336Mhzにしています。(USBのクロックはVCOの出力を別のQという分周器で作っています。Qの値を7にすると48Mhzになります。これはUSBの通信速度です)

深いことは考えない

これでPLLでどうやって168Mhzを作っているのかわかりました。
今回はここまででこの関数やレジスタは深追いはしません、流れだけ書いておきますね。

  1. HSE(外部クロック)を有効にする
  2. HSEが正常に立ち上がって、かつある程度クロックを出すまで待つ(クリスタルの起動後は不アンテナ周波数なため待つのが普通)
  3. VCOの準備
  4. APB2はHCLKの1/2となるようにする
  5. APB1はHCLKの1/4となるようにする
  6. PLLに各値の設定
  7. PLLをONにする
  8. PLLが安定になるまで待機
  9. クロック源をHSIからPLLに切り替える
  10. 切替後正常になるまで待機
  11. I2Cに関する別のPLLの設定

ただ、1つあなたが気にしなきゃいけないのはAPB1とAPB2のクロックです。
これらはAHBのクロック(168Mhz)を分周したものになっています。
前回まで使ってきたGPIOはAPB2のクロックを使っていましたね。
APB2は1/4分周されているので168/4=42Mhzとなります。
つまりCPUの実行速度とは違ってだいぶ遅いわけです。
なんでかというと実はAPB1とAPB2は上限速度があって、それもだいぶ遅くて

  1. APB2は90Mhzが上限
  2. APB1は45Mhzが上限

となっているからです。

このプログラムを動かすと前回と何の違いもなくLEDがボタンに合わせてON,OFFします。
速くなったかどうかわからないですね。。。
それを確かめるためにも次回はタイマーを使って時間が経ったら何かをするというプログラムを書いてみましょう。
これで本当に168Mhzになっているかを確認できますね。

コメントを残す