ESP32-WROOM-32 SPIFFS メモリサイズを大きくする方法

ESP32 ( ESP-WROOM-32 )

Partition Table 編集方法

では、SPIFFS メモリ領域のサイズアップするために、Partition Table の編集方法を説明します。

先ほどは default.csv ファイルをExcel で開きましたが、それで編集するといろいろとややこしくなる可能性があるので、私はテキストエディタで編集しました。
私の場合は Adobe Brackets を使用しています。
※メモ帳で編集しないでください。
文字コードがうまく変換されない場合があります。

テキストエディタで開くとこんな感じになります。

nvs や ota 領域は変えない方が無難なので、ユーザーが自由に変更しても問題ないのは上図の赤線で囲ったところになります。

SPIFFS 領域を大きくするということは、他のサイズが小さくなるということです。
総合計サイズが変更できない為です。

デフォルトの app 領域サイズを10進数に直すと、

0x140000 = 1,310,720 byte

となるので、1MB 近辺まで削減してみたいと思います。
スケッチ領域はそれくらいで十分かと思います。

ここでとても重要なことを言います。

app サイズ変更は必ず、0x10000 単位で変えること!

それ以外の数値で変更するとコンパイルエラーになります。
ちゃんとコンパイラメッセージで「 0x10000 単位で変えなさい」と警告が出るので分かると思います。

では、app 領域をそれぞれ、0x50000 = 327680 byte 減らしてみます。

すると、app0 のサイズは、

0x140000 – 0x50000 = 0xF0000

となります。

0xF0000 = 983,040 byte

なので、1MB を切ってしまいますが、私の目的とする東雲フォントを入れるためにはこれくらい減らさないとアップロードできませんでした。
でも、これで十分です。

16進数演算なので、ビギナーの方々には難解かもしれません。
その場合、Microsoft Excel 表を作って、
HEX2DEC関数
を使うと文字列の16進数を10進数に変換できるので便利です。
別のセルから16進数数値を参照する場合はそのセルの書式設定を文字列にすることが重要です。

逆に10進数を16進数に変換するには
DEC2HEX関数を使えば良いです。
Excelを使うと、こういう計算はとても重宝します。

次の app1 の Offset は app0 の Offset 0x10000 に app0 のサイズ 0xF0000 を足せばよいことになります。

0x10000 + 0xF0000 = 0x100000

こんな感じでそれぞれ計算していきます。
eeprom のサイズは変更しません。

最後の spiffs のサイズは、app0 と app1 で減らしたサイズを足せば、OKです。
結果、下図の様になります。

ここでもう一つ注意していただきたいのは、総合計サイズは変えられないということがポイントです。
総合計サイズは、Size の項目を足しただけはダメです。
それに加えて、ブートローダー分の 0x9000 を考慮しなければなりません。
つまり、nvs の Offset 分ですね。

よって、総合計は

0x9000 +
0x5000 +
0xF0000 +
0xF0000 +
0x1000 +
0x20F000
= 0x400000 = 4,194,304 byte

となります。
パーティションテーブルを変更しても、どこか計算間違いをして、この総合計が変わってしまうとちゃんと動作しませんのでご注意ください
私はこれで何度も失敗して無駄な時間を費やしてしまいました。

変更したら、必ずUTF-8 テキスト形式で保存してください。

その後、Arduino IDE を必ず再起動してください

SPIFFS アップローダープラグインでデータをアップロードする

では、Arduino – ESP32 用の SPIFFS アップローダープラグインを使って、ちょっと大きめのデータを ESP-WROOM-32 内蔵 Flash にアップロードしてみます。
その方法は以下の記事を参照してください。

ESP-WROOM-32 ( ESP32 ) SPIFFS アップローダープラグインの使い方

私個人の目標である、東雲フォント他、以下のファイルをアップロードしてみました。

Windows 10 のエクスプローラーのプロパティで見たファイルサイズは以下の通りです。
「ディスク上のサイズ」指標ではなく、「サイズ」指標です。

shnm8x16.bdf 29,124 byte
MyFont.fnt 1,184 byte
shnmk16.bdf 1,135,668 byte
Utf8Sjis.tbl 240, 878 byte
4X8.FNT 2,065 byte
mgotec48.FNT 2,065 byte
MSKG13KU.FNT 60,288 byte
—————————————–
合計 1,471,272 byte

SPIFFS アップロードしたファイルのサイズ確認

では、アップロードしたファイルのサイズを確認してみます。

確認するスケッチ例は以下です。
正確な値を示すかどうかは正直分かりません。
Arduino – ESP32 の場合、IDE の Flashサイズ設定によって Chip Size は変わりますのでご注意ください。
Flash サイズは 4MB にしておいてください。

【ソースコード】 (※無保証 ※PCの場合、ダブルクリックすればコード全体を選択できます)

#include "FS.h"
#include <SPIFFS.h>

