今回は前回いまいちスッキリしなかった内蔵PLLの周波数測定を行ってみます。そのついでにIOポートの「スピード」も調整してみたいと思います。また、別シリーズでBit Banging速度についていい加減なことを書いてしまったので、STM32版のMicroPythonでの速度を測ってみます。いろいろ落穂ひろい編ね。
※「MicroPython的午睡」投稿順 Indexはこちら
※以下のボード上で、以下のバージョンのMicroPythonを使用して動作確認しています。
-
- ST Microelectronics製 NUCLEO-F401RE ボード(STM32F401RE搭載)
- MicroPython v1.19.1-560-g68f166dae on 2022-10-31; NUCLEO-F401RE with STM32F401xE
IOポートの「スピード調整」
使用しているSTM32にはIOポートのドライブ能力を調整するためのOSPEEDRというレジスタが存在しており、4段階に調整できるようになってます。前回から使用しているD7ピン(Arduinoコネクタ上のお名前)の場合、デフォルトは最弱設定みたいです。最弱の場合、適する出力速度は4MHz程度みたいっす。前回は何も設定せず20MHzほどの信号を出力してしまいました。そのせいか波形がフルスイングせず、2V付近でちんまりと振れてました。
D7(STM32の端子的にはPA8)のポートスピードを3段階目の「準高速」に引き上げるコードが以下に。以下2行をPA8の設定関数に追加すればポートのドライバビリティを引き上げることができるようです。
tmp = stm.mem32[stm.GPIOA + stm.GPIO_OSPEEDR] & 0xFFFCFFFF #Port Speed(10) stm.mem32[stm.GPIOA + stm.GPIO_OSPEEDR] = tmp | 0x00020000
まず、比較のためによわよわのデフォルト設定での出力波形が以下に。
これで、気になっていた振幅の問題はクリアしましたが、周波数測定についてはあまり変化はありません。結構波形が揺らいでいて周波数の読み値は数MHzくらい変動してます。PLL出力を4分周(最大は5分周できるケド)しているので、4倍すると10MHzくらい幅のある測定結果になっちまいます。測定に使用しているお手軽ツール Analog Discovery2は
100MS/s
です。ナイキスト周波数的には50MHzまでOKですが、波形を見ようと思うと20MHzは上記のようにかなり辛い感じです。そこで外部で手を打つことにしました。
外部に分周器を取り付け
別シリーズでPLLを練習しており、その分周に使うつもりで4ビット・カウンタIC、TC4520BPを手に入れてありました。最初、今回の作業にも使ってみるつもりでブレッドボードに載せたのです。しかしTC4520BPのデータシートを見たらばダメでした。TC4520BPは古い系統のCMOS-ICなのでとても広い動作電圧範囲を持ち、3.3Vでも動作可能ではあるのです。しかし受け入れられるクロック周波数の上限速度が遅かったです。3.3V電源で20MHzなどはちょっと無理。
そこでTC74HC4020Aにお出ましいただきました。74HCというお名前は伊達ではありません。20MHzくらいはへいチャラ?(実際は電源電圧低めなので微妙だけれども)
上記の回路で分周(4020で16分周、STM32内部で4分周、合計64分周)した波形が以下に。周波数はかなり安定しとります。当然だけど。
上記の波形から計算した周波数が以下に。
1.3348 * 16 * 4 = 85.4272 [MHz]
若干の揺らぎがあるので、5回測定した平均の周波数は
85.4MHz
ドキュメント的には84MHzの筈ですが、ちょいと速めの値を得ました。内蔵クロックソースが多少速めなのか、Analog Discovery2の時間測定の誤差なのかは不明っす。
別件、Bit Bangingもついでに測定
これまた別シリーズでマイコン上のRuby処理系を動かしているときに、うろ覚えの数字を挙げてMicroPythonの方が速い、などと書いてしまいました。その後、うろ覚えの数字は125MHz動作のラズパイPicoの数字だったような気がしました。相手は96MHzなのでラズパイPicoと比べたら遅いのはあたりまえっす。今回85.4MHzと測れたSTM32で確認しておきたいと思います。
実験用のBit Bangingコードが以下に。ほぼRubyで実験したWhileループと同等なコードのハズ。
#STM32F401RE: bit banging on D7 from machine import Pin bb = Pin(machine.Pin.board.D7, Pin.OUT) bb.value(0) def main(): print("STM32F401RE bit banging.") while True: bb.value(1) bb.value(0) # Normal End if __name__ == "__main__": main()
やっぱりMicroPythonの方が倍近く速いっす。それでどうこう言う気はないけど。