このドキュメンテーションは、MicroPython の最新開発ブランチのためのものです。 リリースバージョンでは利用できない機能に言及することがあります。

特定のリリースのドキュメントをお探しの場合は、左側のドロップダウンメニューを使って、 望みのバージョンを選択します。

ROMFS の利用

概要

ROMFS (Read-Only Memory Filesystem) は、コードとデータをフラッシュメモリに格納し、RAM にコピーせずに効率よくアクセスする必要のあるマイクロコントローラや組み込みシステム向けに最適化された、軽量な読み出し専用ファイルシステムです。

ROMFS の主な利点は次のとおりです:

  • ゼロコピーの import: ROMFS に格納された .mpy のバイトコードファイルは、まず RAM にコピーされるのではなく、フラッシュメモリから直接(メモリマップして)実行できます。これは 凍結モジュール の動作に似ていますが、ファームウェア全体を書き込み直す必要はありません。

  • RAM のオーバーヘッドが小さい: ROMFS から読み込まれた .mpy ファイル内の文字列やバイト列の定数オブジェクトは、RAM に複製されず、フラッシュから直接参照されます。

  • 柔軟なデプロイ: ROMFS のイメージはホスト PC 上でビルドし、ファームウェアを再ビルドすることなく mpremote でデバイスにデプロイできます。

  • 標準的なファイルシステムのインターフェース: ROMFS は VFS にマウントされ、通常の Python のファイル操作( open 、 os.listdir 、 import など)でアクセスできます。

ROMFS は、(他のフラッシュパーティションに置かれる)読み書き可能な LittleFS/FAT のファイルシステムとも、(ファームウェア自体にコンパイルされる) 凍結モジュール とも補完的な関係にあります。

注釈

ROMFS を使うには、ROMFS のサポート ( MICROPY_VFS_ROM ) を有効にしてビルドしたファームウェアが必要です。すべてのポートやボードがデフォルトでこれを含んでいるわけではありません。ボードのドキュメントかビルドの設定を確認してください。

ポートのサポート状況

次のポートは ROMFS をサポートしています。これらのポートでは、ボードに ROMFS パーティションが設定されていれば、起動時に自動的に検出されて VFS の /rom にマウントされます。 /rom と /rom/lib は自動的に sys.path に追加されるので、そこに置いたモジュールを直接 import できます。

ポート

備考

alif

ROMFS パーティションが設定されたボードでサポートされます。

esp32

カスタムのパーティションテーブルでサポートされます。

esp8266

2MiB 以上のボードでサポートされます (ESP8266_GENERIC の FLASH_2M_ROMFS バリアント)。

mimxrt

ROMFS パーティションが設定されたボードでサポートされます。

nrf

ROMFS パーティションが設定されたボードでサポートされます。

qemu

サポートされます (CI のテストに使われます)。

renesas-ra

ROMFS パーティションが設定されたボードでサポートされます。

rp2

ROMFS パーティションが設定されたボードでサポートされます。

samd

ROMFS パーティションが設定されたボードでサポートされます。

stm32

ROMFS パーティションが設定されたボードでサポートされます。

unix

サポートされます (主にテスト用)。

ポートやボードで ROMFS を有効にする

ROMFS の実装は現時点ではポート固有であり、ここで説明するには詳細が多すぎます。

作業の流れ

ROMFS を使う一般的な流れは次のとおりです:

  1. デプロイしたい Python のファイル(または .mpy ファイル)を置いたディレクトリを PC 上に作ります。

  2. mpremote romfs deploy <directory> を使って ROMFS のイメージをビルドし、デバイスにデプロイします。

  3. ROMFS は次回の起動時に /rom にマウントされます(デバイスをソフトリセットすればすぐにマウントすることもできます)。

  4. その後、デバイス上の Python のコードから、他のファイルシステムと同じように ROMFS のモジュールを import できます。

たとえばホスト PC 上に、app.py を含むディレクトリ "myapp/" があるとします:

$ mpremote romfs deploy myapp/

ソフトリセットの後、デバイスでは /rom/app.mpy が import できるようになります( mpy_cross がインストールされていない場合は /rom/app.py )。

あるいは、先にホスト PC 上で ROMFS のイメージをビルドしてから、デバイスにデプロイすることもできます:

$ mpremote romfs build myapp
$ mpremote romfs deploy myapp.romfs

mpremote のコマンドの詳細は mpremote romfs commands の節を参照してください。

起動時の自動マウント

ファームウェアで ROMFS のサポートが有効になっている場合、MicroPython は初期化中( mp_init() の後)に、最初の ROM パーティションを /rom にマウントしようと自動的に試みます。パーティションに有効な ROMFS イメージがあればマウントされ、 /rom と /rom/lib が自動的に sys.path に追加されます。

