ESP32のパーティション設定

概要

arduino-esp32のv3.0系調査でパーティションまわりを調べてみました。

パーティションとは?

ESP32シリーズは2MBから32MBまでのフラッシュメモリを搭載しており、アプリやファイル保存領域として利用することができます。

Partition Tables - ESP32 - — ESP-IDF Programming Guide v5.4.1 documentation

上記に詳しい説明があります。

# 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,0x160000,
coredump, data, coredump,0x3F0000,0x10000,

default.csvのパーティションは上記になります。

項目概要
Name説明用の文字列
Typeappとdataがある
SubType実際の種類を表す
Offset配置場所だが空でも自動計算可能
Size割当られた大きさ
Flags暗号化などのフラグ

Nameは見た目の名前で説明以上の意味はありません。Typeはappとdataがありますが、SubTypeを見れば区別が可能です。重要なのはSubTypeとSizeになります。

起動にかかわるSubTypeの種類

coredump(data)

ハングアップした場合などのcoredumpを保存する領域です。基本的には64KB確保してありますが、USBストレージとして認識して、ファームウエアのファイルをコピーして更新を行うTinyUF2では確保されていませんでした。

ota(data)

Over The Air(OTA)でネットワーク経由でファームウエアを更新するときの管理領域です。次にどの領域から起動するのかを保存してあります。この領域が存在しな場合のみfactoryから起動します。

factory(app)

デフォルトで起動するファームウエアを保存する領域です。しかしながら実際のところあまり利用されていません。

ota_0 ~ ota_15(app)

ファームウエアが保存される領域です。factoryの変わりにota_0が利用されることが多いです。2つ以上のota_app領域がある場合には実際にOTA経由でファームウエアの更新が可能です。

test(app)

標準構成で利用されることはありませんが、ota_app領域もfactory領域もない場合にはtestから起動されます。また、カスタムブートローダーを使うことで特定のGPIOの状態をみて起動時にtestから起動するように構成も可能です。主にファームウエアをSDカードやOTA経由で強制アップデートさせる場合などに利用可能です。

その他のデータ用領域

nvs(data)

キーバリューストアでデータを保存する領域です。最後に接続したWi-Fiアクセスポイント情報なども保存されています。通常は20KBの領域が割り当てられていますがESP RainMakerやTinyUF2などではもう少し大きめに確保されています。

spiffs(data)

SPI接続されている内蔵フラッシュをファイルシステムとして利用する領域です。SDカードなどと同じようにファイルの保存が可能になります。Wi-Fi接続時はWebDAVやFTPプロトコルなどを利用してパソコンとファイルのやり取りなどが可能です。

fat(data)

spiffsと同じく内蔵フラッシュを利用したファイルシステムなのですがSPIFFSとしてではなく、FatFsとしてフォーマットされます。

littlefs(data)

arduiono-esp32だとデフォルトで設定はされていませんが、同じようにLittleFSでフォーマットされている領域です。ただしspiffsでも動きますので通常はspiffsを利用します。

efuse(data)

書き込み回数に制限があるeFuse領域をエミュレートする領域です。通常は利用されませんが、この領域を作成することで実際のeFuseに書き込みをすることなくeFuse周りの動作確認が可能になります。

起動領域

ざっくりですが上記になります。領域が壊れていた場合などはもう少し複雑なチェックが入っています。またfactoryはあまり利用されておらず、OTAを使わない場合でもota_0から起動するので、ota_0にファームウエアを保存することが多いようです。

OTAを利用する場合には最低でも2つのota_app領域が必要です。現在起動している領域には更新できなくなっているため、2つの場合には交互に更新していく形となります。また、あまり利用はされていませんが、複数の領域に別のファームウエアを保存しておき、ota領域を書き換えることで次回起動するファームウエアを指定することも可能です。

データ領域

コンフィグ領域はnvs

過去はEEPROM領域もありましたが、現在はnvs領域に統一されています。キーバリューストア形式でデータを保存可能ですので、あまり大きくない設定データはnvs領域に保存してください。

内蔵フラッシュ

