MicroPython的午睡(99) STM32版、Nuceloのクロック速度つづき

Joseph Halfmoon

今回は前回いまいちスッキリしなかった内蔵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

まず、比較のためによわよわのデフォルト設定での出力波形が以下に。DefaultPortSpeed_PLL

続いて、「3速」にシフトアップした場合が以下に。PortSpeed10_PLL

これで、気になっていた振幅の問題はクリアしましたが、周波数測定についてはあまり変化はありません。結構波形が揺らいでいて周波数の読み値は数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くらいはへいチャラ?(実際は電源電圧低めなので微妙だけれども)

実験用の回路が以下に。MonitorCLKcircuit

上記の回路で分周(4020で16分周、STM32内部で4分周、合計64分周)した波形が以下に。周波数はかなり安定しとります。当然だけど。PortSpeed10_PLL_Q4

 

上記の波形から計算した周波数が以下に。

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()

上記コードの測定結果が以下に。BBspeed

 

やっぱりMicroPythonの方が倍近く速いっす。それでどうこう言う気はないけど。

MicroPython的午睡(98) STM32版、Nuceoのクロック設定を見直す へ戻る

MicroPython的午睡(100) ESP32版、ブートモードに入らなくて焦りました へ進む