As described in Using SmartFS, the code is divided into a SMART MTD layer and a filesystem layer. The MTD layer divides the flash or partition into equal sized logical sectors, allocates, deallocates and moves them around as needed to fulfill requests from the filesystem layer. The filesystem layer uses the logical sectors to store directory and file information, and to create chains of logical sector numbers to build larger files (and directories).
The diagram below depicts a portion of a SmartFS device showing the erase blocks, logical sectors and sector assignments. In the diagram, the top row of numbers is the absolute sector number within the device. The bottom row with numbers represents the logical sector number assigned to each absolute sector. Using 5 bytes from the header in each sector, the MTD layer manages the assignments of the logical sector numbers.
The filesystem layer receives the logical sector numbers reported from MTD layer and assigns them to specific files and/or directories. As a file grows in size, additional logical sector numbers are requested and “chained” together. In the diagram, three files are depicted (files 'a', 'b' and 'c') with varying lengths. The files shown are as follows:
- File 'a': Has data in 3 sectors, a0-a2, logical sectors 12-14
- File 'b': Has data in 4 sectors, b0-b3, logical sectors 15-18
- File 'c': Has data in a single sector, c0, logical sector 19
|Device or partition|
EB = Erase Block
LS = Logical Sector
FS = Format Sector
RS = Root-directory Sector
— = Free Sector
The filesystem layer uses last 5-bytes of each sector's header to save the logical sector number of the next logical sector in the chain. When a file is first created, it's name and beginning logical sector number are recorded in the Root-directory Sector (or a sub-directory sector as needed).
The filesystem layer uses the recorded logical sector numbers in the directory sectors and header sector-chain information to perform logical sector allocate, read/write and sector release requests to carry out all typical file system operations. The SMART MTD layer then performs all the logical to physical mapping, wear-leveling, sector relocation and block erase operations, etc. When a sector needs to be physically relocated, it will retain it's logical sector number, preventing the need to update file sector-chain information, etc. The MTD layer will simply update the logical to physical map assignments.
Writing data to the filesystem and then reading it back is great. But at some point you might actually want to change or delete something. When this happens, the existing data on the flash has to be modified. As you probably already know, data on a flash can't simply be re-written, it must be erased in large chunks (erase blocks) that are typically 4K, 32K or 64K in size. When erasing this large a chunk of the flash, it is highly likely that there will be data in that erase block which should NOT be erased.
When data in a logical sector on the flash needs to be modified or deleted, SmartFS simply marks that logical sector as “released” without actually touching the data. This is done using the characteristic of NOR flash that allows multiple writes to a given address. This feature allows any bit of any byte to be changed from a '1' state to a '0' state, regardless of whether that byte had previously been written with *other* bits set to a 0 state. As long as there is no attempt to change any bits from a '0' to a '1', each address can be programmed multiple times.
As shown in the diagrams below, the SMART MTD layer uses the 5th byte of the logical sector header as a status byte. The most significant bit of this status byte (0x80) indicates if the sector has been allocated (contains valid data) while the next bit (0x40) indicates if the sector has been “released” (contains data that is no longer valid). When a sector is first allocated, the RELEASE bit is held at a '1' state, meaning the data has not been released. If the data in that sector needs to be changed, deleted or relocated, the SMART MTD code will simply re-program the status byte, changing the RELEASE bit to a '0' state. At that point, all data in that logical sector becomes invalid.
Logical Sector MTD Header
|MTD Header (5 bytes)||FS Header|
|Logical Sector Number||Seq #||CRC||Status||5 Bytes|
CB: Commit Bit
RB: Release Bit
CE: CRC Enable Bit
SS: Sector Size Bits
FV: Format Version Bits