ESP-SPIFFS

最終修正日:2020/10/19

ESP32のモジュールには基本4MBのフラッシュメモリがSPI接続されています。他のCPUに比べ大きなプログラムを書き込む事が可能なMCUで有ることは明らかなのですが、実際にビルドすると、

最大1310720バイトのフラッシュメモリのうち、スケッチが760038バイト(57%)を使っています。

書き込み可能なプログラム領域が4MBではなく1.3MBとなっています。これは環境側で用意しているメモリマップに割り当てている情報に従っています。
シリアルから書込と『APP0』の領域に書き込まれ、0x140000=1310720が最大領域になります。
メモリマップを見ると『APP1』という領域があります。これがOTAでプログラムが書き込まれるときに使用されるもう一つの領域になります。OTAで書き込まれるとbootアドレスが変更になります。OTAを使わないのならばメモリマップを独自に弄ってプログラムサイズを更に大きくする事も可能です。

4MBの内まだ1.5MBもの領域が残っています。この領域がSPIFFS(SPI Flash File System)です。
ESP32のようにはじめから無線LAN/BLEが搭載されていることもあり、ファイルシステムをモジュール内に保有する仕組みが用意されているのです。
WebServerを構築したときのHTMLファイルを格納したり、取得データのロギングに使用したり出来ます。ただ、フラッシュは書込回数に上限を持ちますし、読書込時間がそこそこ掛かるので、適用方法には留意が必要です。

以下のようなArduinoIDEのソース環境で、『ESP32 SketchData Upload』を実行して、“data”フォルダ内の情報をUploadし、スケッチをビルド後書込と指定されたURLにアクセスする事でブラウザにSPIFFSに記載したHTML内容を表示することが出来ました。

Upload実行時にはシリアルモニタは閉じてください】

    シリアル接続した状態で“data”フォルダ内を一気にUploadするわけですが、このときにシリアルモニタが開いていると次のようなエラーが出て実行出来ません。

esptool.py v2.6
Serial port COM10
Traceback (most recent call last):
  File "esptool.py", line 2959, in <module>
  File "esptool.py", line 2952, in _main
  File "esptool.py", line 2652, in main
  File "esptool.py", line 222, in __init__
  File "site-packages\serial\__init__.py", line 88, in serial_for_url
  File "site-packages\serial\serialwin32.py", line 62, in open
serial.serialutil.SerialException: could not open port 'COM10': WindowsError(5, '\x83A\x83N\x83Z\x83X\x82\xaa\x8b\x91\x94\xdb\x82\xb3\x82\xea\x82\xdc\x82\xb5\x82\xbd\x81B')
Failed to execute script esptool
SPIFFS Upload failed!

ちょっと面倒なのは、“data”フォルダ内のファイル一つ一つに対してアクションを定義しておかないと実行出来ない事でしょうか?つまり、“index.htm”を読み込んだとき、そのindex.htm内にリンクされている画像ファイル等も一つ一つアクションの記述が必要で、そうしないと期待した結果になりません。

実際に実行するとこんな結果になります。