一年以上前に計測したデータなので現状と違うかもしれませんが過去にファイルシステム別にベンチマークを取っていました。これまでSPIFFSがよく使われてきましたがパフォーマンスはあまり良くありません。書き込みはLittleFSが早く、バランス的にはFatFsが優秀です。SPIFFSとLittleFSは同じパーティション領域で利用できるのですが、FatFsは専用領域を設定する必要があるので注意してください。

外部ストレージ

内蔵フラッシュは余っている領域にファイルを保存するので使いやすいのですが、外部からのファイルアクセスが難しいです。はやりSDカードなどを利用した外部ストレージが便利なときも多いはずです。

ただ内蔵ストレージでもWi-Fiを利用してWebDavサーバーのライブラリを利用すればWindowsのエクスプローラーなどから直接ファイルのアップロードやダウンロードが可能になります。

パーティションの選択方法

filenametotalfactoryota_0ota_1spiffsfat
minimal.csv2MB0KB1,280KB0KB640KB0KB
rainmaker.csv4MB0KB1,920KB1,920KB0KB0KB
default.csv4MB0KB1,280KB1,280KB1,408KB0KB
default_ffat.csv4MB0KB1,280KB1,280KB0KB1,408KB
huge_app.csv4MB0KB3,072KB0KB896KB0KB
min_spiffs.csv4MB0KB1,920KB1,920KB128KB0KB
no_fs.csv4MB0KB1,984KB1,984KB0KB0KB
no_ota.csv4MB0KB2,048KB0KB1,920KB0KB
noota_3g.csv4MB0KB1,024KB0KB2,944KB0KB
noota_3gffat.csv4MB0KB1,024KB0KB0KB2,944KB
noota_ffat.csv4MB0KB2,048KB0KB0KB1,920KB
zigbee.csv4MB0KB1,280KB1,280KB1,388KB4KB
zigbee_zczr.csv4MB0KB1,280KB1,280KB4KB4KB
default_8MB.csv8MB0KB3,264KB3,264KB1,536KB0KB
default_ffat_8MB.csv8MB0KB3,264KB3,264KB0KB1,536KB
large_ffat_8MB.csv8MB0KB1,280KB1,280KB0KB5,504KB
large_spiffs_8MB.csv8MB0KB1,280KB1,280KB5,504KB0KB
max_app_8MB.csv8MB8,064KB0KB0KB0KB0KB
app3M_fat9M_16MB.csv16MB0KB3,072KB3,072KB0KB10,112KB
app3M_fat9M
_fact512k_16MB.csv
16MB512KB3,072KB3,072KB0KB9,600KB
app3M_spiffs9M
_fact512k_16MB.csv
16MB512KB3,072KB3,072KB9,600KB0KB
default_16MB.csv16MB0KB6,400KB6,400KB3,456KB0KB
esp_sr_16.csv16MB0KB3,072KB3,072KB2,944KB0KB
ffat.csv16MB0KB2,048KB2,048KB0KB12,160KB
large_spiffs_16MB.csv16MB0KB4,608KB4,608KB7,040KB0KB
m5stack_partitions_16MB
_factory_4_apps.csv
16MB960KB3,072KB3,072KB3,008KB0KB
m5stack_partitions_16MB
_factory_6_apps.csv
16MB960KB2,048KB2,048KB3,008KB0KB
large_fat_32MB.csv32MB0KB4,608KB4,608KB0KB23,424KB
large_littlefs_32MB.csv32MB0KB4,608KB4,608KB23,424KB0KB

一部特殊なのを除いていますが上記のパーティションがArduino IDEからは選択可能です。まずはボードに搭載されているフラッシュメモリの容量を確認し、その中から選択することになります。

filenametotalfactoryota_0ota_1spiffs
minimal.csv2MB0KB1,280KB0KB640KB
default.csv4MB0KB1,280KB1,280KB1,408KB
default_8MB.csv8MB0KB3,264KB3,264KB1,536KB
default_16MB.csv16MB0KB6,400KB6,400KB3,456KB

デフォルト系の場合上記の中からフラッシュの容量に応じて選択をします。どれもfactoryは利用しておらず、ota_0領域が設定されています。minimalはota_1がないので実際のOTAは利用できませんが、それ以外のものは利用可能です。

