fs/littlefs: upgrade littlefs to v2.2.1

Since littlefs is in active development, it's not a good idea to use its
source code files directly. So upgrade littlefs v2.2.1 by using the littlefs
tar.gz release package instead.

Change-Id: I16d9cf0b6bca700a54ca86ed11d7c8c7f27a898f
Signed-off-by: liuhaitao <liuhaitao@xiaomi.com>
This commit is contained in:
liuhaitao 2020-04-21 15:22:31 +08:00 committed by patacongo
parent 43ee4ae184
commit fe0ba38580
12 changed files with 102 additions and 6442 deletions

View File

@ -99,6 +99,8 @@ $(COBJS): %$(OBJEXT): %.c
$(BIN): $(OBJS)
$(call ARCHIVE, $@, $(OBJS))
context::
.depend: Makefile $(SRCS)
$(Q) $(MKDEP) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
$(Q) touch $@
@ -109,7 +111,7 @@ clean:
$(call DELFILE, $(BIN))
$(call CLEAN)
distclean: clean
distclean:: clean
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)

4
fs/littlefs/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/.littlefsunpack
/littlefs
/*tar.gz
/*.zip

File diff suppressed because it is too large Load Diff

View File

@ -1,55 +1,52 @@
#############################################################################
############################################################################
# fs/littlefs/Make.defs
#
# This file is a part of NuttX:
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# Copyright (C) 2019 Gregory Nutt. All rights reserved.
# http://www.apache.org/licenses/LICENSE-2.0
#
# Ported by:
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (C) 2019 Pinecone Inc. All rights reserved.
# Author: lihaichen <li8303@163.com>
#
# This port derives from ARM mbed logic which has a compatible 3-clause
# BSD license:
#
# Copyright (c) 2017, Arm Limited. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the names ARM, NuttX nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
#############################################################################
############################################################################
ifeq ($(CONFIG_FS_LITTLEFS),y)
# Files required for littlefs file system support
CSRCS += lfs.c lfs_util.c lfs_vfs.c
CSRCS += lfs_vfs.c
DEPPATH += --dep-path littlefs
VPATH += :littlefs
CSRCS += lfs.c lfs_util.c
DEPPATH += --dep-path littlefs/littlefs
VPATH += :littlefs/littlefs
LITTLEFS_VERSION ?= 2.2.1
LITTLEFS_TARBALL = v$(LITTLEFS_VERSION).tar.gz
$(LITTLEFS_TARBALL):
$(Q) wget -P littlefs https://github.com/ARMmbed/littlefs/archive/$(LITTLEFS_TARBALL)
.littlefsunpack: $(LITTLEFS_TARBALL)
$(Q) tar zxf littlefs/$(LITTLEFS_TARBALL) -C littlefs
$(Q) mv littlefs/littlefs-$(LITTLEFS_VERSION) littlefs/littlefs
$(Q) touch littlefs/.littlefsunpack
context:: .littlefsunpack
distclean::
$(call DELFILE, littlefs/.littlefsunpack)
$(call DELFILE, littlefs/$(LITTLEFS_TARBALL))
$(call DELDIR, littlefs/littlefs)
endif

View File

@ -1,220 +0,0 @@
## usage
depends on !DISABLE_MOUNTPOINT
1. register_mtddriver("/dev/w25", mtd, 0755, NULL);
2. mount("/dev/w25", "/w25", "littlefs", 0, NULL);
## need to do
1. no format tool, mount auto format.
## The little filesystem
A little fail-safe filesystem designed for embedded systems.
```
| | | .---._____
.-----. | |
--|o |---| littlefs |
--| |---| |
'-----' '----------'
| | |
```
**Bounded RAM/ROM** - The littlefs is designed to work with a limited amount
of memory. Recursion is avoided and dynamic memory is limited to configurable
buffers that can be provided statically.
**Power-loss resilient** - The littlefs is designed for systems that may have
random power failures. The littlefs has strong copy-on-write guarantees and
storage on disk is always kept in a valid state.
**Wear leveling** - Since the most common form of embedded storage is erodible
flash memories, littlefs provides a form of dynamic wear leveling for systems
that can not fit a full flash translation layer.
## Example
Here's a simple example that updates a file named `boot_count` every time
main runs. The program can be interrupted at any time without losing track
of how many times it has been booted and without corrupting the filesystem:
``` c
#include "lfs.h"
/* variables used by the filesystem */
lfs_t lfs;
lfs_file_t file;
/* configuration of the filesystem is provided by this struct */
const struct lfs_config cfg =
{
/* block device operations */
.read = user_provided_block_device_read,
.prog = user_provided_block_device_prog,
.erase = user_provided_block_device_erase,
.sync = user_provided_block_device_sync,
/* block device configuration */
.read_size = 16,
.prog_size = 16,
.block_size = 4096,
.block_count = 128,
.lookahead = 128,
};
/* entry point */
int main(void)
{
/* mount the filesystem */
int err = lfs_mount(&lfs, &cfg);
/* reformat if we can't mount the filesystem
* this should only happen on the first boot
*/
if (err)
{
lfs_format(&lfs, &cfg);
lfs_mount(&lfs, &cfg);
}
/* read current count */
uint32_t boot_count = 0;
lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT);
lfs_file_read(&lfs, &file, &boot_count, sizeof(boot_count));
/* update boot count */
boot_count += 1;
lfs_file_rewind(&lfs, &file);
lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count));
/* remember the storage is not updated until the file is closed successfully */
lfs_file_close(&lfs, &file);
/* release any resources we were using */
lfs_unmount(&lfs);
/* print the boot count */
printf("boot_count: %d\n", boot_count);
}
```
## Usage
Detailed documentation (or at least as much detail as is currently available)
can be found in the comments in [lfs.h](lfs.h).
As you may have noticed, littlefs takes in a configuration structure that
defines how the filesystem operates. The configuration struct provides the
filesystem with the block device operations and dimensions, tweakable
parameters that tradeoff memory usage for performance, and optional
static buffers if the user wants to avoid dynamic memory.
The state of the littlefs is stored in the `lfs_t` type which is left up
to the user to allocate, allowing multiple filesystems to be in use
simultaneously. With the `lfs_t` and configuration struct, a user can
format a block device or mount the filesystem.
Once mounted, the littlefs provides a full set of POSIX-like file and
directory functions, with the deviation that the allocation of filesystem
structures must be provided by the user.
All POSIX operations, such as remove and rename, are atomic, even in event
of power-loss. Additionally, no file updates are actually committed to the
filesystem until sync or close is called on the file.
## Other notes
All littlefs have the potential to return a negative error code. The errors
can be either one of those found in the `enum lfs_error` in [lfs.h](lfs.h),
or an error returned by the user's block device operations.
In the configuration struct, the `prog` and `erase` function provided by the
user may return a `LFS_ERR_CORRUPT` error if the implementation already can
detect corrupt blocks. However, the wear leveling does not depend on the return
code of these functions, instead all data is read back and checked for
integrity.
If your storage caches writes, make sure that the provided `sync` function
flushes all the data to memory and ensures that the next read fetches the data
from memory, otherwise data integrity can not be guaranteed. If the `write`
function does not perform caching, and therefore each `read` or `write` call
hits the memory, the `sync` function can simply return 0.
## Reference material
[DESIGN.md](DESIGN.md) - DESIGN.md contains a fully detailed dive into how
littlefs actually works. I would encourage you to read it since the
solutions and tradeoffs at work here are quite interesting.
[SPEC.md](SPEC.md) - SPEC.md contains the on-disk specification of littlefs
with all the nitty-gritty details. Can be useful for developing tooling.
## Testing
The littlefs comes with a test suite designed to run on a PC using the
[emulated block device](emubd/lfs_emubd.h) found in the emubd directory.
The tests assume a Linux environment and can be started with make:
``` bash
make test
```
## License
The littlefs is provided under the [BSD-3-Clause](https://spdx.org/licenses/BSD-3-Clause.html)
license. See [LICENSE.md](LICENSE.md) for more information. Contributions to
this project are accepted under the same license.
Individual files contain the following tag instead of the full license text.
SPDX-License-Identifier: BSD-3-Clause
This enables machine processing of license information based on the SPDX
License Identifiers that are here available: http://spdx.org/licenses/
## Related projects
[Mbed OS](https://github.com/ARMmbed/mbed-os/tree/master/features/filesystem/littlefs) -
The easiest way to get started with littlefs is to jump into [Mbed](https://os.mbed.com/),
which already has block device drivers for most forms of embedded storage. The
littlefs is available in Mbed OS as the [LittleFileSystem](https://os.mbed.com/docs/latest/reference/littlefilesystem.html)
class.
[littlefs-fuse](https://github.com/geky/littlefs-fuse) - A [FUSE](https://github.com/libfuse/libfuse)
wrapper for littlefs. The project allows you to mount littlefs directly on a
Linux machine. Can be useful for debugging littlefs if you have an SD card
handy.
[littlefs-js](https://github.com/geky/littlefs-js) - A javascript wrapper for
littlefs. I'm not sure why you would want this, but it is handy for demos.
You can see it in action [here](http://littlefs.geky.net/demo.html).
[mklfs](https://github.com/whitecatboard/Lua-RTOS-ESP32/tree/master/components/mklfs/src) -
A command line tool built by the [Lua RTOS](https://github.com/whitecatboard/Lua-RTOS-ESP32)
guys for making littlefs images from a host PC. Supports Windows, Mac OS,
and Linux.
[SPIFFS](https://github.com/pellepl/spiffs) - Another excellent embedded
filesystem for NOR flash. As a more traditional logging filesystem with full
static wear-leveling, SPIFFS will likely outperform littlefs on small
memories such as the internal flash on microcontrollers.
[Dhara](https://github.com/dlbeer/dhara) - An interesting NAND flash
translation layer designed for small MCUs. It offers static wear-leveling and
power-resilience with only a fixed O(|address|) pointer structure stored on
each block and in RAM.

View File

@ -1,370 +0,0 @@
## The little filesystem technical specification
This is the technical specification of the little filesystem. This document
covers the technical details of how the littlefs is stored on disk for
introspection and tooling development. This document assumes you are
familiar with the design of the littlefs, for more info on how littlefs
works check out [DESIGN.md](DESIGN.md).
```
| | | .---._____
.-----. | |
--|o |---| littlefs |
--| |---| |
'-----' '----------'
| | |
```
## Some important details
- The littlefs is a block-based filesystem. This is, the disk is divided into
an array of evenly sized blocks that are used as the logical unit of storage
in littlefs. Block pointers are stored in 32 bits.
- There is no explicit free-list stored on disk, the littlefs only knows what
is in use in the filesystem.
- The littlefs uses the value of 0xffffffff to represent a null block-pointer.
- All values in littlefs are stored in little-endian byte order.
## Directories / Metadata pairs
Metadata pairs form the backbone of the littlefs and provide a system for
atomic updates. Even the superblock is stored in a metadata pair.
As their name suggests, a metadata pair is stored in two blocks, with one block
acting as a redundant backup in case the other is corrupted. These two blocks
could be anywhere in the disk and may not be next to each other, so any
pointers to directory pairs need to be stored as two block pointers.
Here's the layout of metadata blocks on disk:
| offset | size | description |
|--------|---------------|----------------|
| 0x00 | 32 bits | revision count |
| 0x04 | 32 bits | dir size |
| 0x08 | 64 bits | tail pointer |
| 0x10 | size-16 bytes | dir entries |
| 0x00+s | 32 bits | CRC |
**Revision count** - Incremented every update, only the uncorrupted
metadata-block with the most recent revision count contains the valid metadata.
Comparison between revision counts must use sequence comparison since the
revision counts may overflow.
**Dir size** - Size in bytes of the contents in the current metadata block,
including the metadata-pair metadata. Additionally, the highest bit of the
dir size may be set to indicate that the directory's contents continue on the
next metadata-pair pointed to by the tail pointer.
**Tail pointer** - Pointer to the next metadata-pair in the filesystem.
A null pair-pointer (0xffffffff, 0xffffffff) indicates the end of the list.
If the highest bit in the dir size is set, this points to the next
metadata-pair in the current directory, otherwise it points to an arbitrary
metadata-pair. Starting with the superblock, the tail-pointers form a
linked-list containing all metadata-pairs in the filesystem.
**CRC** - 32 bit CRC used to detect corruption from power-lost, from block
end-of-life, or just from noise on the storage bus. The CRC is appended to
the end of each metadata-block. The littlefs uses the standard CRC-32, which
uses a polynomial of 0x04c11db7, initialized with 0xffffffff.
Here's an example of a simple directory stored on disk:
```
(32 bits) revision count = 10 (0x0000000a)
(32 bits) dir size = 154 bytes, end of dir (0x0000009a)
(64 bits) tail pointer = 37, 36 (0x00000025, 0x00000024)
(32 bits) CRC = 0xc86e3106
00000000: 0a 00 00 00 9a 00 00 00 25 00 00 00 24 00 00 00 ........%...$...
00000010: 22 08 00 03 05 00 00 00 04 00 00 00 74 65 61 22 "...........tea"
00000020: 08 00 06 07 00 00 00 06 00 00 00 63 6f 66 66 65 ...........coffe
00000030: 65 22 08 00 04 09 00 00 00 08 00 00 00 73 6f 64 e"...........sod
00000040: 61 22 08 00 05 1d 00 00 00 1c 00 00 00 6d 69 6c a"...........mil
00000050: 6b 31 22 08 00 05 1f 00 00 00 1e 00 00 00 6d 69 k1"...........mi
00000060: 6c 6b 32 22 08 00 05 21 00 00 00 20 00 00 00 6d lk2"...!... ...m
00000070: 69 6c 6b 33 22 08 00 05 23 00 00 00 22 00 00 00 ilk3"...#..."...
00000080: 6d 69 6c 6b 34 22 08 00 05 25 00 00 00 24 00 00 milk4"...%...$..
00000090: 00 6d 69 6c 6b 35 06 31 6e c8 .milk5.1n.
```
A note about the tail pointer linked-list: Normally, this linked-list is
threaded through the entire filesystem. However, after power-loss this
linked-list may become out of sync with the rest of the filesystem.
- The linked-list may contain a directory that has actually been removed
- The linked-list may contain a metadata pair that has not been updated after
a block in the pair has gone bad.
The threaded linked-list must be checked for these errors before it can be
used reliably. Fortunately, the threaded linked-list can simply be ignored
if littlefs is mounted read-only.
## Entries
Each metadata block contains a series of entries that follow a standard
layout. An entry contains the type of the entry, along with a section for
entry-specific data, attributes, and a name.
Here's the layout of entries on disk:
| offset | size | description |
|---------|------------------------|----------------------------|
| 0x0 | 8 bits | entry type |
| 0x1 | 8 bits | entry length |
| 0x2 | 8 bits | attribute length |
| 0x3 | 8 bits | name length |
| 0x4 | entry length bytes | entry-specific data |
| 0x4+e | attribute length bytes | system-specific attributes |
| 0x4+e+a | name length bytes | entry name |
**Entry type** - Type of the entry, currently this is limited to the following:
- 0x11 - file entry
- 0x22 - directory entry
- 0x2e - superblock entry
Additionally, the type is broken into two 4 bit nibbles, with the upper nibble
specifying the type's data structure used when scanning the filesystem. The
lower nibble clarifies the type further when multiple entries share the same
data structure.
The highest bit is reserved for marking the entry as "moved". If an entry
is marked as "moved", the entry may also exist somewhere else in the
filesystem. If the entry exists elsewhere, this entry must be treated as
though it does not exist.
**Entry length** - Length in bytes of the entry-specific data. This does
not include the entry type size, attributes, or name. The full size in bytes
of the entry is 4 + entry length + attribute length + name length.
**Attribute length** - Length of system-specific attributes in bytes. Since
attributes are system specific, there is not much guarantee on the values in
this section, and systems are expected to work even when it is empty. See the
[attributes](#entry-attributes) section for more details.
**Name length** - Length of the entry name. Entry names are stored as UTF8,
although most systems will probably only support ASCII. Entry names can not
contain '/' and can not be '.' or '..' as these are a part of the syntax of
filesystem paths.
Here's an example of a simple entry stored on disk:
```
(8 bits) entry type = file (0x11)
(8 bits) entry length = 8 bytes (0x08)
(8 bits) attribute length = 0 bytes (0x00)
(8 bits) name length = 12 bytes (0x0c)
(8 bytes) entry data = 05 00 00 00 20 00 00 00
(12 bytes) entry name = smallavacado
00000000: 11 08 00 0c 05 00 00 00 20 00 00 00 73 6d 61 6c ........ ...smal
00000010: 6c 61 76 61 63 61 64 6f lavacado
```
## Superblock
The superblock is the anchor for the littlefs. The superblock is stored as
a metadata pair containing a single superblock entry. It is through the
superblock that littlefs can access the rest of the filesystem.
The superblock can always be found in blocks 0 and 1, however fetching the
superblock requires knowing the block size. The block size can be guessed by
searching the beginning of disk for the string "littlefs", although currently
the filesystems relies on the user providing the correct block size.
The superblock is the most valuable block in the filesystem. It is updated
very rarely, only during format or when the root directory must be moved. It
is encouraged to always write out both superblock pairs even though it is not
required.
Here's the layout of the superblock entry:
| offset | size | description |
|--------|------------------------|----------------------------------------|
| 0x00 | 8 bits | entry type (0x2e for superblock entry) |
| 0x01 | 8 bits | entry length (20 bytes) |
| 0x02 | 8 bits | attribute length |
| 0x03 | 8 bits | name length (8 bytes) |
| 0x04 | 64 bits | root directory |
| 0x0c | 32 bits | block size |
| 0x10 | 32 bits | block count |
| 0x14 | 32 bits | version |
| 0x18 | attribute length bytes | system-specific attributes |
| 0x18+a | 8 bytes | magic string ("littlefs") |
**Root directory** - Pointer to the root directory's metadata pair.
**Block size** - Size of the logical block size used by the filesystem.
**Block count** - Number of blocks in the filesystem.
**Version** - The littlefs version encoded as a 32 bit value. The upper 16 bits
encodes the major version, which is incremented when a breaking-change is
introduced in the filesystem specification. The lower 16 bits encodes the
minor version, which is incremented when a backwards-compatible change is
introduced. Non-standard Attribute changes do not change the version. This
specification describes version 1.1 (0x00010001), which is the first version
of littlefs.
**Magic string** - The magic string "littlefs" takes the place of an entry
name.
Here's an example of a complete superblock:
```
(32 bits) revision count = 3 (0x00000003)
(32 bits) dir size = 52 bytes, end of dir (0x00000034)
(64 bits) tail pointer = 3, 2 (0x00000003, 0x00000002)
(8 bits) entry type = superblock (0x2e)
(8 bits) entry length = 20 bytes (0x14)
(8 bits) attribute length = 0 bytes (0x00)
(8 bits) name length = 8 bytes (0x08)
(64 bits) root directory = 3, 2 (0x00000003, 0x00000002)
(32 bits) block size = 512 bytes (0x00000200)
(32 bits) block count = 1024 blocks (0x00000400)
(32 bits) version = 1.1 (0x00010001)
(8 bytes) magic string = littlefs
(32 bits) CRC = 0xc50b74fa
00000000: 03 00 00 00 34 00 00 00 03 00 00 00 02 00 00 00 ....4...........
00000010: 2e 14 00 08 03 00 00 00 02 00 00 00 00 02 00 00 ................
00000020: 00 04 00 00 01 00 01 00 6c 69 74 74 6c 65 66 73 ........littlefs
00000030: fa 74 0b c5 .t..
```
## Directory entries
Directories are stored in entries with a pointer to the first metadata pair
in the directory. Keep in mind that a directory may be composed of multiple
metadata pairs connected by the tail pointer when the highest bit in the dir
size is set.
Here's the layout of a directory entry:
| offset | size | description |
|--------|------------------------|-----------------------------------------|
| 0x0 | 8 bits | entry type (0x22 for directory entries) |
| 0x1 | 8 bits | entry length (8 bytes) |
| 0x2 | 8 bits | attribute length |
| 0x3 | 8 bits | name length |
| 0x4 | 64 bits | directory pointer |
| 0xc | attribute length bytes | system-specific attributes |
| 0xc+a | name length bytes | directory name |
**Directory pointer** - Pointer to the first metadata pair in the directory.
Here's an example of a directory entry:
```
(8 bits) entry type = directory (0x22)
(8 bits) entry length = 8 bytes (0x08)
(8 bits) attribute length = 0 bytes (0x00)
(8 bits) name length = 3 bytes (0x03)
(64 bits) directory pointer = 5, 4 (0x00000005, 0x00000004)
(3 bytes) name = tea
00000000: 22 08 00 03 05 00 00 00 04 00 00 00 74 65 61 "...........tea
```
## File entries
Files are stored in entries with a pointer to the head of the file and the
size of the file. This is enough information to determine the state of the
CTZ skip-list that is being referenced.
How files are actually stored on disk is a bit complicated. The full
explanation of CTZ skip-lists can be found in [DESIGN.md](DESIGN.md#ctz-skip-lists).
A terribly quick summary: For every nth block where n is divisible by 2^x,
the block contains a pointer to block n-2^x. These pointers are stored in
increasing order of x in each block of the file preceding the data in the
block.
The maximum number of pointers in a block is bounded by the maximum file size
divided by the block size. With 32 bits for file size, this results in a
minimum block size of 104 bytes.
Here's the layout of a file entry:
| offset | size | description |
|--------|------------------------|------------------------------------|
| 0x0 | 8 bits | entry type (0x11 for file entries) |
| 0x1 | 8 bits | entry length (8 bytes) |
| 0x2 | 8 bits | attribute length |
| 0x3 | 8 bits | name length |
| 0x4 | 32 bits | file head |
| 0x8 | 32 bits | file size |
| 0xc | attribute length bytes | system-specific attributes |
| 0xc+a | name length bytes | directory name |
**File head** - Pointer to the block that is the head of the file's CTZ
skip-list.
**File size** - Size of file in bytes.
Here's an example of a file entry:
```
(8 bits) entry type = file (0x11)
(8 bits) entry length = 8 bytes (0x08)
(8 bits) attribute length = 0 bytes (0x00)
(8 bits) name length = 12 bytes (0x03)
(32 bits) file head = 543 (0x0000021f)
(32 bits) file size = 256 KB (0x00040000)
(12 bytes) name = largeavacado
00000000: 11 08 00 0c 1f 02 00 00 00 00 04 00 6c 61 72 67 ............large
00000010: 65 61 76 61 63 61 64 6f eavacado
```
## Entry attributes
Each dir entry can have up to 256 bytes of system-specific attributes. Since
these attributes are system-specific, they may not be portable between
different systems. For this reason, all attributes must be optional. A minimal
littlefs driver must be able to get away with supporting no attributes at all.
For some level of portability, littlefs has a simple scheme for attributes.
Each attribute is prefixes with an 8-bit type that indicates what the attribute
is. The length of attributes may also be determined from this type. Attributes
in an entry should be sorted based on portability, since attribute parsing
will end when it hits the first attribute it does not understand.
Each system should choose a 4-bit value to prefix all attribute types with to
avoid conflicts with other systems. Additionally, littlefs drivers that support
attributes should provide a "ignore attributes" flag to users in case attribute
conflicts do occur.
Attribute types prefixes with 0x0 and 0xf are currently reserved for future
standard attributes. Standard attributes will be added to this document in
that case.
Here's an example of non-standard time attribute:
```
(8 bits) attribute type = time (0xc1)
(72 bits) time in seconds = 1506286115 (0x0059c81a23)
00000000: c1 23 1a c8 59 00 .#..Y.
```
Here's an example of non-standard permissions attribute:
```
(8 bits) attribute type = permissions (0xc2)
(16 bits) permission bits = rw-rw-r-- (0x01b4)
00000000: c2 b4 01 ...
```
Here's what a dir entry may look like with these attributes:
```
(8 bits) entry type = file (0x11)
(8 bits) entry length = 8 bytes (0x08)
(8 bits) attribute length = 9 bytes (0x09)
(8 bits) name length = 12 bytes (0x0c)
(8 bytes) entry data = 05 00 00 00 20 00 00 00
(8 bits) attribute type = time (0xc1)
(72 bits) time in seconds = 1506286115 (0x0059c81a23)
(8 bits) attribute type = permissions (0xc2)
(16 bits) permission bits = rw-rw-r-- (0x01b4)
(12 bytes) entry name = smallavacado
00000000: 11 08 09 0c 05 00 00 00 20 00 00 00 c1 23 1a c8 ........ ....#..
00000010: 59 00 c2 b4 01 73 6d 61 6c 6c 61 76 61 63 61 64 Y....smallavacad
00000020: 6f o
```

File diff suppressed because it is too large Load Diff

View File

@ -1,673 +0,0 @@
/****************************************************************************
* fs/littlefs/lfs.h
*
* This file is a part of NuttX:
*
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
*
* Ported by:
*
* Copyright (C) 2019 Pinecone Inc. All rights reserved.
* Author: lihaichen <li8303@163.com>
*
* This port derives from ARM mbed logic which has a compatible 3-clause
* BSD license:
*
* Copyright (c) 2017, Arm Limited. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the names ARM, NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __FS_LITTLEFS_LFS_H
#define __FS_LITTLEFS_LFS_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
#include <stdbool.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Version info */
/* Software library version
* Major (top-nibble), incremented on backwards incompatible changes
* Minor (bottom-nibble), incremented on feature additions
*/
#define LFS_VERSION 0x00010007
#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
/* Version of On-disk data structures
* Major (top-nibble), incremented on backwards incompatible changes
* Minor (bottom-nibble), incremented on feature additions
*/
#define LFS_DISK_VERSION 0x00010001
#define LFS_DISK_VERSION_MAJOR (0xffff & (LFS_DISK_VERSION >> 16))
#define LFS_DISK_VERSION_MINOR (0xffff & (LFS_DISK_VERSION >> 0))
/* Max name size in bytes */
#ifndef LFS_NAME_MAX
# define LFS_NAME_MAX NAME_MAX
#endif
/* Max file size in bytes */
#ifndef LFS_FILE_MAX
# define LFS_FILE_MAX 2147483647
#endif
/****************************************************************************
* Public Types
****************************************************************************/
typedef uint32_t lfs_size_t;
typedef uint32_t lfs_off_t;
typedef int32_t lfs_ssize_t;
typedef int32_t lfs_soff_t;
typedef uint32_t lfs_block_t;
/* Possible error codes, these are negative to allow
* valid positive return values
*/
enum lfs_error_e
{
LFS_ERR_OK = 0, /* No error */
LFS_ERR_IO = -5, /* Error during device operation */
LFS_ERR_CORRUPT = -52, /* Corrupted */
LFS_ERR_NOENT = -2, /* No directory entry */
LFS_ERR_EXIST = -17, /* Entry already exists */
LFS_ERR_NOTDIR = -20, /* Entry is not a dir */
LFS_ERR_ISDIR = -21, /* Entry is a dir */
LFS_ERR_NOTEMPTY = -39, /* Dir is not empty */
LFS_ERR_BADF = -9, /* Bad file number */
LFS_ERR_FBIG = -27, /* File too large */
LFS_ERR_INVAL = -22, /* Invalid parameter */
LFS_ERR_NOSPC = -28, /* No space left on device */
LFS_ERR_NOMEM = -12, /* No more memory available */
};
/* File types */
enum lfs_type_e
{
LFS_TYPE_REG = 0x11,
LFS_TYPE_DIR = 0x22,
LFS_TYPE_SUPERBLOCK = 0x2e,
};
/* File open flags */
enum lfs_open_flags_e
{
/* open flags */
LFS_O_RDONLY = 1, /* Open a file as read only */
LFS_O_WRONLY = 2, /* Open a file as write only */
LFS_O_RDWR = 3, /* Open a file as read and write */
LFS_O_CREAT = 0x0100, /* Create a file if it does not exist */
LFS_O_EXCL = 0x0200, /* Fail if a file already exists */
LFS_O_TRUNC = 0x0400, /* Truncate the existing file to zero size */
LFS_O_APPEND = 0x0800, /* Move to end of file on every write */
/* internally used flags */
LFS_F_DIRTY = 0x10000, /* File does not match storage */
LFS_F_WRITING = 0x20000, /* File has been written since last flush */
LFS_F_READING = 0x40000, /* File has been read since last flush */
LFS_F_ERRED = 0x80000, /* An error occurred during write */
};
/* File seek flags */
enum lfs_whence_flags_e
{
LFS_SEEK_SET = 0, /* Seek relative to an absolute position */
LFS_SEEK_CUR = 1, /* Seek relative to the current file position */
LFS_SEEK_END = 2, /* Seek relative to the end of the file */
};
/* Configuration provided during initialization of the littlefs */
struct lfs_config_s
{
/* Opaque user provided context that can be used to pass
* information to the block device operations
*/
FAR void *context;
/* Read a region in a block. Negative error codes are propagated
* to the user.
*/
CODE int (*read)(FAR const struct lfs_config_s *c, lfs_block_t block,
lfs_off_t off, FAR void *buffer, lfs_size_t size);
/* Program a region in a block. The block must have previously
* been erased. Negative error codes are propagated to the user.
* May return LFS_ERR_CORRUPT if the block should be considered bad.
*/
CODE int (*prog)(FAR const struct lfs_config_s *c, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size);
/* Erase a block. A block must be erased before being programmed.
* The state of an erased block is undefined. Negative error codes
* are propagated to the user.
* May return LFS_ERR_CORRUPT if the block should be considered bad.
*/
CODE int (*erase)(FAR const struct lfs_config_s *c, lfs_block_t block);
/* Sync the state of the underlying block device. Negative error codes
* are propagated to the user.
*/
CODE int (*sync)(FAR const struct lfs_config_s *c);
/* Minimum size of a block read. This determines the size of read buffers.
* This may be larger than the physical read size to improve performance
* by caching more of the block device.
*/
lfs_size_t read_size;
/* Minimum size of a block program. This determines the size of program
* buffers. This may be larger than the physical program size to improve
* performance by caching more of the block device.
* Must be a multiple of the read size.
*/
lfs_size_t prog_size;
/* Size of an erasable block. This does not impact ram consumption and
* may be larger than the physical erase size. However, this should be
* kept small as each file currently takes up an entire block.
* Must be a multiple of the program size.
*/
lfs_size_t block_size;
/* Number of erasable blocks on the device. */
lfs_size_t block_count;
/* Number of blocks to lookahead during block allocation. A larger
* lookahead reduces the number of passes required to allocate a block.
* The lookahead buffer requires only 1 bit per block so it can be quite
* large with little ram impact. Should be a multiple of 32.
*/
lfs_size_t lookahead;
/* Optional, statically allocated read buffer. Must be read sized. */
FAR void *read_buffer;
/* Optional, statically allocated program buffer. Must be program sized. */
FAR void *prog_buffer;
/* Optional, statically allocated lookahead buffer. Must be 1 bit per
* lookahead block.
*/
FAR void *lookahead_buffer;
/* Optional, statically allocated buffer for files. Must be program sized.
* If enabled, only one file may be opened at a time.
*/
FAR void *file_buffer;
};
/* Optional configuration provided during lfs_file_opencfg */
struct lfs_file_config_s
{
/* Optional, statically allocated buffer for files. Must be program sized.
* If NULL, malloc will be used by default.
*/
FAR void *buffer;
};
/* File info structure */
struct lfs_info_s
{
/* Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR */
uint8_t type;
/* Size of the file, only valid for REG files */
lfs_size_t size;
/* Name of the file stored as a null-terminated string */
char name[LFS_NAME_MAX + 1];
};
/* littlefs data structures */
typedef struct lfs_entry_s
{
lfs_off_t off;
struct lfs_disk_entry_s
{
uint8_t type;
uint8_t elen;
uint8_t alen;
uint8_t nlen;
union
{
struct
{
lfs_block_t head;
lfs_size_t size;
} file;
lfs_block_t dir[2];
} u;
} d;
} lfs_entry_t;
typedef struct lfs_cache_s
{
lfs_block_t block;
lfs_off_t off;
FAR uint8_t *buffer;
} lfs_cache_t;
typedef struct lfs_file_s
{
FAR struct lfs_file_s *next;
lfs_block_t pair[2];
lfs_off_t poff;
lfs_block_t head;
lfs_size_t size;
FAR const struct lfs_file_config_s *cfg;
uint32_t flags;
lfs_off_t pos;
lfs_block_t block;
lfs_off_t off;
lfs_cache_t cache;
} lfs_file_t;
typedef struct lfs_dir_s
{
FAR struct lfs_dir_s *next;
lfs_block_t pair[2];
lfs_off_t off;
lfs_block_t head[2];
lfs_off_t pos;
struct lfs_disk_dir_s
{
uint32_t rev;
lfs_size_t size;
lfs_block_t tail[2];
} d;
} lfs_dir_t;
typedef struct lfs_superblock_s
{
lfs_off_t off;
struct lfs_disk_superblock_s
{
uint8_t type;
uint8_t elen;
uint8_t alen;
uint8_t nlen;
lfs_block_t root[2];
uint32_t block_size;
uint32_t block_count;
uint32_t version;
char magic[8];
} d;
} lfs_superblock_t;
typedef struct lfs_free_s
{
lfs_block_t off;
lfs_block_t size;
lfs_block_t i;
lfs_block_t ack;
FAR uint32_t *buffer;
} lfs_free_t;
/* The littlefs type */
typedef struct lfs_s
{
FAR const struct lfs_config_s *cfg;
lfs_block_t root[2];
FAR lfs_file_t *files;
lfs_dir_t *dirs;
lfs_cache_t rcache;
lfs_cache_t pcache;
lfs_free_t free;
bool deorphaned;
bool moving;
} lfs_t;
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef __cplusplus
extern "C"
{
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/* Filesystem functions */
/* Format a block device with the littlefs
*
* Requires a littlefs object and config struct. This clobbers the littlefs
* object, and does not leave the filesystem mounted. The config struct must
* be zeroed for defaults and backwards compatibility.
*
* Returns a negative error code on failure.
*/
int lfs_format(FAR lfs_t *lfs, FAR const struct lfs_config_s *config);
/* Mounts a littlefs
*
* Requires a littlefs object and config struct. Multiple filesystems
* may be mounted simultaneously with multiple littlefs objects. Both
* lfs and config must be allocated while mounted. The config struct must
* be zeroed for defaults and backwards compatibility.
*
* Returns a negative error code on failure.
*/
int lfs_mount(FAR lfs_t *lfs, FAR const struct lfs_config_s *config);
/* Unmounts a littlefs
*
* Does nothing besides releasing any allocated resources.
* Returns a negative error code on failure.
*/
int lfs_unmount(FAR lfs_t *lfs);
/* General operations */
/* Removes a file or directory
*
* If removing a directory, the directory must be empty.
* Returns a negative error code on failure.
*/
int lfs_remove(FAR lfs_t *lfs, FAR const char *path);
/* Rename or move a file or directory
*
* If the destination exists, it must match the source in type.
* If the destination is a directory, the directory must be empty.
*
* Returns a negative error code on failure.
*/
int lfs_rename(FAR lfs_t *lfs, FAR const char *oldpath, FAR
const char *newpath);
/* Find info about a file or directory
*
* Fills out the info structure, based on the specified file or directory.
* Returns a negative error code on failure.
*/
int lfs_stat(FAR lfs_t *lfs, FAR const char *path,
FAR struct lfs_info_s *info);
/* File operations */
/* Open a file
*
* The mode that the file is opened in is determined by the flags, which
* are values from the enum lfs_open_flags that are bitwise-ored together.
*
* Returns a negative error code on failure.
*/
int lfs_file_open(FAR lfs_t *lfs, FAR lfs_file_t *file,
FAR const char *path, int flags);
/* Open a file with extra configuration
*
* The mode that the file is opened in is determined by the flags, which
* are values from the enum lfs_open_flags that are bitwise-ored together.
*
* The config struct provides additional config options per file as described
* above. The config struct must be allocated while the file is open, and the
* config struct must be zeroed for defaults and backwards compatibility.
*
* Returns a negative error code on failure.
*/
int lfs_file_opencfg(FAR lfs_t *lfs, FAR lfs_file_t *file,
FAR const char *path, int flags,
FAR const struct lfs_file_config_s *config);
/* Close a file
*
* Any pending writes are written out to storage as though
* sync had been called and releases any allocated resources.
*
* Returns a negative error code on failure.
*/
int lfs_file_close(FAR lfs_t *lfs, FAR lfs_file_t *file);
/* Synchronize a file on storage
*
* Any pending writes are written out to storage.
* Returns a negative error code on failure.
*/
int lfs_file_sync(FAR lfs_t *lfs, FAR lfs_file_t *file);
/* Read data from file
*
* Takes a buffer and size indicating where to store the read data.
* Returns the number of bytes read, or a negative error code on failure.
*/
lfs_ssize_t lfs_file_read(FAR lfs_t *lfs, FAR lfs_file_t *file,
FAR void *buffer, lfs_size_t size);
/* Write data to file
*
* Takes a buffer and size indicating the data to write. The file will not
* actually be updated on the storage until either sync or close is called.
*
* Returns the number of bytes written, or a negative error code on failure.
*/
lfs_ssize_t lfs_file_write(FAR lfs_t *lfs, FAR lfs_file_t *file,
FAR const void *buffer, lfs_size_t size);
/* Change the position of the file
*
* The change in position is determined by the offset and whence flag.
* Returns the old position of the file, or a negative error code on failure.
*/
lfs_soff_t lfs_file_seek(FAR lfs_t *lfs, FAR lfs_file_t *file,
lfs_soff_t off, int whence);
/* Truncates the size of the file to the specified size
*
* Returns a negative error code on failure.
*/
int lfs_file_truncate(FAR lfs_t *lfs, FAR lfs_file_t *file,
lfs_off_t size);
/* Return the position of the file
*
* Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR)
* Returns the position of the file, or a negative error code on failure.
*/
lfs_soff_t lfs_file_tell(FAR lfs_t *lfs, FAR lfs_file_t *file);
/* Change the position of the file to the beginning of the file
*
* Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR)
* Returns a negative error code on failure.
*/
int lfs_file_rewind(FAR lfs_t *lfs, FAR lfs_file_t *file);
/* Return the size of the file
*
* Similar to lfs_file_seek(lfs, file, 0, LFS_SEEK_END)
* Returns the size of the file, or a negative error code on failure.
*/
lfs_soff_t lfs_file_size(FAR lfs_t *lfs, FAR lfs_file_t *file);
/* Directory operations */
/* Create a directory
*
* Returns a negative error code on failure.
*/
int lfs_mkdir(FAR lfs_t *lfs, FAR const char *path);
/* Open a directory
*
* Once open a directory can be used with read to iterate over files.
* Returns a negative error code on failure.
*/
int lfs_dir_open(FAR lfs_t *lfs, FAR lfs_dir_t *dir, FAR const char *path);
/* Close a directory
*
* Releases any allocated resources.
* Returns a negative error code on failure.
*/
int lfs_dir_close(FAR lfs_t *lfs, FAR lfs_dir_t *dir);
/* Read an entry in the directory
*
* Fills out the info structure, based on the specified file or directory.
* Returns a negative error code on failure.
*/
int lfs_dir_read(FAR lfs_t *lfs, FAR lfs_dir_t *dir,
FAR struct lfs_info_s *info);
/* Change the position of the directory
*
* The new off must be a value previous returned from tell and specifies
* an absolute offset in the directory seek.
*
* Returns a negative error code on failure.
*/
int lfs_dir_seek(FAR lfs_t *lfs, FAR lfs_dir_t *dir, lfs_off_t off);
/* Return the position of the directory
*
* The returned offset is only meant to be consumed by seek and may not make
* sense, but does indicate the current position in the directory iteration.
*
* Returns the position of the directory, or a negative error code on failure
*/
lfs_soff_t lfs_dir_tell(FAR lfs_t *lfs, FAR lfs_dir_t *dir);
/* Change the position of the directory to the beginning of the directory
*
* Returns a negative error code on failure.
*/
int lfs_dir_rewind(FAR lfs_t *lfs, FAR lfs_dir_t *dir);
/* Miscellaneous littlefs specific operations */
/* Traverse through all blocks in use by the filesystem
*
* The provided callback will be called with each block address that is
* currently in use by the filesystem. This can be used to determine which
* blocks are in use or how much of the storage is available.
*
* Returns a negative error code on failure.
*/
int lfs_traverse(FAR lfs_t *lfs, CODE int (*cb)(FAR void *, lfs_block_t),
FAR void *data);
/* Prunes any recoverable errors that may have occurred in the filesystem
*
* Not needed to be called by user unless an operation is interrupted
* but the filesystem is still mounted. This is already called on first
* allocation.
*
* Returns a negative error code on failure.
*/
int lfs_deorphan(FAR lfs_t *lfs);
#ifdef __cplusplus
}
#endif
#endif /* __FS_LITTLEFS_LFS_H */

View File

@ -1,83 +0,0 @@
/****************************************************************************
* fs/littlefs/lfs_util.c
*
* This file is a part of NuttX:
*
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
*
* Ported by:
*
* Copyright (C) 2019 Pinecone Inc. All rights reserved.
* Author: lihaichen <li8303@163.com>
*
* This port derives from ARM mbed logic which has a compatible 3-clause
* BSD license:
*
* Copyright (c) 2017, Arm Limited. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the names ARM, NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "lfs.h"
#include "lfs_util.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/* Only compile if user does not provide custom config */
#ifndef LFS_CONFIG
/* Software CRC implementation with small lookup table */
void lfs_crc(FAR uint32_t *crc, FAR const void *buffer, size_t size)
{
static const uint32_t rtable[16] =
{
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4,
0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
};
FAR const uint8_t *data = buffer;
size_t i;
for (i = 0; i < size; i++)
{
*crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 0)) & 0xf];
*crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 4)) & 0xf];
}
}
#endif

View File

@ -1,275 +0,0 @@
/****************************************************************************
* fs/littlefs/lfs_util.h
*
* This file is a part of NuttX:
*
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
*
* Ported by:
*
* Copyright (C) 2019 Pinecone Inc. All rights reserved.
* Author: lihaichen <li8303@163.com>
*
* This port derives from ARM mbed logic which has a compatible 3-clause
* BSD license:
*
* Copyright (c) 2017, Arm Limited. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the names ARM, NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __FS_LITTLEFS_LFS_UTIL_H
#define __FS_LITTLEFS_LFS_UTIL_H
/****************************************************************************
* Included Files
****************************************************************************/
/* Users can override lfs_util.h with their own configuration by defining
* LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).
*
* If LFS_CONFIG is used, none of the default utils will be emitted and must be
* provided by the config file. To start I would suggest copying lfs_util.h and
* modifying as needed.
*/
#ifdef LFS_CONFIG
# define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
# define LFS_STRINGIZE2(x) #x
# include LFS_STRINGIZE(LFS_CONFIG)
#else
/* System includes */
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#ifndef LFS_NO_MALLOC
# include <nuttx/kmalloc.h>
#endif
#ifndef LFS_NO_ASSERT
# include <assert.h>
#endif
#if !defined(LFS_NO_DEBUG) || !defined(LFS_NO_WARN) || !defined(LFS_NO_ERROR)
# include <debug.h>
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Macros, may be replaced by system specific wrappers. Arguments to these
* macros must not have side-effects as the macros can be removed for a smaller
* code footprint
*/
/* Logging functions */
#ifndef LFS_NO_DEBUG
# define LFS_DEBUG(fmt, ...) \
finfo("lfs debug:%d: " fmt "\n", __LINE__, __VA_ARGS__)
#else
# define LFS_DEBUG(fmt, ...)
#endif
#ifndef LFS_NO_WARN
# define LFS_WARN(fmt, ...) \
fwarn("lfs warn:%d: " fmt "\n", __LINE__, __VA_ARGS__)
#else
# define LFS_WARN(fmt, ...)
#endif
#ifndef LFS_NO_ERROR
# define LFS_ERROR(fmt, ...) \
ferr("lfs error:%d: " fmt "\n", __LINE__, __VA_ARGS__)
#else
# define LFS_ERROR(fmt, ...)
#endif
/* Runtime assertions */
#ifndef LFS_NO_ASSERT
# define LFS_ASSERT(test) DEBUGASSERT(test)
#else
# define LFS_ASSERT(test)
#endif
/****************************************************************************
* Public Types
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef __cplusplus
extern "C"
{
#endif
/****************************************************************************
* Inline Functions
****************************************************************************/
/* Builtin functions, these may be replaced by more efficient
* toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
* expensive basic C implementation for debugging purposes
*/
/* Min/max functions for unsigned 32-bit numbers */
static inline uint32_t lfs_max(uint32_t a, uint32_t b)
{
return (a > b) ? a : b;
}
static inline uint32_t lfs_min(uint32_t a, uint32_t b)
{
return (a < b) ? a : b;
}
/* Find the next smallest power of 2 less than or equal to a */
static inline uint32_t lfs_npw2(uint32_t a)
{
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
return 32 - __builtin_clz(a - 1);
#else
uint32_t r = 0;
uint32_t s;
a -= 1;
s = (a > 0xffff) << 4;
a >>= s;
r |= s;
s = (a > 0xff) << 3;
a >>= s;
r |= s;
s = (a > 0xf) << 2;
a >>= s;
r |= s;
s = (a > 0x3) << 1;
a >>= s;
r |= s;
return (r | (a >> 1)) + 1;
#endif
}
/* Count the number of trailing binary zeros in a
* lfs_ctz(0) may be undefined
*/
static inline uint32_t lfs_ctz(uint32_t a)
{
#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
return __builtin_ctz(a);
#else
return lfs_npw2((a & -a) + 1) - 1;
#endif
}
/* Count the number of binary ones in a */
static inline uint32_t lfs_popc(uint32_t a)
{
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
return __builtin_popcount(a);
#else
a = a - ((a >> 1) & 0x55555555);
a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
#endif
}
/* Find the sequence comparison of a and b, this is the distance
* between a and b ignoring overflow
*/
static inline int lfs_scmp(uint32_t a, uint32_t b)
{
return (int)(unsigned)(a - b);
}
/* Convert from 32-bit little-endian to native order */
static inline uint32_t lfs_fromle32(uint32_t a)
{
#if !defined(CONFIG_ENDIAN_BIG)
return a;
#elif !defined(LFS_NO_INTRINSICS)
return __builtin_bswap32(a);
#else
return (((uint8_t *)&a)[0] << 0) | (((uint8_t *)&a)[1] << 8) |
(((uint8_t *)&a)[2] << 16) | (((uint8_t *)&a)[3] << 24);
#endif
}
/* Convert to 32-bit little-endian from native order */
static inline uint32_t lfs_tole32(uint32_t a)
{
return lfs_fromle32(a);
}
/* Allocate memory, only used if buffers are not provided to littlefs */
static inline void *lfs_malloc(size_t size)
{
#ifndef LFS_NO_MALLOC
return kmm_malloc(size);
#else
return NULL;
#endif
}
/* Deallocate memory, only used if buffers are not provided to littlefs */
static inline void lfs_free(FAR void *p)
{
#ifndef LFS_NO_MALLOC
kmm_free(p);
#else
(void)p;
#endif
}
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/* Calculate CRC-32 with polynomial = 0x04c11db7 */
void lfs_crc(uint32_t *crc, const void *buffer, size_t size);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
#endif /* __FS_LITTLEFS_LFS_UTIL_H */

View File

@ -1,46 +1,20 @@
/****************************************************************************
* fs/littlefs/lfs_vfs.c
*
* This file is a part of NuttX:
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
* http://www.apache.org/licenses/LICENSE-2.0
*
* Ported by:
*
* Copyright (C) 2019 Pinecone Inc. All rights reserved.
* Author: lihaichen <li8303@163.com>
*
* This port derives from ARM mbed logic which has a compatible 3-clause
* BSD license:
*
* Copyright (c) 2017, Arm Limited. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the names ARM, NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
@ -56,14 +30,15 @@
#include <nuttx/fs/dirent.h>
#include <nuttx/fs/fs.h>
#include <nuttx/kmalloc.h>
#include <nuttx/mtd/mtd.h>
#include <nuttx/semaphore.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include "lfs.h"
#include "lfs_util.h"
#include "littlefs/lfs.h"
#include "littlefs/lfs_util.h"
/****************************************************************************
* Private Types
@ -79,7 +54,7 @@ struct littlefs_mountpt_s
sem_t sem;
FAR struct inode *drv;
struct mtd_geometry_s geo;
struct lfs_config_s cfg;
struct lfs_config cfg;
lfs_t lfs;
};
@ -249,7 +224,7 @@ static int littlefs_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_file_s *priv;
FAR struct lfs_file *priv;
FAR struct inode *inode;
int ret;
@ -327,7 +302,7 @@ errsem:
static int littlefs_close(FAR struct file *filep)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_file_s *priv;
FAR struct lfs_file *priv;
FAR struct inode *inode;
int ret;
@ -363,7 +338,7 @@ static ssize_t littlefs_read(FAR struct file *filep, FAR char *buffer,
size_t buflen)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_file_s *priv;
FAR struct lfs_file *priv;
FAR struct inode *inode;
ssize_t ret;
int semret;
@ -401,7 +376,7 @@ static ssize_t littlefs_write(FAR struct file *filep, const char *buffer,
size_t buflen)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_file_s *priv;
FAR struct lfs_file *priv;
FAR struct inode *inode;
ssize_t ret;
int semret;
@ -438,7 +413,7 @@ static ssize_t littlefs_write(FAR struct file *filep, const char *buffer,
static off_t littlefs_seek(FAR struct file *filep, off_t offset, int whence)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_file_s *priv;
FAR struct lfs_file *priv;
FAR struct inode *inode;
off_t ret;
int semret;
@ -505,7 +480,7 @@ static int littlefs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
static int littlefs_sync(FAR struct file *filep)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_file_s *priv;
FAR struct lfs_file *priv;
FAR struct inode *inode;
int ret;
@ -551,7 +526,7 @@ static int littlefs_dup(FAR const struct file *oldp, FAR struct file *newp)
static int littlefs_fstat(FAR const struct file *filep, FAR struct stat *buf)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_file_s *priv;
FAR struct lfs_file *priv;
FAR struct inode *inode;
int ret;
@ -598,7 +573,7 @@ static int littlefs_fstat(FAR const struct file *filep, FAR struct stat *buf)
static int littlefs_truncate(FAR struct file *filep, off_t length)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_file_s *priv;
FAR struct lfs_file *priv;
FAR struct inode *inode;
int ret;
@ -634,7 +609,7 @@ static int littlefs_opendir(FAR struct inode *mountpt,
FAR struct fs_dirent_s *dir)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_dir_s *priv;
FAR struct lfs_dir *priv;
int ret;
/* Recover our private data from the inode instance */
@ -689,7 +664,7 @@ static int littlefs_closedir(FAR struct inode *mountpt,
FAR struct fs_dirent_s *dir)
{
struct littlefs_mountpt_s *fs;
FAR struct lfs_dir_s *priv;
FAR struct lfs_dir *priv;
int ret;
/* Recover our private data from the inode instance */
@ -724,8 +699,8 @@ static int littlefs_readdir(FAR struct inode *mountpt,
FAR struct fs_dirent_s *dir)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_dir_s *priv;
struct lfs_info_s info;
FAR struct lfs_dir *priv;
struct lfs_info info;
int ret;
/* Recover our private data from the inode instance */
@ -777,7 +752,7 @@ static int littlefs_rewinddir(FAR struct inode *mountpt,
FAR struct fs_dirent_s *dir)
{
struct littlefs_mountpt_s *fs;
FAR struct lfs_dir_s *priv;
FAR struct lfs_dir *priv;
int ret;
/* Recover our private data from the inode instance */
@ -815,7 +790,7 @@ static int littlefs_rewinddir(FAR struct inode *mountpt,
*
****************************************************************************/
static int littlefs_read_block(FAR const struct lfs_config_s *c,
static int littlefs_read_block(FAR const struct lfs_config *c,
lfs_block_t block, lfs_off_t off,
FAR void *buffer, lfs_size_t size)
{
@ -843,7 +818,7 @@ static int littlefs_read_block(FAR const struct lfs_config_s *c,
* Name: littlefs_write_block
****************************************************************************/
static int littlefs_write_block(FAR const struct lfs_config_s *c,
static int littlefs_write_block(FAR const struct lfs_config *c,
lfs_block_t block, lfs_off_t off,
FAR const void *buffer, lfs_size_t size)
{
@ -871,7 +846,7 @@ static int littlefs_write_block(FAR const struct lfs_config_s *c,
* Name: littlefs_erase_block
****************************************************************************/
static int littlefs_erase_block(FAR const struct lfs_config_s *c,
static int littlefs_erase_block(FAR const struct lfs_config *c,
lfs_block_t block)
{
FAR struct littlefs_mountpt_s *fs = c->context;
@ -894,7 +869,7 @@ static int littlefs_erase_block(FAR const struct lfs_config_s *c,
* Name: littlefs_sync_block
****************************************************************************/
static int littlefs_sync_block(FAR const struct lfs_config_s *c)
static int littlefs_sync_block(FAR const struct lfs_config *c)
{
FAR struct littlefs_mountpt_s *fs = c->context;
FAR struct inode *drv = fs->drv;
@ -988,21 +963,19 @@ static int littlefs_bind(FAR struct inode *driver, FAR const void *data,
/* Initialize lfs_config structure */
fs->cfg.context = fs;
fs->cfg.read = littlefs_read_block;
fs->cfg.prog = littlefs_write_block;
fs->cfg.erase = littlefs_erase_block;
fs->cfg.sync = littlefs_sync_block;
fs->cfg.read_size = fs->geo.blocksize;
fs->cfg.prog_size = fs->geo.blocksize;
fs->cfg.block_size = fs->geo.erasesize;
fs->cfg.block_count = fs->geo.neraseblocks;
fs->cfg.lookahead = 32 * ((fs->cfg.block_count + 31) / 32);
if (fs->cfg.lookahead > 32 * fs->cfg.read_size)
{
fs->cfg.lookahead = 32 * fs->cfg.read_size;
}
fs->cfg.context = fs;
fs->cfg.read = littlefs_read_block;
fs->cfg.prog = littlefs_write_block;
fs->cfg.erase = littlefs_erase_block;
fs->cfg.sync = littlefs_sync_block;
fs->cfg.read_size = fs->geo.blocksize;
fs->cfg.prog_size = fs->geo.blocksize;
fs->cfg.block_size = fs->geo.erasesize;
fs->cfg.block_count = fs->geo.neraseblocks;
fs->cfg.block_cycles = 500;
fs->cfg.cache_size = fs->geo.blocksize;
fs->cfg.lookahead_size = lfs_min(lfs_alignup(fs->cfg.block_count / 8, 8),
fs->cfg.read_size);
/* Then get information about the littlefs filesystem on the devices
* managed by this driver.
@ -1116,20 +1089,6 @@ static int littlefs_unbind(FAR void *handle, FAR struct inode **driver,
return ret;
}
/****************************************************************************
* Name: littlefs_used_block
****************************************************************************/
static int littlefs_used_block(void *arg, lfs_block_t block)
{
FAR struct statfs *buf = arg;
buf->f_bfree--;
buf->f_bavail--;
return 0;
}
/****************************************************************************
* Name: littlefs_statfs
*
@ -1162,7 +1121,15 @@ static int littlefs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf)
return ret;
}
ret = lfs_traverse(&fs->lfs, littlefs_used_block, buf);
ret = lfs_fs_size(&fs->lfs);
if (ret > 0)
{
buf->f_bfree -= ret;
buf->f_bavail -= ret;
ret = 0;
}
littlefs_semgive(fs);
return ret;
@ -1285,7 +1252,7 @@ static int littlefs_stat(FAR struct inode *mountpt, FAR const char *relpath,
FAR struct stat *buf)
{
FAR struct littlefs_mountpt_s *fs;
struct lfs_info_s info;
struct lfs_info info;
int ret;
memset(buf, 0, sizeof(*buf));

View File

@ -74,7 +74,7 @@ endif
KERNDEPDIRS += sched drivers boards $(ARCH_SRC)
KERNDEPDIRS += fs binfmt
CONTEXTDIRS = boards $(APPDIR)
CONTEXTDIRS = boards fs $(APPDIR)
CLEANDIRS += pass1
ifeq ($(CONFIG_BUILD_FLAT),y)