macsbug

ESP8266 の GPIO 速度

with 7 comments

ESP8266 のGPIOの速度を調べてみました。              2016.02.16
_                            追記及び改訂 2016.02.17
ESP8266 (32bit 80MHz:ESP8266EX) は 単純計算で Arduino UNO より5倍(80/16)速い。
3D CUBE with ESP8266 and OLED では その差が見えました。
では、実際の GPIO の速度はどうなのか?


Lチカ等の速度を必要としないものは良いのですが、
周波数の高い信号の解析や信号を発生させる場合は 高速のGPIOを必要とします。
この為には、現在の速度の把握とGPIOへのダイレクト・アクセスが必要です。
注:測定器の性能が低い事と波形のひずみがある為に数値が不正確かも知れません。

ESP8266 は 32bit 80MHzに加えてWiFi 機能、D1 miniでの大きさは1/4。
ESP8266EXをArduinoに装着すれば 製品版の「WeMos D1」になる。
性能はArduinoより強力だが弱点はアナログ入力が1つである事。


結論:
digitalWrite 命令の速度。
_ ESP8266 は 最高 1MHz の周波数出力が可能である。
_ ESP8266 は Arduino UNO に比べ11倍の周波数を出力できる。
_ ESP8266 は Arduino DUE に比べ    5倍の周波数を出力できる。

Direct Access Port 命令の速度。
_ ESP8266 は 最高 6.2MHz の周波数出力が可能である。
_ ESP8266 は Arduino UNO に比べ12倍の周波数を出力できる。
_ ESP8266 は Arduino DUE に比べ 周波数は 約1/3倍である。



Arduino UNO:digitalWrite(13, HIGH); digitalWrite(13, LOW);
最小幅:5.06 usec。1周期:10.56 usec。周波数:94.65 KHz。

Arduino UNO:PORT操作:PORTB = B11111111; 上記と比較の為時間軸を同じ。
最小幅:4.00 usec。1周期:999 nsec。周波数:500.0 KHz。

Arduino UNO:PORT操作:PORTB = B11111111;
最小幅:4.00 usec。1周期:999 nsec。周波数:500.0 KHz。


DUE:digitalWrite(13, HIGH); digitalWrite(13, LOW);:この繰り返し
最小幅:2.47 usec。1周期:4.88 usec。周波数:204.8 KHz。

DUE:PORT操作:POUT(13,HIGH); POUT(13,LOW);:この繰り返し
最小幅:27.6 nsec。繰り返し幅:72.1 nsec。周波数:13.87 MHz。
注:測定器の精度により正しく測定されていません。


ESP8266:void loop() {digitalWrite(13, HIGH); digitalWrite(13, LOW);}
最小幅:0.410 usec。LOOPによる遅延:6.17 usec。


ESP8266:digitalWrite(13, HIGH); digitalWrite(13, LOW);:この繰り返し
最小幅:438 nsec。繰り返し幅:923 nsec。周波数:1.083 MHz。


追記:2016.02.17
再測定:測定器の性能が低く測定できない事と、DUEの出力波形が歪んでいる為
_ 測定方法は2つのポートの時間差を比較する事とした。

DUE:PORT操作:POUT(13,HIGH); POUT(12,LOW);delayMicroseconds(1);:13 と 12 の差
最小幅:28 nsec。繰り返し幅:56 nsec。周波数:17.85 MHz。

ESP8266:PORT操作:PIN_0 = 1;PIN_2 = 1;delayMicroseconds(1);:GPIO_0 と 2 の差。
最小幅:80 nsec。繰り返し幅:160 nsec。周波数:6.25 MHz。


