Skip to content

Commit 9a849cc

Browse files
jimmodpgeorge
authored andcommitted
docs: Add littlefs docs and a filesystem tutorial.
1 parent f2650be commit 9a849cc

File tree

4 files changed

+322
-63
lines changed

4 files changed

+322
-63
lines changed

docs/library/esp32.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,14 @@ This class gives access to the partitions in the device's flash memory.
5656
Returns a 6-tuple ``(type, subtype, addr, size, label, encrypted)``.
5757

5858
.. method:: Partition.readblocks(block_num, buf)
59+
.. method:: Partition.readblocks(block_num, buf, offset)
5960
.. method:: Partition.writeblocks(block_num, buf)
61+
.. method:: Partition.writeblocks(block_num, buf, offset)
6062
.. method:: Partition.ioctl(cmd, arg)
6163

62-
These methods implement the block protocol defined by :class:`uos.AbstractBlockDev`.
64+
These methods implement the simple and :ref:`extended
65+
<block-device-interface>` block protocol defined by
66+
:class:`uos.AbstractBlockDev`.
6367

6468
.. method:: Partition.set_boot()
6569

docs/library/uos.rst

Lines changed: 38 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,35 @@ represented by VFS classes.
178178

179179
Build a FAT filesystem on *block_dev*.
180180

181+
.. class:: VfsLfs1(block_dev)
182+
183+
Create a filesystem object that uses the `littlefs v1 filesystem format`_.
184+
Storage of the littlefs filesystem is provided by *block_dev*, which must
185+
support the :ref:`extended interface <block-device-interface>`.
186+
Objects created by this constructor can be mounted using :func:`mount`.
187+
188+
See :ref:`filesystem` for more information.
189+
190+
.. staticmethod:: mkfs(block_dev)
191+
192+
Build a Lfs1 filesystem on *block_dev*.
193+
194+
.. class:: VfsLfs2(block_dev)
195+
196+
Create a filesystem object that uses the `littlefs v2 filesystem format`_.
197+
Storage of the littlefs filesystem is provided by *block_dev*, which must
198+
support the :ref:`extended interface <block-device-interface>`.
199+
Objects created by this constructor can be mounted using :func:`mount`.
200+
201+
See :ref:`filesystem` for more information.
202+
203+
.. staticmethod:: mkfs(block_dev)
204+
205+
Build a Lfs2 filesystem on *block_dev*.
206+
207+
.. _littlefs v1 filesystem format: https://github.com/ARMmbed/littlefs/tree/v1
208+
.. _littlefs v2 filesystem format: https://github.com/ARMmbed/littlefs
209+
181210
Block devices
182211
-------------
183212

@@ -187,9 +216,15 @@ implementation of this class will usually allow access to the memory-like
187216
functionality a piece of hardware (like flash memory). A block device can be
188217
used by a particular filesystem driver to store the data for its filesystem.
189218

219+
.. _block-device-interface:
220+
221+
Simple and extended interface
222+
.............................
223+
190224
There are two compatible signatures for the ``readblocks`` and ``writeblocks``
191225
methods (see below), in order to support a variety of use cases. A given block
192-
device may implement one form or the other, or both at the same time.
226+
device may implement one form or the other, or both at the same time. The second
227+
form (with the offset parameter) is referred to as the "extended interface".
193228

194229
.. class:: AbstractBlockDev(...)
195230

@@ -247,64 +282,5 @@ device may implement one form or the other, or both at the same time.
247282
(*arg* is unused)
248283
- 6 -- erase a block, *arg* is the block number to erase
249284

250-
By way of example, the following class will implement a block device that stores
251-
its data in RAM using a ``bytearray``::
252-
253-
class RAMBlockDev:
254-
def __init__(self, block_size, num_blocks):
255-
self.block_size = block_size
256-
self.data = bytearray(block_size * num_blocks)
257-
258-
def readblocks(self, block_num, buf):
259-
for i in range(len(buf)):
260-
buf[i] = self.data[block_num * self.block_size + i]
261-
262-
def writeblocks(self, block_num, buf):
263-
for i in range(len(buf)):
264-
self.data[block_num * self.block_size + i] = buf[i]
265-
266-
def ioctl(self, op, arg):
267-
if op == 4: # get number of blocks
268-
return len(self.data) // self.block_size
269-
if op == 5: # get block size
270-
return self.block_size
271-
272-
It can be used as follows::
273-
274-
import uos
275-
276-
bdev = RAMBlockDev(512, 50)
277-
uos.VfsFat.mkfs(bdev)
278-
vfs = uos.VfsFat(bdev)
279-
uos.mount(vfs, '/ramdisk')
280-
281-
An example of a block device that supports both signatures and behaviours of
282-
the :meth:`readblocks` and :meth:`writeblocks` methods is::
283-
284-
class RAMBlockDev:
285-
def __init__(self, block_size, num_blocks):
286-
self.block_size = block_size
287-
self.data = bytearray(block_size * num_blocks)
288-
289-
def readblocks(self, block, buf, offset=0):
290-
addr = block_num * self.block_size + offset
291-
for i in range(len(buf)):
292-
buf[i] = self.data[addr + i]
293-
294-
def writeblocks(self, block_num, buf, offset=None):
295-
if offset is None:
296-
# do erase, then write
297-
for i in range(len(buf) // self.block_size):
298-
self.ioctl(6, block_num + i)
299-
offset = 0
300-
addr = block_num * self.block_size + offset
301-
for i in range(len(buf)):
302-
self.data[addr + i] = buf[i]
303-
304-
def ioctl(self, op, arg):
305-
if op == 4: # block count
306-
return len(self.data) // self.block_size
307-
if op == 5: # block size
308-
return self.block_size
309-
if op == 6: # block erase
310-
return 0
285+
See :ref:`filesystem` for example implementations of block devices using both
286+
protocols.

0 commit comments

Comments
 (0)