気をつけないといけないのはdefaultのファームウエアサイズが1,280KBなことです。Wi-FiとBLEを利用するとおそらくはそれ以上の容量になりファームウエアを転送できなくなります。その場合にはよいファームウエア容量の大きなパーティションを選択する必要があります。

filenametotalota_0ota_1spiffs備考
default.csv4MB1,280KB1,280KB1,408KB標準。BLEだと容量が足りない
huge_app.csv4MB3,072KB0KB896KBOTAをなくしてspiffsを減らす
min_spiffs.csv4MB1,920KB1,920KB128KBspiffsを減らす
no_fs.csv4MB1,984KB1,984KB0KBspiffsを無くした
no_ota.csv4MB2,048KB0KB1,920KBOTAをなくしてspiffsを増やす

4MBの代表的なパーティションになります。ファームウエア領域を増やすためには他の容量を減らす必要があります。基本的にはOTAを諦めるか、spiffsの容量を減らすかになります。

カスタム設定の方法

arduino-esp32/libraries/LittleFS/examples/LITTLEFS_test at master · espressif/arduino-esp32
Arduino core for the ESP32. Contribute to espressif/arduino-esp32 development by creating an account on GitHub.

スケッチ例のLittleFSの中にあるLITTLEFS_testではカスタム設定のパーティションを利用しています。

まずパーティション選択で一番下にあるCustomを選択します。これを選択した場合にはプロジェクトの中にあるpartitions.csvを利用するようになっています。

# Name,   Type, SubType, Offset,  Size, Flags
nvs,      data, nvs,     0x9000,  0x5000,
otadata,  data, ota,     0xe000,  0x2000,
app0,     app,  ota_0,   0x10000, 0x100000,
app1,     app,  ota_1,           ,0x100000,
spiffs,   data, spiffs,          ,0x1D0000,
part2,    data, spiffs,          ,0x20000,
#1048576

上記がpartitions.csvです。1MBぐらいのota_0とota_1があるのでOTA対応ですね。そしてspiffs領域が2つあります。コードをみるとあまり利用することはないのですが、1個目のspiffsが通常マウントされるはずですが、名前指定で2個目以降のspiffsをマウントすることもできるようです。

仕組み

ちなみにこのCustomパーティションはかなり強引な方法で実現しています。Arduino IDEの設定ファイルはif文がないので、通常はこのような動作はできないはずです。

# Check if custom partitions exist: source > variant > build.partitions
recipe.hooks.prebuild.1.pattern=/usr/bin/env bash -c "[ ! -f "{build.source.path}"/partitions.csv ] || cp -f "{build.source.path}"/partitions.csv "{build.path}"/partitions.csv"
recipe.hooks.prebuild.2.pattern=/usr/bin/env bash -c "[ -f "{build.path}"/partitions.csv ] || [ ! -f "{build.variant.path}"/{build.custom_partitions}.csv ] || cp "{build.variant.path}"/{build.custom_partitions}.csv "{build.path}"/partitions.csv"
recipe.hooks.prebuild.3.pattern=/usr/bin/env bash -c "[ -f "{build.path}"/partitions.csv ] || cp "{runtime.platform.path}"/tools/partitions/{build.partitions}.csv "{build.path}"/partitions.csv"

platform.txtの該当部分です。ワンライナーのコマンドを実行して、優先順位順にファイルをさがしてきているようでした。

  1. プロジェクトフォルダにあるpartitions.csv
  2. {build.variant.path}”/{build.custom_partitions}.csv
  3. {runtime.platform.path}”/tools/partitions/{build.partitions}.csv

上記の順に探していました。partitions.csvを設置するとIDEでどの項目を選択していてもカスタムパーティションが選択されていそうです。2はボード特有のパーティション設定になります。

XIAO ESP32-S3の「TinyUF2 8MB (2MB APP/3.7MB FFAT)」などは2のボード特有の設定でした。ブートローダーも通常のものからTinyUF2用のものが設定されているようです。

3はデフォルトの共通設定のパーティションからになります。

まとめ

8MB以上のボードの場合にはあまりパーティションは変更しませんが、4MBのボードの場合にはBLE利用時にどうしても容量が足りなくなると思います。OTAは便利なのですが、利用していないことも多いと思いますので、その場合にはno_otaなどを選択することで転送できるファームウエアの容量を大きくすることが可能です。

コメント