詳細:
Arduinoでは以下に示す内容で高速アクセスが可能である。
Arduino UNO (8bit 16MHz:ATmega328P):ダイレクトにアクセスできる命令がある。
_ 例:DDRD = B11111110; PORTD = B10101000; 参照:Arduino:Port Registers
_ 例:PORTB =_BV(1)|_BV(2);  a = PINH & _BV(6) + _BV(5);
Arduino MEGA (8bit 16MHz:ATmega2560):例:UNOと同様。
Arduino DUE  (32bit 84MHz:Atmel SAM3X8E ARM Cortex-M3)
_ DUEはUNOのダイレクトアクセス命令は使用できないが以下で動作する。

//====================================================================
inline void POUT(int pin, boolean val){          // POUT:Port OUTPUT
  if(val) g_APinDescription[pin].pPort ->        // digitalWriteDirect
        PIO_SODR = g_APinDescription[pin].ulPin; //
  else    g_APinDescription[pin].pPort ->        //
        PIO_CODR = g_APinDescription[pin].ulPin; //
}                                                //
//====================================================================
inline int PIN(int pin){                         // PIN:Port INPUT
  return !!(g_APinDescription[pin].pPort ->      // digitalReadDirect
        PIO_PDSR & g_APinDescription[pin].ulPin);//
}                                                //
//====================================================================

POUT(13,HIGH);
a = PIN(13);

ESP8266では以下に示す内容で高速アクセスが可能である。
今回測定のスケッチ:(事前準備が必要:参考を参照の事)

extern uint32_t PIN_OUT;
extern uint32_t PIN_DIR;
extern uint32_t PIN_0;
extern uint32_t PIN_2;

void setup() {
  PIN_OUT = 0b101;
  PIN_DIR = 0b101;
}

void loop() {
  PIN_0 = 0;
  PIN_2 = 0;
  delayMicroseconds(1);
  PIN_0 = 1;
  PIN_2 = 1;
  delayMicroseconds(1);
}

参考:
ESP8266 DIRECT GPIO ACCESS:ネットでこの論議をしている場所。
_ 上記の内容で DIRECT GPIO ACCESS は可能です。
_ これには、「Arduino15」ファイル内の「eagle.app.v6.ld」リンカースクリプトに追加をします。
_ ユーザー/ライブラリーの不可視ファイルを開く必要があり、eagle.app.v6.ld の場所は、
_ ~/Library/Arduino15/packages/esp8266/hardware/esp8266/2.0.0/tools/sdk/ld/ です。
_ eagle.app.v6.ld に上記に書かれている、PROVIDE(PIN_OUT = 0x60000300); から
_  PROVIDE(PIN_0 = 0x60000328); までを追加すると この命令が使えるようになります。
_ スケッチの定義は、extern uint32_t PIN_OUT; から extern uint32_t PIN_2; を記述します。
_ それにより、PIN_IN、PIN_0、PIN_2が使用できるようになります。
_ GPIO0とGPIO2 のみですが、他はアドレスとピンを追加すればよいかと思います。
_ :不可視ファイル内のリンカースクリプトを書き換える為、問題を起こす可能性があります。
_   この件は上記の論議の中でされています。
追記:2016.02.18:「eagle.app.v6.ld」を書き換えずにスケッチを記述する方法があります。
_  この件は、後日記事にする予定です。
Neil kolban:Kolban’s Book on ESP8266:GPIOの詳細が書かれています。
esp8266.ru:ESP8266 Pins list function, register, strapping:GPIOのアドレス。

ESP8266/ESP32で遊んでます。:ESP8266で高速GPIOアクセス: 2017.09.17 追記。


感想:
Arduino DUE の方法は、難しい表記ですが先人により実現しています。
追記:2016.02.17:FaceBookのESP8266環境向上委員会で永山氏からアドバイスを
_ いただき DIRECT GPIO ACCESSの方法が判明しました。永山氏に感謝。
_ DIRECT GPIO ACCESS では、DUE が ESP に比べ遥かに速く どういう事か疑問が起きる。
_ 特に ESP8266 の DIRECT GPIO ACCESS が想像よりも遅いのは残念です。
_ 測定を何度もしたがほぼ同じ結果。いくつか疑問がありますが今回はこれまでとしました。
_ 高速にアクセスできる事によりこれまで以上の事が出来るかも知れません。
_ ESP8266 の DIRECT GPIO ACCESS による Lチカが出来ました。