//********************************************************************
void setup() {  
  Serial.begin(115200);
  Serial.println("----------------------");

  if (!SPIFFS.begin()) {
    Serial.println("SPIFFS Mount Failed");
    return;
  }

  Serial.printf("IDE Flash Chip Size = %d byte\r\n", ESP.getFlashChipSize());
  Serial.printf("SPIFFS Total Size = %d byte\r\n", SPIFFS.totalBytes());
  Serial.printf("SPIFFS Used Size = %d byte\r\n", SPIFFS.usedBytes());

  delay(100);

  //deleteFile(SPIFFS, "/xxx.txt");

  listDir(SPIFFS, "/", 0); //SPIFFSフラッシュ ルートのファイルリスト表示

  SPIFFS.end();
}
//********************************************************************
void loop() {

}
//********************************************************************
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
    Serial.printf("Listing directory: %s\n", dirname);

    File root = fs.open(dirname);
    if(!root){
        Serial.println("Failed to open directory");
        return;
    }
    if(!root.isDirectory()){
        Serial.println("Not a directory");
        return;
    }

    File file = root.openNextFile();
    while(file){
        if(file.isDirectory()){
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if(levels){
                listDir(fs, file.name(), levels -1);
            }
        } else {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("  SIZE: ");
            Serial.println(file.size());
        }
        file = root.openNextFile();
    }
}
//********************************************************************
void deleteFile(fs::FS &fs, const char * path) {
  Serial.printf("Deleting file: %s\n", path);
  if (fs.remove(path)) {
    Serial.println("File deleted");
  } else {
    Serial.println("Delete failed");
  }
}

listDir関数はサンプルスケッチを流用しています。
また、deleteFile関数は、アップロードしたファイルを消したい場合に使って下さい。

では、これをコンパイル書き込み実行してみます。
すると、シリアルモニターには下図の様に表示されました。

Windows10 で確認したファイルサイズとビンゴ! 同じでした。

ただ、合計サイズと Used Size と異なりますね。
これの原因はSPIFFSライブラリの関数値なので良く分かりませんが、いずれにせよ全てアップロードできたので、私的にヨシとします。

Total Size が 1.9MB となっていますが、実際のところここまでアップロードできません。
なぜか、それよりもかなり少ないです。

前項で、app0 と app1 のサイズを0x50000 byte 減らしましたが、0x40000 の場合は全部アップロードできませんでした。
ということで、SPIFFS Total Size より少なめのサイズが実際アップロード可能なサイズということを頭に入れておいてください。

因みに、16×16 pixel 日本語 東雲フォントをスクロールさせた動画は以下のようになりました。
SPIFFS から読み出した場合と、micro SDHC カードから読み出した場合を比較しています。
micro SDHC は 24MHz で読み出しています。

OLED は SPI通信の SSD1331 を使っています。

お分かりのとおり、micro SDHC カードの方が圧倒的にスムースですね。
ということは、SPIFFS ファイルシステムの場合は、ランダム読み取りは遅いということです。
この速さは、ESP-WROOM-02 ( ESP8266 )の場合と殆ど同じでしたね。

これを速くする方法は今のところ分かりません。

まとめ

以上、Arduino core for ESP32 の SPIFFS ファイルサイズアップの方法でした。

今回の件は、コメント欄の Tomさんによる投稿が無かったら、ずーっと分からないままだったと思います。
本当に Tomさん、ありがとうございました。
m(_ _)m

この情報で、皆さんの ESP32 開発が役立ってくれれば幸いです。

いずれ、ESP8266 のように、Arduino IDE のツールメニューでこのパーティションテーブル変更が簡単にできる日が来ると思います。

ただ、このようにパーティションテーブルを自分自身で変更した方が、内蔵 Flash メモリの構造が理解できて、とても勉強になると思いますよ。

SPIFFS は読み取り速度が遅いのですが、用途を考えて使用すれば、いろいろと使えると思います。

以上、今回はここまでです。

ではまた・・・。