つまり、 mpremote で ROMFS のイメージをデプロイした後は、ソフトリセットするだけで新しいモジュールを import できるようになります。

パーティションに有効な ROMFS のイメージが見つからない場合(書き込み直後のボードなど)は、マウントは何も表示せずにスキップされます。

mpremote を使った ROMFS の管理

mpremote の romfs コマンドで、ROMFS パーティションの問い合わせ、ROMFS イメージのビルド、接続したデバイスへのイメージのデプロイができます。コマンドの構文、オプション、例は mpremote ROMFS commands を参照してください。

ROMFS の使用例

単純なアプリケーションのデプロイ

次の構成のプロジェクトディレクトリ myapp/ があるとします:

── myapp
   ├── myapp.py
   ├── utils.py
   └── lib
       └── helper.py

これをデバイスの ROMFS にデプロイするには:

$ mpremote romfs deploy myapp/
$ mpremote tree
  tree :
  :/
  └── rom
      ├── lib
      │   └── helper.mpy
      ├── myapp.mpy
      └── utils.mpy

ソフトリセットの後、マウントポイントと lib フォルダが sys.path に追加されているので、モジュールを ROMFS から import できます:

import myapp
import utils
import helper

Python から ROMFS の内容を一覧表示する

マウント後は、ROMFS の内容を他のファイルシステムと同じように調べられます:

import os

for entry in os.ilistdir('/rom'):
    print(entry)

# あるいは単純に:
print(os.listdir('/rom'))

2つ目の ROMFS イメージを手動でマウントする

ROMFS のパーティションが複数ある場合は、デバイス上の別のパーティションから2つ目の ROMFS イメージをマウントできます。たとえば、2つ目の ROMFS パーティションが番号 2 にある場合、次のようにしてマウントできます:

import vfs
dev = vfs.rom_ioctl(2, 1)  # 2つ目のパーティションを取得
vfs.mount(vfs.VfsRom(dev), "/rom2")

ファイルに格納された ROMFS イメージのマウント

ROMFS の中にファイルとして格納された ROMFS のイメージは、RAM にコピーすることなく入れ子のファイルシステムとしてマウントできます。たとえば /rom/data.romfs があれば、次のようにマウントできます:

# boot.py
import vfs
with open('/rom/data.romfs', 'rb') as f:
    fs = vfs.VfsRom(f)
vfs.mount(fs, '/data')

その後ソフトリセットすると、入れ子の ROMFS が /data で利用できます:

$ mpremote tree
  tree :
  :/
  ├── boot.py
  ├── data
  │   └── facts.db
  ├── main.py
  └── rom
      ├── data.romfs
      ├── lib
      │   └── helper.mpy
      ├── myapp.mpy
      └── utils.mpy

ROMFS のファイルシステム形式

ROMFS は、読み出し専用でデータをメモリマップできるファイルを持つディレクトリ階層を表現するために設計された、柔軟で拡張可能なファイルシステム形式です。

概念:

  • varuint : 可変長のバイト数でエンコードされる符号なし整数です。ビッグエンディアンで格納され、後続のバイトがある場合はそのバイトの最上位ビットが立ちます。

  • record : 型を持つ可変長の要素です。2つの varuint とそれに続くペイロードとして格納されます。1つ目の varuint はレコードの種類、2つ目の varuint はペイロードの長さです(0 バイトのこともあります)。

ROMFS のファイルシステムは、レコード種別 0x14a6b1 のレコードです。この値は、エンコードすると 0xd2-0xcd-0x31 、つまり最初の2バイトの最上位ビットを立てた "RM1" になるように選ばれています。ROMFS レコードのペイロードが空でない場合、その中にはレコードが入っています。

レコードの種類:

  • 0 -- 未使用: ファイルシステムの破損の検出に使えます。

  • 1 -- パディング/コメント: ペイロードには任意のデータを入れられます。

  • 2 -- そのままのデータ: ファイルのデータの格納に使います。

  • 3 -- 間接データ: ROMFS のペイロード内のオフセットを指します。

  • 4 -- ディレクトリ: ペイロードにはディレクトリ名の長さ(バイト単位)を示す varuint が入り、続いて名前と、ディレクトリの内容を表す省略可能な入れ子のレコード(省略可能なメタデータを含む)が入ります。

  • 5 -- ファイル: ペイロードにはファイル名の長さ(バイト単位)を示す varuint が入り、続いて名前と省略可能な入れ子のレコードが入ります。

未知のレコード種別は何も表示せずにスキップされるので、前方互換性が保たれます。

この形式は MicroPython のソースの extmod/vfs_rom.c で定義されています。 mpremote がイメージのビルドに使う Python の実装は tools/mpremote/mpremote/romfs.py にあります。

参考