extern uint32_t PIN_OUT;
extern uint32_t PIN_DIR;
extern uint32_t PIN_0;

void setup() {
  PIN_OUT = 0x01;
  PIN_DIR = 0x01;
}

void loop() {
  PIN_0 = 0;
  delay(1000);
  PIN_0 = 1;
  delay(1000);
}

 

Written by macsbug

2月 15, 2016 @ 11:01 pm

カテゴリー: ESP8266

7件のフィードバック

Subscribe to comments with RSS.

  1. 色々と参考になります。

    > LOOPによる遅延:6.17 usec

    これまで、loopそのものの遅延を気にしてませんでした。

    GPIOのdirect accessの方法も参考になります (永山さんにも感謝)。

    http://qiita.com/7of9/items/c55023a4af15b83ac7e3
    で試していたときにdirect accessの方法を自分で探しましたが、探しきれませんでした。

    7of9

    2月 18, 2016 at 3:39 am

  2. 7of9さん、ブログを見に来ていただきありがとうございます。
    通常の速度ではLOOPは目立ちませんが高速になると影響が大きいです。
    そこで工夫が必要になってきますね。
    ほんと、永山氏からは一言で難しい事が判明し助かりました。
    それも含めDirect access Portの記事を書き終えて公開しました。

    >Arduinoで50%のDuty比で1MHzを出したい
    Arduino UNOのスケッチだけで 1MHz は無理ですね。理由は最高が500KHzだからです。
    Arduino DUEならば可能ですね。理由は最高周波数出力が17MHzだからです。
    ただし、時間調整にdelayMicrosecondsは最小1usec(1MHz)と大きく使えません。
    代わりに何かの命令を挟んでdelayの変わりをさせれば細かな時間調整ができます。
    その為には、その命令がマシンサイクルでどのくらい時間を使用するか知る必要があります。
    Arduinoにおいてはマシンサイクルが解っていますので計算でできます。
    経験としてDUEの場合、ある命令を挟んで時間調整をして信号を出力した事があります。
    この時は、理論値に対し実際にそうなのか100MHz位のオシロスコープで確認する必要があります。
    また、高速になると出力波形が歪みますのでこれもオシロで観測する必要がありますね。
    最高速にすると三角波のようになってきます。

    >1MHzのクロックをESP8266でどう出力するのか。
    digitalWrite方式は無理です。理由は最高1083KHzだからです。
    Direct Access Port方式は、最高6MHzですから可能性があります。
    私の宿題としては、
    1. 無限ループをどのように作るか。
      LOOPは遅延がありますから、これを抜け出す方法を探がす必要がある。
      for(;;){} や while(1){} は、無限ループですが実際に動かすと3秒に1度 0.25sec間
      信号が途絶えます。、、これで難儀しています。
      goto文で回すと何故かしばらくして停止してしまいます。
      この3点の謎があります。
    2. 命令の時間が不明。マシンサイクルが解らない為にある1命令はどのくらいの時間を使うか不明です。
      簡単にはオシロスコープで見ながら命令を入れてdelayを作り希望の周波数を作るという事でしょうか。
      この件は、今試していますが、すんなりといかないのが現状です。

    参照例にあった海外の記事、MCP23S17に興味があります。
    つまり、ESP8266は使いこなすとI/Oが少ない為、いつかI/O Expanderが必要となります。
    どの記事もじっくり読みたいと思っています。記事の紹介をありがとうございました。

    macsbug

    2月 19, 2016 at 12:29 am

    • 詳細なコメントありがとうございます。
      このコメントだけですごいたくさんのことを学ばせていただいています。

      > Arduino UNOのスケッチだけで 1MHz は無理ですね。理由は最高が500KHzだからです。
      > Arduino DUEならば可能ですね。理由は最高周波数出力が17MHzだからです。

      なるほどです。

      > ただし、時間調整にdelayMicrosecondsは最小1usec(1MHz)と大きく使えません。

      そうなのですね。このあたりも知りませんでした。

      >>1MHzのクロックをESP8266でどう出力するのか。
      >digitalWrite方式は無理です。理由は最高1083KHzだからです。
      >Direct Access Port方式は、最高6MHzですから可能性があります。

      このあたりも勉強になります。

      さらに、宿題として色々調べられているのですね。

      > for(;;){} や while(1){} は、無限ループですが実際に動かすと3秒に1度 0.25sec間信号が途絶えます。、、これで難儀しています。

      結構トラップがあるのですね。

      ところで、時々出てくるオシロスコープの画像ですが、どのオシロスコープを使われているのでしょうか?
      100MHzとあるので、Analog Discovery(アナログ帯域5MHz)ではないとは思いますが。

      オシロスコープは買う予定なのですが、どんどん性能が更新されていくもののため、5年使えるオシロを5年程度で数回更新するか、10年以上使えるものを買ってしまうか悩みどころです。
      RIGOL 1054Zなどいくつか候補は考えています。

      7of9

      2月 19, 2016 at 3:32 am

      • 7of9さん、お返事ありがとうございます。
        高速にアクセスすると幾つかの問題が出てきて私の脳では限界があります。
        ESP8266で1MHz 50%duty を出力する 命題は、以下に投稿しましたので参考にしてください。
        スケッチがかなりダサくて恥ずかしいのですが参考になればと思います。
        ESP8266で1MHz 50%duty を出力する
        https://macsbug.wordpress.com/2016/02/19/esp8266で1mhzwo/
        ーーーーーーーーーーー
        オシロスコープは、Analog Discvery です。秋月で購入しました。マックかウインか使用アプリをよく見る事。
        現在、Analog Discvery Ver 2 が出ているので、いいな〜と、横目で見ています。
        >オシロスコープは買う予定なのですが、、、悩みどころです。
        >RIGOL 1054Zなどいくつか候補は考えています。
        実に同感です。私はかなり悩み動作周波数は低いですが利便性を考えAnalog Discveryにしました。
        使用してみると予想以上に使い勝手がよくRIGOL 買わなくて良かったという結果。
        どうしても周波数帯域の広い物が凄く気になるのですよね。
        ーーーーーーーーーーー
        使用は以下の感じです。
        コンピュター上で使えるので場所を取らない。
        波形等の記録が直ぐ取れる。
        画面の大きさはデイスプレーのサイズまで大きく出来る。
        27インチを使用していますが横いっぱいにするとデーターロガーみたいになります。
        この点はオシロでは大きくできない。寂しい画面になると思います。
        マウスでいろいろな設定ができる。オシロだと操作したりコンピュターをみたり煩雑だと思う。
        DigilentのWaveformというソフトを使用するのですが、この機能が凄いです。
        Scope,Waveform,Supplies,Meter,Logic,patterns,StaticsIO,NetWork,Spectrum,Scriptが出来るのです。
        Spectrumもできるのがこれまた凄い。上記の記事はSpectrumを使用し周波数の安定度が把握できました。
        他の特徴では信号発生器がついています。これは何か信号を必要とする場面でとても役に立ちます。
        今回の記事で信号を発生させプローブできちんと受かるかの準備をしてから始めました。
        仮想の装置を作れる訳で、いろいろなSGとか買う必要がなくなります。デジタルもできます。
        結果、RIGOL等のオシロより凄い事が解り便利にしています。

        これを使いこなしている友人が秋葉原にいます。
        参考になればよいかと思います。
        アナログ回路のおもちゃ箱
        http://designideas.cocolog-nifty.com

        補足:
        その後、最小時間の命令が判明しました。
        __asm__ __volatile__ (“nop”);
        です。
        1/80000000 second : 12.5 nsec を実現できます。

        macsbug

        2月 19, 2016 at 12:25 pm

  3. macsbugさん

    色々ありがとうございます。
    ESP8266の1MHz 50%duty出力はもうできたのですか。進展がやはり早いですね。

    Analog Discoveryを使われているとのこと、その使用感ありがとうございます。
    色々考えた上でAnalog Discovery 2 を注文しました。

    パソコンとの親和性が高いこと、記載されたWaveformやSpectrumなどの扱い、信号発生器、さらにロジックアナライザなどいいと思いました。

    > 今回の記事で信号を発生させプローブできちんと受かるかの準備をしてから始めました。
    > 仮想の装置を作れる訳で、いろいろなSGとか買う必要がなくなります。デジタルもできます。
    > 結果、RIGOL等のオシロより凄い事が解り便利にしています。

    確かにRIGOLなどのオシロと比べての利点も多そうです。

    ご友人のリンク情報もありがとうございます。
    さらに勉強になります。

    こちらのブログ(まだ少ししか読めてません)と合わせて少しずつ読んでいこうと思います。

    > その後、最小時間の命令が判明しました。
    > __asm__ __volatile__ (“nop”);
    > です。
    > 1/80000000 second : 12.5 nsec を実現できます。

    80MHzをきちんと出せているのですね。
    ハードウェアをパフォーマンスを最高に引き出せているのがすごいです。

    7of9

    2月 20, 2016 at 2:42 am

  4. […] SDカードの高速化が出来たとしても、ディスプレイ表示や、文字列スクロールを高速化するにはプログラムの改善が必要です。 私の自作ライブラリで、できるだけ高速化を試みて、ほぼ限界の速度が先の動画の中央部分でした。 そこで、ネットで検索したら、なんと、標準ライブラリの digitalWrite() が速度が遅いということがわかりました。 Arduino でもレジスタに直接命令すれば高速化が図れるということは知っていましたが、やはり ESP8266でもあったんです。 これについてとても素晴らしいブログをみつけてしまいました。 macsbugさんという方のこちらのサイトです。 こちら→ ESP8266 の GPIO 速度 […]

    • mgo-tecさん、初めまして。ブログを見に来ていただきありがとうございます。
      「電子工作と介護と生活と」から現在の「mgo-tec電子工作」まで素晴らしい記事を拝見させて頂いています。
      SDカードの高速化は素晴らしいですね。さらにOLEDのスクロールアップが出来たとは凄いです。
      確かに追求して行くと digitalWrite と digitalRrad の壁に突き当たります。
      これには Arduinoと同様にレジスタへの直接命令で高速化、さらにアセンブラとかマシン語とか難しくなりますね。

      リンクをありがとうございます。お互いに盛り上げましょう。

      画像や高速化に興味がある中で注目しているのが OLED 128×64のライブラリーとして
      squix78 の esp8266-oled-ssd1306 ライブラリー があります。
      https://github.com/squix78/esp8266-oled-ssd1306

      これはTFT Colorには対応していませんが Adafruitのライブラリーよりかなり高速ですしフォントもも奇麗です。
      今年、ver 2 になり更に高速化されました。
      この仕組みがなんであるかライブラリーの中を見ても私には理解できず課題になっています。
      C言語で高速化したとの事らしいですが.cppを読んでみてもレジスタへの直接命令がなくても高速なのです。
      SPI のライブラリーもあり、OLED 128×64 SPI でかなり高速に表示しています。

      mgo-tecさん、ESP8266 ( ESP-WROOM-02 ) SPI 通信の高速化に挑戦
      や TFT Colorの記事は素晴らしいです。
      特に Adafruit OLED SSD1351 SPI の高速化は動画を見てその速度に驚嘆しています。

      私の方はやっと 1.44″ 128X128 SPI Color TFT ST7735(278円)を始めました。
      今後ともmgo-tecさんの記事を参考にさせて頂きますね。

      macsbug

      10月 6, 2016 at 9:13 pm


コメントを残す