Làm việc với ROMFS¶
Tổng quan¶
ROMFS (Hệ thống tệp bộ nhớ chỉ đọc) là một hệ thống tệp nhỏ gọn, chỉ đọc được thiết kế cho các thiết bị MicroPython. Nó được tối ưu hóa cho vi điều khiển và hệ thống nhúng, nơi mã và dữ liệu cần được lưu trữ trong bộ nhớ flash và truy cập hiệu quả mà không cần sao chép vào RAM.
Các lợi ích chính của ROMFS là:
Import không sao chép (zero-copy): Các tệp bytecode
.mpyđược lưu trong ROMFS có thể được thực thi trực tiếp từ bộ nhớ flash (ánh xạ bộ nhớ) thay vì phải sao chép vào RAM trước. Điều này tương tự như cách hoạt động của các mô-đun đóng băng, nhưng không yêu cầu nạp lại toàn bộ firmware.Tốn ít RAM: Các đối tượng hằng số (chuỗi, bytes, v.v.) trong các tệp
.mpyđược tải từ ROMFS được tham chiếu trực tiếp từ flash, không nhân bản trong RAM.Triển khai linh hoạt: Ảnh ROMFS có thể được xây dựng trên máy tính chủ và triển khai tới thiết bị bằng mpremote, mà không cần xây dựng lại firmware.
Giao diện hệ thống tệp chuẩn: ROMFS được gắn kết trong VFS và được truy cập thông qua các thao tác tệp Python thông thường (
open,os.listdir,import, v.v.).
ROMFS bổ sung cho cả hệ thống tệp FAT/LittleFS có thể đọc-ghi (nằm trên các phân vùng flash khác) và cho các mô-đun đóng băng (được biên dịch trực tiếp vào firmware).
Hỗ trợ bo mạch¶
ROMFS được bật trong firmware OpenMV trên mọi bo mạch camera có phân vùng ROMFS được dành riêng trong bố cục flash. Trên các bo mạch này, phân vùng ROMFS được tự động phát hiện khi khởi động và gắn kết tại /rom; cả /rom và /rom/lib đều được thêm vào sys.path để các mô-đun lưu trữ ở đó có thể được import trực tiếp.
Bo mạch |
Hỗ trợ ROMFS |
|---|---|
OpenMV Cam N6 |
Có |
OpenMV AE3 |
Có |
OpenMV Cam RT1062 |
Có |
OpenMV Cam Pure Thermal |
Có |
OpenMV Cam M4 / M7 / H7 / H7 Plus |
Có |
Arduino Giga |
Có |
Arduino Portenta H7 |
Có |
Arduino Nicla Vision |
Có |
Arduino Nano 33 BLE Sense |
Không (không có phân vùng ROMFS) |
Arduino Nano RP2040 Connect |
Không (không có phân vùng ROMFS) |
Xem romfs để biết về trợ giúp dành riêng cho OpenMV kiểm tra ROMFS được gắn kết tại /rom.
Quy trình làm việc¶
Quy trình điển hình để sử dụng ROMFS là:
Tạo một thư mục trên máy tính của bạn chứa các tệp Python (hoặc tệp
.mpy) bạn muốn triển khai.Sử dụng
mpremote romfs deploy <directory>để xây dựng và triển khai ảnh ROMFS tới thiết bị.ROMFS sẽ được gắn kết tại
/romkhi khởi động lần tiếp theo (hoặc có thể gắn kết ngay lập tức nếu thiết bị được khởi động lại).Mã Python trên thiết bị sau đó có thể
importcác mô-đun từ ROMFS giống như từ bất kỳ hệ thống tệp nào khác.
Ví dụ:
# On the host PC, with a directory "myapp/" containing app.py:
$ mpremote romfs deploy myapp/
Sau khi soft-reset, thiết bị sẽ có /rom/app.py (hoặc /rom/app.mpy nếu mpy_cross được cài đặt) sẵn sàng để import.
Xem phần các lệnh con romfs của mpremote bên dưới để biết chi tiết đầy đủ về các lệnh con mpremote.
API Python¶
API Python cho ROMFS được cung cấp thông qua mô-đun vfs.
- class vfs.VfsRom(buffer)
Tạo đối tượng hệ thống tệp ROMFS từ buffer, phải là một đối tượng hỗ trợ giao thức buffer (ví dụ: đối tượng
bytes,bytearrayhoặcmemoryview) chứa ảnh ROMFS hợp lệ.Hàm khởi tạo xác thực rằng buffer bắt đầu bằng các byte kỳ diệu của ROMFS (
b"\xd2\xcd\x31"). Nếu buffer quá nhỏ hoặc không phải là ROMFS hợp lệ,OSError(ENODEV)sẽ được phát sinh.Các đối tượng được tạo bởi hàm khởi tạo này có thể được gắn kết bằng
vfs.mount().Ví dụ:
import vfs # Load a ROMFS image from flash into a memoryview. dev = vfs.rom_ioctl(2, 0) # get partition 0 as a memoryview fs = vfs.VfsRom(dev) vfs.mount(fs, '/rom')
Hoặc, để gắn kết ảnh ROMFS được lưu trong một tệp:
import vfs with open('/flash/app.romfs', 'rb') as f: romfs_data = f.read() fs = vfs.VfsRom(romfs_data) vfs.mount(fs, '/rom2')
Các phương thức sau đây có sẵn trên đối tượng
VfsRom:- VfsRom.open(path, mode)
Mở một tệp từ ROMFS. Chỉ hỗ trợ chế độ đọc (
'','r','rt','rb'). Cố gắng mở tệp để ghi sẽ phát sinhOSError(EROFS).Đối tượng tệp trả về hỗ trợ
read(),seek(),tell()vàclose(). Đối với các tệp nhị phân được mở ở chế độ đọc, đối tượng trả về cũng hỗ trợ giao thức buffer để có thể lấymemoryviewcủa dữ liệu tệp, tham chiếu trực tiếp vào bộ nhớ ROMFS (zero-copy).
- VfsRom.ilistdir(path)
Trả về một iterator qua các mục trong thư mục path. Mỗi mục là một tuple
(name, type, inode, size)trong đó type là0x8000cho tệp hoặc0x4000cho thư mục.
- VfsRom.stat(path)
Trả về một tuple 10 phần tử giống
os.statcho path. Phát sinhOSError(ENOENT)nếu đường dẫn không tồn tại.
- VfsRom.statvfs(path)
Trả về thống kê hệ thống tệp. Kích thước khối được báo cáo là 1 và số lượng khối biểu thị tổng kích thước của ảnh ROMFS tính bằng byte. Các khối trống và tệp trống luôn là 0 (hệ thống tệp chỉ đọc).
- VfsRom.chdir(path)
Thay đổi thư mục trong ROMFS. Chỉ hỗ trợ thư mục gốc (
'/'); thay đổi sang bất kỳ thư mục con nào sẽ phát sinhOSError(EOPNOTSUPP).
- VfsRom.getcwd()
Trả về thư mục làm việc hiện tại trong ROMFS. Luôn trả về
'/'.
- vfs.rom_ioctl(op, ...)
Giao diện cấp thấp để truy cập phân vùng bộ nhớ chỉ đọc (ROM) của thiết bị.
Các thao tác được hỗ trợ là:
vfs.rom_ioctl(1)-- Trả về số lượng phân vùng ROM có sẵn.vfs.rom_ioctl(2, id)-- Trả về phân vùng ROM với chỉ số id dưới dạng đối tượngmemoryview. Bộ nhớ có thể đọc nhưng không thể ghi trực tiếp.vfs.rom_ioctl(3, id, length)-- Chuẩn bị phân vùng ROM để ghi. Xóa length byte đầu tiên của phân vùng với chỉ số id. Trả về kích thước ghi tối thiểu tính bằng byte (căn chỉnh cần thiết cho các lần ghi tiếp theo).vfs.rom_ioctl(4, id, offset, buf)-- Ghi buf (đối tượng kiểu bytes) vào phân vùng ROM với chỉ số id tại byte offset.vfs.rom_ioctl(5, id)-- Hoàn thành chuỗi ghi vào phân vùng id (thực hiện mọi hoàn thiện cần thiết sau khi ghi, chẳng hạn như xả cache).
Các thao tác này được sử dụng nội bộ bởi
mpremoteđể triển khai ảnh ROMFS. Hầu hết người dùng không cần gọivfs.rom_ioctl()trực tiếp.Ví dụ (truy vấn các phân vùng có sẵn):
import vfs n = vfs.rom_ioctl(1) print("Number of ROM partitions:", n) for i in range(n): dev = vfs.rom_ioctl(2, i) print(f" Partition {i}: {len(dev)} bytes")
Tự động gắn kết khi khởi động¶
Khi hỗ trợ ROMFS được bật trong firmware, MicroPython sẽ tự động cố gắng gắn kết phân vùng ROM đầu tiên tại /rom trong quá trình khởi tạo. Nếu phân vùng chứa ảnh ROMFS hợp lệ, nó sẽ được gắn kết và cả /rom lẫn /rom/lib đều được thêm tự động vào sys.path.
Điều này có nghĩa là sau khi triển khai ảnh ROMFS bằng mpremote, một lần soft-reset là đủ để các mô-đun mới có thể được import.
Nếu không tìm thấy ảnh ROMFS hợp lệ trong phân vùng (ví dụ: trên bo mạch mới được lập trình), quá trình gắn kết sẽ bị bỏ qua một cách im lặng.
Sử dụng mpremote để quản lý ROMFS¶
Công cụ mpremote cung cấp ba lệnh con để quản lý ảnh ROMFS trên thiết bị được kết nối.
romfs query¶
$ mpremote romfs query
Liệt kê tất cả các phân vùng ROMFS có sẵn trên thiết bị và kích thước của chúng. Cũng hiển thị 12 byte đầu tiên của mỗi phân vùng ở dạng hex và báo cáo xem có ảnh ROMFS hợp lệ hay không.
Ví dụ đầu ra:
ROMFS0 partition has size 131072 bytes (32 blocks of 4096 bytes each)
Raw contents: d2:cd:31:XX:XX:XX:XX:XX:XX:XX:XX:XX ...
ROMFS image size: 1234
romfs build¶
$ mpremote romfs [-o <output>] build <source>
Xây dựng ảnh ROMFS từ thư mục source trên máy tính chủ. Ảnh được ghi vào output (mặc định: <source>.romfs).
Các tùy chọn:
-o <output>,--output <output>: Chỉ định đường dẫn tệp đầu ra.-m,--mpy(mặc định): Tự động biên dịch các tệp.pysang.mpybằngmpy_crosstrước khi thêm chúng vào ảnh. Yêu cầu gói Pythonmpy_cross(pip install mpy_cross).--no-mpy: Tắt biên dịch tự động các tệp.py.
Ví dụ:
$ mpremote romfs build myapp/
Building romfs filesystem, source directory: myapp/
/
|-- main.py -> .mpy
\-- lib/
\-- helper.py -> .mpy
Writing 2048 bytes to output file myapp.romfs
romfs deploy¶
$ mpremote romfs [-p <partition>] deploy <source>
Triển khai ảnh ROMFS tới thiết bị. source có thể là:
Một thư mục trên máy chủ: ảnh ROMFS được xây dựng trong bộ nhớ và triển khai trực tiếp.
Một tệp
.romfshoặc.img: ảnh được đọc từ đĩa và triển khai.
Các tùy chọn:
-p <partition>,--partition <partition>: Chỉ định chỉ số phân vùng đích (mặc định:0).-m,--mpy(mặc định): Biên dịch.pysang.mpykhi source là một thư mục.--no-mpy: Tắt biên dịch tự động các tệp.py.
Sau khi triển khai, thiết bị phải được soft-reset để ROMFS mới được gắn kết tại /rom.
Ví dụ:
$ mpremote romfs deploy myapp/
Building romfs filesystem, source directory: myapp/
/
|-- main.py -> .mpy
\-- lib/
\-- helper.py -> .mpy
Image size is 2048 bytes
ROMFS0 partition has size 131072 bytes (32 blocks of 4096 bytes each)
Preparing ROMFS0 partition for writing
Deploying ROMFS to ROMFS0 partition
ROMFS image deployed
$ mpremote soft-reset
Ví dụ¶
Triển khai một ứng dụng đơn giản¶
Giả sử bạn có thư mục dự án myapp/ với cấu trúc sau:
myapp/
main.py
utils.py
lib/
helper.py
Để triển khai nó lên ROMFS của thiết bị:
$ mpremote romfs deploy myapp/
Sau khi soft-reset, các mô-đun có thể được import từ ROMFS:
import main
import utils
from lib import helper
Liệt kê nội dung ROMFS từ Python¶
Sau khi gắn kết, nội dung ROMFS có thể được khám phá như bất kỳ hệ thống tệp nào khác:
import os
for entry in os.ilistdir('/rom'):
print(entry)
# Or simply:
print(os.listdir('/rom'))
OpenMV cũng đi kèm một trợ giúp nhỏ romfs in danh sách có định dạng bao gồm địa chỉ ánh xạ bộ nhớ và căn chỉnh của mỗi tệp:
from omv import romfs
romfs.ls_romfs()
Lồng ROMFS trong ROMFS¶
Ảnh ROMFS được lưu dưới dạng tệp trong ROMFS bên ngoài có thể được gắn kết như một hệ thống tệp lồng nhau. Ví dụ: nếu /rom/inner.romfs tồn tại. Vì /rom là ROMFS, các đối tượng tệp được mở từ nó hỗ trợ giao thức buffer, vì vậy có thể lấy trực tiếp memoryview zero-copy:
import vfs
with open('/rom/inner.romfs', 'rb') as f:
inner = vfs.VfsRom(memoryview(f))
vfs.mount(inner, '/inner')
print(os.listdir('/inner'))
Định dạng ảnh ROMFS¶
Định dạng ảnh ROMFS là một định dạng nhị phân nhỏ gọn được thiết kế cho truy cập ánh xạ bộ nhớ trên vi điều khiển. Tổng quan ngắn gọn:
Ảnh bắt đầu bằng các byte kỳ diệu
0xd2 0xcd 0x31(được mã hóa là"RM1"với các bit cao của hai byte đầu tiên được đặt).Phần còn lại của ảnh bao gồm các bản ghi, mỗi bản ghi có thẻ loại (varuint), độ dài (varuint) và tải trọng.
Các loại bản ghi bao gồm: đệm, dữ liệu nguyên văn, con trỏ dữ liệu gián tiếp, thư mục, tệp.
Tên thư mục và tệp được lưu trữ dưới dạng chuỗi byte có tiền tố độ dài.
Dữ liệu tệp có thể được lưu trữ nguyên văn (nội tuyến) hoặc thông qua con trỏ gián tiếp đến nơi khác trong ảnh, điều này cho phép căn chỉnh để truy cập ánh xạ bộ nhớ.
Các loại bản ghi không rõ sẽ bị bỏ qua một cách im lặng, cung cấp khả năng tương thích về phía trước.
Định dạng này được định nghĩa trong extmod/vfs_rom.c trong nguồn MicroPython. Cài đặt Python được mpremote sử dụng để xây dựng ảnh nằm trong tools/mpremote/mpremote/romfs.py.
Xem thêm
Làm việc với hệ thống tệp -- Tổng quan về VFS MicroPython và các loại hệ thống tệp có sẵn.
Tệp manifest MicroPython -- Cách đóng băng các mô-đun Python vào firmware.
Các tệp .mpy của MicroPython -- Định dạng tệp nhị phân .mpy của MicroPython.
Điều khiển từ xa MicroPython: mpremote -- Tài liệu tham khảo lệnh mpremote đầy đủ.
romfs -- Trợ giúp OpenMV để kiểm tra hệ thống tệp /rom được gắn kết.