An open API service indexing awesome lists of open source software.

https://github.com/mateusznowakdev/minifs

Absurdly small filesystem for microcontrollers running TinyGo
https://github.com/mateusznowakdev/minifs

Last synced: 9 months ago
JSON representation

Absurdly small filesystem for microcontrollers running TinyGo

Awesome Lists containing this project

README

          

# minifs

Dead simple filesystem for very low-power microcontrollers running TinyGo. Requires Go 1.23+.

* Good performance (10x faster than littlefs on average, tested with SAMD21 at 8 MHz)
* Atomic file updates
* Basic wear leveling
* Only essential features
* no long filenames
* no directories
* no timestamps
* no access control
* ...

It can be useful if there are few small files to be frequently read or written, but may not be a good choice for other purposes.

## Installing

```
$ go get github.com/mateusznowakdev/minifs
```

## API

This library is a wrapper around the TinyGo's `machine.Flash`

Instead of the standard Go file API, there's a custom one which is simpler and faster:

* `Format()`
* `fs.Delete(name)`
* `fs.Exists(name)`
* `fs.List()`
* `fs.Read(name)`
* `fs.Rename(old, new)`
* `fs.Write(name, data)`

Each function returns an error object, either from `machine.Flash` (due to hardware failures) or from `Filesystem` implementation.

Some checks are not implemented (for example if flash memory is too small to store all files created so far).

## Metadata

Metadata block is split into 16-byte-long sections.

| Section # | Bytes | Explanation |
|:---------:|:------:|------------------------------|
| **0** | 0..12 | `SfsMetadataBk` magic number |
| | 13 | Version number |
| | 14..15 | File count (up to 2^16) |
| **1..n** | 0..11 | File name (0xFF-terminated) |
| | 12..13 | File size (up to 2^16) |
| | 14..15 | Block number (up to 2^16) |

For example, up to 15 files can be stored if the block size is 256 bytes. The larger the block, the more file slots are available.

Metadata block is not guaranteed to be found at the very beginning. It is necessary to scan the entire flash memory to find it. It may be beneficial to reserve less space to improve the startup speed.

If there are multiple "valid" metadata blocks, only the first one is considered actually valid. If there are no valid blocks or there is some suspicious data (such as invalid version number), then the filesystem is considered damaged and must be formatted.

The file size is also limited to the size of a single block, which makes fragmentation impossible, but may be a significant limitation.

## Wear leveling

File data is always written next to the current position of metadata block.

### Example

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:--:|:--:|:--:|:--:|:--:|:--:|
| | | M | 1 | 5 | | 3 | 4 | | 2 | 8 | 11 | 6 | 7 | 10 | 9 |

Let's rename file 1. This will cause metadata to be copied.

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|:-:|:-:|:-----:|:-:|:-:|:-------:|:-:|:-:|:-:|:-:|:--:|:--:|:--:|:--:|:--:|:--:|
| | | ~~M~~ | 1 | 5 | _**M**_ | 3 | 4 | | 2 | 8 | 11 | 6 | 7 | 10 | 9 |

If this successful, then the old metadata block gets erased.

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|:-:|:-:|:-:|:-:|:-:|:-------:|:-:|:-:|:-:|:-:|:--:|:--:|:--:|:--:|:--:|:--:|
| | | | 1 | 5 | _**M**_ | 3 | 4 | | 2 | 8 | 11 | 6 | 7 | 10 | 9 |

### Example 2

Now let's overwrite file 10. First, the new file data is written to the first available block, next to the metadata block:

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:--------:|:-:|:--:|:--:|:--:|:--:|:------:|:--:|
| | | | 1 | 5 | M | 3 | 4 | _**10**_ | 2 | 8 | 11 | 6 | 7 | ~~10~~ | 9 |

Then the metadata needs to be updated. Since there is no more space to the right (block #14 is still being used!), we wrap around and find the first available block:

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|:-------:|:-:|:-:|:-:|:-:|:-----:|:-:|:-:|:--------:|:-:|:--:|:--:|:--:|:--:|:------:|:--:|
| _**M**_ | | | 1 | 5 | ~~M~~ | 3 | 4 | _**10**_ | 2 | 8 | 11 | 6 | 7 | ~~10~~ | 9 |

If this is successful, then the old metadata block gets erased and old data block will be repurposed later (data is NOT erased).

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|:-------:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:--------:|:-:|:--:|:--:|:--:|:--:|:------:|:--:|
| _**M**_ | | | 1 | 5 | | 3 | 4 | _**10**_ | 2 | 8 | 11 | 6 | 7 | ~~10~~ | 9 |