Warning: The magic method InvisibleReCaptcha\MchLib\Plugin\MchBasePublicPlugin::__wakeup() must have public visibility in /home/prototype09/prototype09.com/public_html/wp/wp-content/plugins/invisible-recaptcha/includes/plugin/MchBasePublicPlugin.php on line 37
Teensy4.1のレジスタを書き換えて超高速digitalWriteを実現する | Prototype 0.9

Teensy4.1のレジスタを書き換えて超高速digitalWriteを実現する

Teensy4.1 (Teensy4)は高速・高性能なマイコンで、ArduinoやESP32では難しい処理をする時に役立ちます。以前の記事では、GPIOのHIGH/LOWの切り替えがESP32よりもかなり速いことを検証しました。

この時の結果はdigitalWriteで35.84ns(クロックで14.0MHz)digitalWriteFastで3.334ns(クロックで150MHz)というスピードであった。これでも驚異的な速度なのですが、レジスタを直接書き換えることで複数のPinを同時に・digitalWriteFastよりも速く書き換えられる可能性があるので、それを検証します。

レジスタを書き換える方法

マイコンの中ではレジスタという領域にデータが入っていおり、この値を変えることでマイコンの設定を変えることができます。Teensy4.1に搭載されたARM Cortex-M7は32bitのマイコンなので、特定の領域(アドレスと言います)の中にある、32桁(2進数)の0と1の並びを書き換えることでGPIOのHIGH/LOWを切り替えたり、読み込んだりすることができます。

ともかくLチカをやってみよう

これで13pin(内蔵LED)が1秒周期でチカチカします。これは13pinがGPIO7というグループの4番目に属しているため、GPIO7_DR_SETの領域にある4桁目(2進数)を1にすると出力がHIGHに(0にしていると影響を受けない)、GPIO7_DR_CLEARの領域にある4桁目(2進数)を1にすると出力がLOWになります。本当はGPIO7ではなくGPIO2に属しているらしいのですが、Arduinoでは高速にON/OFFするためにGPIO7の方を操作しているとのこと(なので他のピンもGPIO1~4ではなくGPIO6~9を操作します)。

Teensy4.1のGPIOのレジスタマップ(参照:https://github.com/KurtE/TeensyDocuments/tree/master

レジスタマップを見ると、一つのGPIOに割り当てられているのはGPIO6が最も多く、20ピンとなっています。一度にHIGH/LOWを切り替えられるのは同じGPIOグループのピン同士なので、最大20ピンを同時に制御できるということになります。(Teensy4だと12ピン)

GPIOの出力を制御するレジスタはそれぞれ以下の通りです。(*はGPIOグループの番号)
 GPIO*_DR:0で出力をLOW、1で出力をHIGH(OUTPUTに設定した全Pinに影響あり)
 GPIO*_DR_SET:1で出力をHIGH、0は変化なし
 GPIO*_DR_CLEAR:1で出力をLOW、0は変化なし
 GPIO*_DR_TOGGLE:1で出力を反転、0は変化なし

GPIOの場所を毎回調べるのは面倒なので

Arduinoのライブラリの記載を借りてきましょう。Teensyduinoライブラリの”core_pins.h”の中に記載された、以下の定数を使います。ちなみに今回はdigitalWriteに関する箇所しか使いませんが、同じファイルにdigitalRead、analogRead/Writeに関する記載もあるので、興味ある人は調べてみてください。

これらの定数をもとに13ピンのLチカを書くとこうなります。

“Set & Clear Test”、”Toggle Test”、”REG Test”は全て同じ動作になります(0.5秒ごとにLEDがOn/OFFを繰り返す)。ただ、”REG Test”は他のGPIOピンの出力に影響を与えるので注意が必要です(今回の場合、他のGPIOピンは(ピンモードをOUTPUTにした場合でも)ずっとLOW)。

複数のPinを同時に切り替える方法

CORE_PIN_BITMASKを足してレジスタに代入すればよいです。ただし、同時に切り替えられるのは同じGPIOのグループに所属しているPin同士のみです。

速度計測

digitalWrite、digitalWriteFast、レジスタ書き換え(Set&CLEAR、TOGGLE、REG)の5種類でHIGH/LOWを1,000,000サイクル繰り返して速度を計測した。

実行結果

方式測定結果 [us]GPIO切り替え速度 [ns]
digitalWrite68,33734.17
digitalWriteFast6,6683.334
Set & Clear:Single Pin6,6683.334
Toggle:Single Pin6,6683.334
REG:Single Pin6,6683.334
Set & Clear:Multi Pin6,6683.334
Toggle:Multi Pin6,6683.334
REG:Multi Pin6,6683.334

digitalWriteとdigitalWriteFastは前回の結果と同じ、レジスタを書き換える方式はPinひとつでも複数でもdigitalWriteFastと同じスピードとなった。

結論

単一のPinの出力だけ変える場合:digitalWriteFast()で十分

複数のPinの出力を高速に変えたい:レジスタを書き換える

おまけ:さらに高速にする方法

実はTeensy4.1はクロックスピードを通常の600MHzからOverClockすることができる(高い周波数の時は冷却が必要)。OverClockにすると、GPIOスピードがもっと高速になります。

クロックスピードdigitalWriteFastの時間 [ns]
600MHz3.334
816MHz2.452
912MHz2.084
1.008GHz1.985

速…!!
250MHzのクロック信号出せるのね…

コメント

タイトルとURLをコピーしました