DUE TO SPAM, SIGN-UP IS DISABLED. Goto Selfserve wiki signup and request an account.
Using SmartFS
Overview
What is SmartFS
SmartFS stands for Sector Mapped Allocation for Really Tiny (SMART) flash. It is a filesystem that has been designed to work primary with small, serial NOR type flash parts that are 1M byte to 16M byte in size (though this is not a limitation). The filesystem operates by segmenting the flash (or flash partition) into "logical sectors" of equal size and then managing them (allocating, mapping, chaining, releasing, etc.) to build files and directories.
SmartFS Code Layering
The system consists of two layers built on top of a standard NuttX MTD driver layer (with it's associated hardware abstraction layer).
...
On top of the SMART MTD layer is the Smart Filesystem code. The SmartFS code uses the logical sector services of the SMART MTD layer to provide file and directory level management, such as creating new files, chaining logical sectors together to create files, creating directories and file / directory search and management routines.
| Smart FS | fs / smartfs / * | |||
|---|---|---|---|---|
| SMART MTD | drivers / mtd / smart.c | |||
|---|---|---|---|---|
| MTD Driver | m25px | sst25 | |
| filemtd | etc. | ||
| HW Driver | spi dev | spi dev | VFS |
| … |
Example SmartFS Device Setup
Setting up a device for use with SmartFS is typically done in the config specific source initialization files and would look something like:
...
| Code Block |
|---|
nsh> mksmartfs /dev/smart0 nsh> mount -t smartfs /dev/smart0 /mnt |
Details of Operation
Pages, Blocks, Sectors and things that FLASH
There are a number of companies that manufacture FLASH parts, and typically they use varying terminology in their data sheets when referring to device geometry. All devices generally have different region sizes for programming, erasing and reading and usually use terms like page, erase block, sector and/or sub-sector. To avoid confusion, NuttX uses the following terminology:
...
An example 128K Byte Flash with 32K and 4K Erase Block sizes and 256 byte page read/write sizes:
| Bulk Erase | Entire Device | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Sector Erase | 32K | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 32K | |||||||||
| 32K |
| 32K | |||||||
| Sector Erase | 4K | ||||
|---|---|---|---|---|---|
| … | 4K | 4K | |||||
| … | 4K | 4K |
| … | 4K | 4K |
| … | 4K | ||
| Page read/write | 256 | 256 |
|---|---|---|
...
256
256
| … | 256 | 256 | … | |||||||||
| 256 | ||||||||||
| … | 256 | |
| Logical Sector (FS) | 512 | |
|---|---|---|
| … | 512 | … | |||||||||||||||
...
512 ::UWCTOKENCOLSPANS:2::
In the example above, a SMART MTD logical sector size of 512 bytes was chosen. On the 128K Byte FLASH represented in the table above, this means there would be:
...
128K / 256 = 512 Logical Sectors Total- {{
4K / 256 = 16 Logical Sectors per Erase Block}} - {{
256 / 256 = 1 MTD Read/Write Block per SMART Logical Sector}} - {{
10 / 256 = 3.9% Overhead for logical sector headers}}
A maximum of about 506 files / directories supported (considering format overhead)Allocations to files in 256 byte chunks (a zero-length file consumes 256 bytes)
Checking Your MTD Geometry
Most of the NuttX MTD drivers (in the drivers/mtd directory) have been tested to work with SmartFS / SMART MTD layer and to report block / erase block sizes correctly. However there may be one or more drivers that have not been validated. When configuring SmartFS for the first time using a new / unknown MTD driver, validate the reported geometries are sane based on the description above.
...
Selecting a logical sector size that creates 256 logical sectors per erase block will create some wasted space on the device. The SMART MTD layer uses a 1-byte variable for the "free sector count" and the "released sector count". This means it can only track up to 255 logical sectors per erase block. When the sectPerEraseBlk == 256, the last logical sector in each erase block will never be used, thus causing wasted space on the device.
RAM Usage Calculation
Efficient management of the filesystem requires building and maintaining RAM resident status information of the SMART MTD logical sector structure on the physical device. During the 'smart_initialize' function, the code performs a device scan ('smart_scan' routine) to perform this action. Tasks performed by the smart_scan are:
...
CONFIG_MTD_SMART_MINIMIZE_RAM is not set
Item | RAM Requirement | 1MB / 256 Logical | 8MB / 1024 Logical |
|---|---|---|---|
dev struct | 368-380 (approx) | 376 | 376 |
Logical sector map | total_sectors * 2 | 8192 | 16384 |
Erase block free count | total erase blocks | 16 | 128 |
Erase block release count | total erase blocks | 16 | 128 |
Wear status | total erase blocks / 2 | 8 | 64 |
MTD sector R/W buffer | logical sector size | 256 | 1024 |
FS sector R/W buffer | logical sector size | 256 | 1024 |
Total |
9,176 | 19,128 |
On larger volumes, the RAM requirement increases significantly because of the logical sector to physical sector mapping table. To help keep RAM requirement under control, setting the CONFIG_MTD_SMART_MINIMIZE_RAM option eliminates this sector-to-sector map and replaces it with a sector-to-sector cache. The cache size is user defined via the CONFIG_MTD_SMART_SECTOR_CACHE_SIZE option. Using this RAM reduction mode trades off RAM usage for performance.
The cache always contains the format and root-directory logical to physical mapping entries, and then stores additional mappings of recently used logical sectors. When a logical sector is requested that is not contained in the cache, then the MTD device is scanned front-to-back until it's physical location on the device is located. Additionally, if the number of logical sectors per erase block is 16 or less, then the "free count" and "release count" can be packed into a single byte per erase block.
_CONFIG_MTD_SMART_MINIMIZE_RAM=y,
CONFIG_MTD_SMART_SECTOR_CACHE_SIZE=64_
Item | RAM Requirement | 1MB / 256 Logical | 8MB / 1024 Logical |
|---|---|---|---|
dev struct | 368-400 (approx) | 392 | 392 |
Logical sector cache | cache entries * 6 | 384 | 384 |
Free sector bitmap | total sectors / 8 | 512 | 1024 |
Erase block free count | total erase blocks | 16 | 128 |
Erase block release count | total erase blocks | 16 | 128 |
Wear status | total erase blocks / 2 | 8 | 64 |
MTD sector R/W buffer | logical sector size | 256 | 1024 |
FS sector R/W buffer | logical sector size | 256 | 1024 |
Total |
1,832 | 4,168 |
Partitions and Mount Points
Creating partitions on the MTD flash / media provides the benefits of physically isolating one filesystem from another, as well as a mechanism for creating multiple mount points within the VFS. There are some pros and cons to consider when deciding to use partitions with SmartFS:
...
| Code Block |
|---|
nsh> ls /dev ... /dev/ram0 /dev/smart0d1 /dev/zero nsh> mksmartfs /dev/smart0d1 3 nsh> ls /dev ... /dev/ram0 /dev/smart0d1 /dev/smart0d2 /dev/smart0d3 /dev/zero nsh> mount -t smartfs /dev/smart0d1 /data nsh> mount -t smartfs /dev/smart0d2 /apps nsh> mount -t smartfs /dev/smart0d3 /recover |
The ProcFS Interface
When the PROCFS interface is enabled, each mounted SmartFS device will appear under:
...
The pseudo files reported for each entry will depend on the configured options. Entries that can currently appear are:
Entry | CONFIG_MTD_SMART_* | Meaning |
|---|---|---|
status |
Report volume status including geometry | ||
debuglevel |
Write ASCII '0' - '2' to set debug print level | ||
erasemap | WEAR_LEVEL=y | Report map (A-N) of erase block erasures |
mem | ALLOC_DEBUG=y | Print report of all SMART MTD memory allocs |
Example procfs usage:
| Code Block |
|---|
nsh> mount -t smartfs /dev/smart0 /mnt nsh> mount -t procfs /proc nsh> cat /proc/fs/smartfs/smart0/status Format version: 1 Name Len: 16 Total Sectors: 4096 Sector Size: 256 Format Sector: 0 Dir Sector: 256 Free Sectors: 4078 Released Sectors: 0 Unused Sectors: 0 Block Erases: 0 Sectors Per Block: 256 Sector Utilization:100% Uneven Wear Count: 0 nsh> cat /proc/fs/smartfs/smart0/erasemap BBACAACA AABAAAAA nsh> |
When Things Don't Work
The SmartFS code and MTD layer have been pretty well tested and used in production products. If things aren't working for you, there are a couple of places to start debugging first.
Check FLASH MTD Driver
Ensure the geometry of the FLASH MTD driver is following the NuttX standard for block / erase block geometry sizes. Most of them do, but via simple inspection of the code (as of version 7.16, July 12, 1016), the drivers that are likely to have improper Geometry reporting (and thus incompatible with SmartFS) are:
...
When configuring to use SmartFS, check the reported geometry of the MTD driver you are using. If the geo.blocksize is reported to be the same as the geo.sectorsize, then there is likely an issue with the MTD driver implementation. But it is likely to be a reporting problem of the geo.blocksize that is incorrect AND possibly the starting address calculations in the _bwrite / _bread routines may be incorrect. These are BLOCK read / write operations and calculations need to be performed using the block size (typically 256), not the sector size (4K, 32K, etc.).
Check CONFIG Options
Double check all of the CONFIG options for both the MTD driver and the SMART MTD layer:
- CONFIG_MTD_SMART_SECTOR_SIZE: Ensure it's not smaller than the block size or larger than erase block size.
- CONFIG_MTD_BYTE_WRITE: If enabled, ensure the FLASH actually supports this mode (single byte programming).
- CONFIG_MTD_XXX_SECTOR512: Ensure this is not set. This should only be use with FAT volumes.
- CONFIG_MTD_XXX_MANUFACTURER: Double check this with the data sheet / MTD driver code
- CONFIG_MTD_XXX_MEMORY_TYPE: Double check this with the data sheet
Check Writability to the Part
Ensure the FLASH can be written successfully. If the WP pin is pull active (i.e. the part is write protected), then the SMART MTD layer will not be able to write any data. Additionally validate there are no individual protected sectors on the device.