各画像に対して、以下のような記述が為されていないと、画像が抜けた表示となってしまいます。

 webServer.on("/img/Vector.gif", HTTP_GET, [](AsyncWebServerRequest *request){
                request->send(SPIFFS, "/img/Vector.gif","image/gif");

以下がサンプルスケッチになります。幾つかライブラリを追加して戴く必要があります。

  • https://github.com/me-no-dev/ESPAsyncWebServer
  • “arduino_secrets.h” はライブラリでは無く

    const char* ssid     = SECRET_SSID;
    const char* password = SECRET_PASS;
    
    #define SECRET_SSID ""
    #define SECRET_PASS ""

    のようにLocalな情報を隠匿するための仕組みです。参照:https://forum.arduino.cc/index.php?topic=678870.0

    /*
     * 20200901 T.Wanibe SPIFFSの勉強
     * 最大1310720バイトのフラッシュメモリのうち、スケッチが759662バイト(57%)を使っています。
     * 最大327680バイトのRAMのうち、グローバル変数が39456バイト(12%)を使っていて、ローカル変数で288224バイト使うことができます。
     */
    #include <WiFi.h>
    #include <FS.h>
    #include <ESPAsyncWebServer.h>
    #include <SPIFFS.h>
    #include "arduino_secrets.h"
    #define LED_PIN         13                              // LED
    #define HTTPport        80                              // HTTPport番号
    bool ledFlag = true;                                    // LED制御フラグ
    //Wi-Fi設定
    const char* ssid     = SECRET_SSID;
    const char* password = SECRET_PASS;
    IPAddress ip(192, 168, 0, 99);                          // IPアドレス(本機が利用するIP)
    IPAddress gateway(192, 168, 0, 1);                      // デフォルトゲートウェイ
    IPAddress subnet(255, 255, 255, 0);                     // サブネットマスク
    // WebServerを定義(ポート80番を使用)
    AsyncWebServer webServer ( HTTPport );
    // 実際のピン出力によってhtmlファイル内のSTATEの文字を変える
    //-----------------
    void handle_NotFound(AsyncWebServerRequest *request)
    {
             //request->send(404, "text/plain", "Not found");
            request->send(SPIFFS, "/404.htm","text/html");
            Serial.println(F("404"));
    }
    //-----------------
    void setup(void) {
            // Serial設定
            Serial.begin(115200);
            // LED設定
            pinMode ( LED_PIN, OUTPUT );
            // 無線Wi-Fi接続
            // SPIFFSのセットアップ
            if(!SPIFFS.begin(true)){
                    Serial.println(F("An Error has occurred while mounting SPIFFS"));
                    return;
            }
            WiFi.config( ip, gateway, subnet );
            WiFi.begin ( ssid, password );
            // Wi-Fi接続処理(接続するまで無限ループ)
            while ( WiFi.status() != WL_CONNECTED ) {
                    // LEDを1秒毎に点滅する
                    ledFlag = !ledFlag;
                    digitalWrite(LED_PIN, ledFlag);
                    // 1秒間Wait
                    delay ( 1000 );
                    Serial.print (F("."));
            }
            // Wi-Fi接続できたのでシリアルモニターにIPアドレス表示
            Serial.print ( F("Wi-Fi Connected! IP address: " ));
            Serial.println ( WiFi.localIP() );
            // LED点灯(Wi-Fi接続状態)
            digitalWrite ( LED_PIN, true );
            // WebServerの受信処理"/"を設定
            webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
                    // HTMLを返答する
                    request->send ( 200, "text/html", "Hello World!" );
                    Serial.println ( "send html" );
            });
            // サーバーのルートディレクトリにアクセスされた時のレスポンス
            webServer.on("/index.htm", HTTP_GET, [](AsyncWebServerRequest *request){
                    request->send(SPIFFS, "/index.htm", "text/html");
            });
            webServer.on("/index.html", HTTP_GET, [](AsyncWebServerRequest *request){
                    request->send(SPIFFS, "/index.htm","text/html");
            });
            webServer.on("/img/Vector.gif", HTTP_GET, [](AsyncWebServerRequest *request){
                    request->send(SPIFFS, "/img/Vector.gif","image/gif");
            });
            // 上記以外アクセス時に handleConfirmFile() を実行
            webServer.onNotFound(handle_NotFound);
            // WebServer起動処理
            webServer.begin();
            Serial.println ( F("Web server started" ));
    }
    //-----------------
    void loop(void){
            //ESPAsyncWebServerを採用しているため、プログラム上は常にclientを監視しなくてもよくなります。
    }

    WebServer.hを使用して同期型のサーバ構築したとき、APIが異なるためSPIFFSの使い方を工夫する必要がありました。


    戯言(nonsense)に戻る


    問い合わせ頁の表示


    免責事項

    本ソフトウエアは、あなたに対して何も保証しません。本ソフトウエアの関係者(他の利用者も含む)は、あなたに対して一切責任を負いません。
    あなたが、本ソフトウエアを利用(コンパイル後の再利用など全てを含む)する場合は、自己責任で行う必要があります。

    本ソフトウエアの著作権はToolsBoxに帰属します。
    本ソフトウエアをご利用の結果生じた損害について、ToolsBoxは一切責任を負いません。
    ToolsBoxはコンテンツとして提供する全ての文章、画像等について、内容の合法性・正確性・安全性等、において最善の注意をし、作成していますが、保証するものではありません。
    ToolsBoxはリンクをしている外部サイトについては、何ら保証しません。
    ToolsBoxは事前の予告無く、本ソフトウエアの開発・提供を中止する可能性があります。

    商標・登録商標

    Microsoft、Windows、WindowsNTは米国Microsoft Corporationの米国およびその他の国における登録商標です。
    Windows Vista、Windows XPは、米国Microsoft Corporation.の商品名称です。
    LabVIEW、National Instruments、NI、ni.comはNational Instrumentsの登録商標です。
    I2Cは、NXP Semiconductors社の登録商標です。
    その他の企業名ならびに製品名は、それぞれの会社の商標もしくは登録商標です。
    すべての商標および登録商標は、それぞれの所有者に帰属します。