概要
arduino-esp32のv3.0系調査でパーティションまわりを調べてみました。
パーティションとは?
ESP32シリーズは2MBから32MBまでのフラッシュメモリを搭載しており、アプリやファイル保存領域として利用することができます。
上記に詳しい説明があります。
# 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 | 説明用の文字列 |
| Type | appと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のエクスプローラーなどから直接ファイルのアップロードやダウンロードが可能になります。
パーティションの選択方法
| filename | total | factory | ota_0 | ota_1 | spiffs | fat |
|---|---|---|---|---|---|---|
| minimal.csv | 2MB | 0KB | 1,280KB | 0KB | 640KB | 0KB |
| rainmaker.csv | 4MB | 0KB | 1,920KB | 1,920KB | 0KB | 0KB |
| default.csv | 4MB | 0KB | 1,280KB | 1,280KB | 1,408KB | 0KB |
| default_ffat.csv | 4MB | 0KB | 1,280KB | 1,280KB | 0KB | 1,408KB |
| huge_app.csv | 4MB | 0KB | 3,072KB | 0KB | 896KB | 0KB |
| min_spiffs.csv | 4MB | 0KB | 1,920KB | 1,920KB | 128KB | 0KB |
| no_fs.csv | 4MB | 0KB | 1,984KB | 1,984KB | 0KB | 0KB |
| no_ota.csv | 4MB | 0KB | 2,048KB | 0KB | 1,920KB | 0KB |
| noota_3g.csv | 4MB | 0KB | 1,024KB | 0KB | 2,944KB | 0KB |
| noota_3gffat.csv | 4MB | 0KB | 1,024KB | 0KB | 0KB | 2,944KB |
| noota_ffat.csv | 4MB | 0KB | 2,048KB | 0KB | 0KB | 1,920KB |
| zigbee.csv | 4MB | 0KB | 1,280KB | 1,280KB | 1,388KB | 4KB |
| zigbee_zczr.csv | 4MB | 0KB | 1,280KB | 1,280KB | 4KB | 4KB |
| default_8MB.csv | 8MB | 0KB | 3,264KB | 3,264KB | 1,536KB | 0KB |
| default_ffat_8MB.csv | 8MB | 0KB | 3,264KB | 3,264KB | 0KB | 1,536KB |
| large_ffat_8MB.csv | 8MB | 0KB | 1,280KB | 1,280KB | 0KB | 5,504KB |
| large_spiffs_8MB.csv | 8MB | 0KB | 1,280KB | 1,280KB | 5,504KB | 0KB |
| max_app_8MB.csv | 8MB | 8,064KB | 0KB | 0KB | 0KB | 0KB |
| app3M_fat9M_16MB.csv | 16MB | 0KB | 3,072KB | 3,072KB | 0KB | 10,112KB |
| app3M_fat9M _fact512k_16MB.csv | 16MB | 512KB | 3,072KB | 3,072KB | 0KB | 9,600KB |
| app3M_spiffs9M _fact512k_16MB.csv | 16MB | 512KB | 3,072KB | 3,072KB | 9,600KB | 0KB |
| default_16MB.csv | 16MB | 0KB | 6,400KB | 6,400KB | 3,456KB | 0KB |
| esp_sr_16.csv | 16MB | 0KB | 3,072KB | 3,072KB | 2,944KB | 0KB |
| ffat.csv | 16MB | 0KB | 2,048KB | 2,048KB | 0KB | 12,160KB |
| large_spiffs_16MB.csv | 16MB | 0KB | 4,608KB | 4,608KB | 7,040KB | 0KB |
| m5stack_partitions_16MB _factory_4_apps.csv | 16MB | 960KB | 3,072KB | 3,072KB | 3,008KB | 0KB |
| m5stack_partitions_16MB _factory_6_apps.csv | 16MB | 960KB | 2,048KB | 2,048KB | 3,008KB | 0KB |
| large_fat_32MB.csv | 32MB | 0KB | 4,608KB | 4,608KB | 0KB | 23,424KB |
| large_littlefs_32MB.csv | 32MB | 0KB | 4,608KB | 4,608KB | 23,424KB | 0KB |
一部特殊なのを除いていますが上記のパーティションがArduino IDEからは選択可能です。まずはボードに搭載されているフラッシュメモリの容量を確認し、その中から選択することになります。
| filename | total | factory | ota_0 | ota_1 | spiffs |
|---|---|---|---|---|---|
| minimal.csv | 2MB | 0KB | 1,280KB | 0KB | 640KB |
| default.csv | 4MB | 0KB | 1,280KB | 1,280KB | 1,408KB |
| default_8MB.csv | 8MB | 0KB | 3,264KB | 3,264KB | 1,536KB |
| default_16MB.csv | 16MB | 0KB | 6,400KB | 6,400KB | 3,456KB |
デフォルト系の場合上記の中からフラッシュの容量に応じて選択をします。どれもfactoryは利用しておらず、ota_0領域が設定されています。minimalはota_1がないので実際のOTAは利用できませんが、それ以外のものは利用可能です。
気をつけないといけないのはdefaultのファームウエアサイズが1,280KBなことです。Wi-FiとBLEを利用するとおそらくはそれ以上の容量になりファームウエアを転送できなくなります。その場合にはよいファームウエア容量の大きなパーティションを選択する必要があります。
| filename | total | ota_0 | ota_1 | spiffs | 備考 |
|---|---|---|---|---|---|
| default.csv | 4MB | 1,280KB | 1,280KB | 1,408KB | 標準。BLEだと容量が足りない |
| huge_app.csv | 4MB | 3,072KB | 0KB | 896KB | OTAをなくしてspiffsを減らす |
| min_spiffs.csv | 4MB | 1,920KB | 1,920KB | 128KB | spiffsを減らす |
| no_fs.csv | 4MB | 1,984KB | 1,984KB | 0KB | spiffsを無くした |
| no_ota.csv | 4MB | 2,048KB | 0KB | 1,920KB | OTAをなくしてspiffsを増やす |
4MBの代表的なパーティションになります。ファームウエア領域を増やすためには他の容量を減らす必要があります。基本的にはOTAを諦めるか、spiffsの容量を減らすかになります。
カスタム設定の方法
スケッチ例の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の該当部分です。ワンライナーのコマンドを実行して、優先順位順にファイルをさがしてきているようでした。
- プロジェクトフォルダにあるpartitions.csv
- {build.variant.path}”/{build.custom_partitions}.csv
- {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などを選択することで転送できるファームウエアの容量を大きくすることが可能です。



コメント