コメント

  1. juchang より:

    mgo-tec 様

    新年明けましておめでとうございます。
    新年早々の新作発表に大変感激致しております。
    今回は SPIFFS 領域のサイズアップが必要とのことで本ページに取り組んでいますが、shnm8x16.bdf と shnmk16.bdf (いずれも SDcard_sample_filses より取り込み) のアップロードができません。
    SPIFFS のサイズアップは、シリアルモニタで確認済みです。
    4×8.FNT 、Utf8Sjis.tbl、mgotec48.FNT、MSKG13KU.FNT のアップロードは、シリアルモニタで確認できます。
    エラー表示:
    UnicodeDecodeError: ‘ascil’ code can’t decode byte 0xef in position 0: ordinalnot in range(128)
    Web で調べると、「 str 型と unicode 型を混ぜるな!」との事のようですが、初心者の私にはどこをどう直せばよいのか見当もつきません。
    新年早々で恐縮です、何かお知恵がありましたらアドバイスの程お願いいたします。

    • mgo-tec mgo-tec より:

      juchangさん

      あけましておめでとうございます。
      こちらこそ、本年も当ブログをご覧いただき、ありがとうございます。
      m(_ _)m

      エラーメッセージの件ですが、以前と同じメッセージですね。
      私も再現しようとしたのですが、どうしてもそういうエラーが出ません。
      謎ですね。
      パーティションテーブルも含めたソースコードをテキストエディタで編集した場合、Unicodeで保存してしまった可能性があるかもしれませんね。
      UTF-8形式で保存すれば直るかもしれません。
      また、ブラウザからソースコードをコピペする場合、ブラウザの設定画面で、文字コードをUTF-8に統一すると良いかもしれません。

      でも、そのエラーメッセージはSPIFFSファイルをプラグインアップローダーでアップロードした時に出るメッセージですよね。
      そうなると謎です。
      Arduino IDE の「ツール」メニューの「Flash Size」を2MB にしてしまっているかと思ってやってみたのですが、それでもそういうエラーメッセージは出ませんでした。

      あと考えられるのは、パーティションテーブルをテキストエディタで編集する時に、ブログ記事の文章中から数値をコピペしてしまうと出てしまうかもしれませんね。
      パーティションテーブルのコピペ用テキストはこのブログ記事には載せていないので大丈夫だとは思ったのですが・・・。
      あれは、テキストエディタでご自分で半角数値を入力しなければいけません。
      あと、その中に全角が混じっている可能性がありますのでご注意ください。
      特に、エラーメッセージにある、「0xEF」というのは、半角文字では読み取れないということを意味しています。
      半角英数値は ASCIIコードの表現できる文字コードです。
      パーティションテーブルなどは半角英数値で読み取るので、0xEF という値はASCIIコードにありません。
      恐らく、全角カンマ「,」などは、UTF-8コードで、0xEFBC8C なので、最初のビット 0xEF を読み取ってしまって、エラーが出ている可能性があります。
      文字列意外のプログラムは全て半角英数値で入力しなければなりません。

      以上、それくらいでしょうか・・・。
      いずれにしても、そのエラーメッセージは文字が何らかの不明な文字コードになってしまっている可能性が大きいです。
      そのエラーメッセージの前に他のメッセージはありませんでしたか?

  2. juchang より:

    mgo-tec 様

    いつも初歩的なミスでご迷惑をお掛けし申し訳ありません。
    パーティションテーブルの編集で、Windows メモ帳を使っていたのが原因でした。
    テキストに忠実に実行しようと、Adobe Brackets をインストールし、編集を行ったところ、error 表示が無くなり、「フルカラー有機 EL に倍角日本語フォントを縦横でスクロールさせてみた」を完成することができました。
    ありがとうございました。
    今後ともご指導の程よろしくお願い致します。

    • mgo-tec mgo-tec より:

      動いて良かったですね。
      メモ帳でも、全角、半角と改行を注意すれば問題無いと思います。
      ただ、やっぱり使いにくいので、ちゃんとしたテキストエディタが正解ですね。

  3. Deco より:

    mgo-tec様、はじめまして。
    メモリサイズのことで調べてたら辿り着きました。
    まったくの初心者の私でも参考になる数々の記事に感謝いたします。

    本題ですが、default.csvを開くと、eepromの項目がありませんでした。
    こんな感じです。
    # Name, Type, SubType, Offset, Size, Flags
    nvs, data, nvs, 0x9000, 0x5000,
    otadata, data, ota, 0xe000, 0x2000,
    app0, app, ota_0, 0x10000, 0x140000,
    app1, app, ota_1, 0x150000,0x140000,
    spiffs, data, spiffs, 0x290000,0x170000,

    eepromがない場合、spiffsのOffsetはどうなるのでしょうか?
    お忙しいところ恐縮ですが、よろしくお願い致します。

    • mgo-tec mgo-tec より:

      Decoさん

      記事をご覧いただきありがとうございます。
      ただ、この記事は3年以上前のもので、当時は動きましたが今の環境では全く異なると思ってください。

      2021/1/21時点のArduino core for the ESP32のstable版最新はver 1.0.4 です。
      この場合、SPIFFSサイズを大きくするならば、Arduino IDE の「ツール」メニューで、
      「Partition Scheme」
      という項目があり、そこで変更する方が確実に安全に変更できます。

      DecoさんのSPIFFSのSizeが、0x170000 とあり、これは16進数表記なので、10進数に直すと、
      0x170000 = 1,507,328 byte = 約1.5MB
      となっています。
      これは、Partition Scheme設定でデフォルト設定だと思いますので、例えば
      No OTA (2MB APP/2MB SPIFFS)
      にすると、SPIFFSを2MBまでサイズアップできます。
      こちらで設定した方が絶対安全で、お勧めです。

      因みに、EEPROMが無い場合、app1のOFFSET値にSize値を足した合計値がSPIFFSのOFFSET値になると思います。
      16進数計算なので10進数計算と異なることに注意すれば良いのではないかと思います。
      ただ、これで正常に動くか分かりませんし、場合によってはフラッシュメモリを破壊してしまう場合も有りえます。

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