Littlefs support. Test scripts adapted to use it.

pull/1/head
Peter Hinch 2019-12-20 15:19:21 +00:00
rodzic d792a2be7f
commit 4624fb41c6
10 zmienionych plików z 71 dodań i 54 usunięć

Wyświetl plik

@ -1,6 +1,6 @@
# 1. MicroPython drivers for nonvolatile memory # 1. MicroPython drivers for nonvolatile memory
These drivers support nonvolatile memory chips. These drivers support nonvolatile memory chips and the littlefs filesystem.
Currently supported devices use technologies having superior performance Currently supported devices use technologies having superior performance
compared to flash. Resultant storage has much higher write endurance. In some compared to flash. Resultant storage has much higher write endurance. In some
@ -18,7 +18,7 @@ The drivers have the following common features:
a `readwrite` method. a `readwrite` method.
3. Alternatively the array can be formatted and mounted as a filesystem using 3. Alternatively the array can be formatted and mounted as a filesystem using
methods in the `uos` module. Any filesystem supported by the MicroPython build methods in the `uos` module. Any filesystem supported by the MicroPython build
may be employed. may be employed: FAT and littlefs have been tested. The latter is recommended.
4. Drivers are portable: buses and pins should be instantiated using the 4. Drivers are portable: buses and pins should be instantiated using the
`machine` module. `machine` module.
5. Buses may be shared with other hardware. This assumes that the application 5. Buses may be shared with other hardware. This assumes that the application
@ -59,6 +59,8 @@ In the table below the Interface column includes page size in bytes.
| Microchip | 24xx64 | I2C 128 | 8KiB | EEPROM | [I2C.md](./i2c/I2C.md) | | Microchip | 24xx64 | I2C 128 | 8KiB | EEPROM | [I2C.md](./i2c/I2C.md) |
| Adafruit | 1895 | I2C n/a | 32KiB | FRAM | [FRAM.md](./fram/FRAM.md) | | Adafruit | 1895 | I2C n/a | 32KiB | FRAM | [FRAM.md](./fram/FRAM.md) |
**STM chip support under development**
Documentation: Documentation:
[SPI.md](./spi/SPI.md) [SPI.md](./spi/SPI.md)
[I2C.md](./i2c/I2C.md) [I2C.md](./i2c/I2C.md)
@ -104,8 +106,8 @@ in the ioctl and (if necessary) implementing a block erase method.
The nature of the drivers in this repo implies that the page size in the ioctl The nature of the drivers in this repo implies that the page size in the ioctl
is arbitrary. Littlefs requires a minimum size of 128 bytes - is arbitrary. Littlefs requires a minimum size of 128 bytes -
[theoretically 104](https://github.com/ARMmbed/littlefs/blob/master/DESIGN.md) [theoretically 104](https://github.com/ARMmbed/littlefs/blob/master/DESIGN.md).
but the driver only allows powers of 2. Testing was done with 512 bytes. The driver only allows powers of 2. Testing was done with 512 bytes.
Currently I have not had success with littlefs but it hasn't yet officially The test programs use littlefs and therefore require MicroPython V1.12 or
been released. The test programs therefore use FAT. later.

Wyświetl plik

@ -62,13 +62,13 @@ class BlockDevice:
# IOCTL protocol. # IOCTL protocol.
def readblocks(self, blocknum, buf, offset=0): def readblocks(self, blocknum, buf, offset=0):
return self.readwrite(offset + (blocknum << self._nbits), buf, True) self.readwrite(offset + (blocknum << self._nbits), buf, True)
def writeblocks(self, blocknum, buf, offset=0): def writeblocks(self, blocknum, buf, offset=None):
offset = 0 if offset is None else offset
self.readwrite(offset + (blocknum << self._nbits), buf, False) self.readwrite(offset + (blocknum << self._nbits), buf, False)
def ioctl(self, op, arg): def ioctl(self, op, arg):
#print("ioctl(%d, %r)" % (op, arg))
if op == 4: # BP_IOCTL_SEC_COUNT if op == 4: # BP_IOCTL_SEC_COUNT
return self._a_bytes >> self._nbits return self._a_bytes >> self._nbits
if op == 5: # BP_IOCTL_SEC_SIZE if op == 5: # BP_IOCTL_SEC_SIZE

Wyświetl plik

@ -79,16 +79,17 @@ Installation: copy files 1 and 2 (optionally 3) to the target filesystem.
The driver supports mounting the FRAM chips as a filesystem. Initially the The driver supports mounting the FRAM chips as a filesystem. Initially the
device will be unformatted so it is necessary to issue code along these lines device will be unformatted so it is necessary to issue code along these lines
to format the device. Code assumes one or more devices: to format the device. Code assumes one or more devices and also assumes the
littlefs filesystem:
```python ```python
import uos import os
from machine import I2C from machine import I2C
from fram_i2c import FRAM from fram_i2c import FRAM
fram = FRAM(I2C(2)) fram = FRAM(I2C(2))
uos.VfsFat.mkfs(fram) # Omit this to mount an existing filesystem # Format the filesystem
vfs = uos.VfsFat(fram) os.VfsLfs2.mkfs(fram) # Omit this to mount an existing filesystem
uos.mount(vfs,'/fram') os.mount(fram,'/fram')
``` ```
The above will reformat a drive with an existing filesystem: to mount an The above will reformat a drive with an existing filesystem: to mount an
existing filesystem simply omit the commented line. existing filesystem simply omit the commented line.

Wyświetl plik

@ -47,21 +47,6 @@ class FRAM(BlockDevice):
productID = ((res[1] & 0x0F) << 8) + res[2] productID = ((res[1] & 0x0F) << 8) + res[2]
return manufacturerID == _MANF_ID and productID == _PRODUCT_ID return manufacturerID == _MANF_ID and productID == _PRODUCT_ID
def __setitem__(self, addr, value):
if isinstance(addr, slice):
return self.wslice(addr, value)
self._buf1[0] = value
self._getaddr(addr, 1)
self._i2c.writevto(self._i2c_addr, (self._addrbuf, self._buf1))
def __getitem__(self, addr):
if isinstance(addr, slice):
return self.rslice(addr)
self._getaddr(addr, 1)
self._i2c.writeto(self._i2c_addr, self._addrbuf)
self._i2c.readfrom_into(self._i2c_addr, self._buf1)
return self._buf1[0]
# In the context of FRAM a page == a chip. # In the context of FRAM a page == a chip.
# Args: an address and a no. of bytes. Set ._i2c_addr to correct chip. # Args: an address and a no. of bytes. Set ._i2c_addr to correct chip.
# Return the no. of bytes available to access on that chip. # Return the no. of bytes available to access on that chip.

Wyświetl plik

@ -77,17 +77,18 @@ Installation: copy files 1 and 2 (optionally 3) to the target filesystem.
# 4. The device driver # 4. The device driver
The driver supports mounting the EEPROM chips as a filesystem. Initially the The driver supports mounting the EEPROM chips as a filesystem. Initially the
device will be unformatted so it is necessary to issue code along these lines to device will be unformatted so it is necessary to issue code along these lines
format the device. Code assumes one or more 64KiB devices: to format the device. Code assumes one or more 64KiB devices and also assumes
the littlefs filesystem:
```python ```python
import uos import os
from machine import I2C from machine import I2C
from eeprom_i2c import EEPROM, T24C512 from eeprom_i2c import EEPROM, T24C512
eep = EEPROM(I2C(2), T24C512) eep = EEPROM(I2C(2), T24C512)
uos.VfsFat.mkfs(eep) # Omit this to mount an existing filesystem # Format the filesystem
vfs = uos.VfsFat(eep) os.VfsLfs2.mkfs(eep) # Omit this to mount an existing filesystem
uos.mount(vfs,'/eeprom') os.mount(eep,'/eeprom')
``` ```
The above will reformat a drive with an existing filesystem: to mount an The above will reformat a drive with an existing filesystem: to mount an
existing filesystem simply omit the commented line. existing filesystem simply omit the commented line.

Wyświetl plik

@ -93,11 +93,19 @@ def test():
# ***** TEST OF FILESYSTEM MOUNT ***** # ***** TEST OF FILESYSTEM MOUNT *****
def fstest(format=False): def fstest(format=False):
eep = get_eep() eep = get_eep()
# ***** CODE FOR FATFS *****
#if format:
#uos.VfsFat.mkfs(eep)
#vfs=uos.VfsFat(eep)
#try:
#uos.mount(vfs,'/eeprom')
#except OSError: # Already mounted
#pass
# ***** CODE FOR LITTLEFS *****
if format: if format:
uos.VfsFat.mkfs(eep) uos.VfsLfs2.mkfs(eep)
vfs=uos.VfsFat(eep)
try: try:
uos.mount(vfs,'/eeprom') uos.mount(eep,'/eeprom')
except OSError: # Already mounted except OSError: # Already mounted
pass pass
print('Contents of "/": {}'.format(uos.listdir('/'))) print('Contents of "/": {}'.format(uos.listdir('/')))
@ -109,9 +117,14 @@ def cptest():
if 'eeprom' in uos.listdir('/'): if 'eeprom' in uos.listdir('/'):
print('Device already mounted.') print('Device already mounted.')
else: else:
vfs=uos.VfsFat(eep) #vfs=uos.VfsFat(eep)
#try:
#uos.mount(vfs,'/eeprom')
#except OSError:
#print('Fail mounting device. Have you formatted it?')
#return
try: try:
uos.mount(vfs,'/eeprom') uos.mount(eep,'/eeprom')
except OSError: except OSError:
print('Fail mounting device. Have you formatted it?') print('Fail mounting device. Have you formatted it?')
return return

Wyświetl plik

@ -82,4 +82,3 @@ class EEPROM(BlockDevice):
nbytes -= npage nbytes -= npage
start += npage start += npage
addr += npage addr += npage
return buf

Wyświetl plik

@ -4,6 +4,8 @@ This driver supports the Microchip 25xx1024 series of 128KiB SPI EEPROMs and
the STM M95M02-DR 256KiB device. These have 1M and 4M cycles of write endurance the STM M95M02-DR 256KiB device. These have 1M and 4M cycles of write endurance
respectively (compared to 10K for Pyboard Flash memory). respectively (compared to 10K for Pyboard Flash memory).
**NOTE: STM chip not yet tested**
Multiple chips may be used to construct a single logical nonvolatile memory Multiple chips may be used to construct a single logical nonvolatile memory
module. The driver allows the memory either to be mounted in the target module. The driver allows the memory either to be mounted in the target
filesystem as a disk device or to be addressed as an array of bytes. filesystem as a disk device or to be addressed as an array of bytes.
@ -75,18 +77,19 @@ Installation: copy files 1 and 2 (optionally 3) to the target filesystem.
# 4. The device driver # 4. The device driver
The driver supports mounting the EEPROM chips as a filesystem. Initially the The driver supports mounting the EEPROM chips as a filesystem. Initially the
device will be unformatted so it is necessary to issue code along these lines to device will be unformatted so it is necessary to issue code along these lines
format the device. Code assumes two Microchip devices: to format the device. Code assumes two Microchip devices and also assumes the
littlefs filesystem:
```python ```python
import uos import os
from machine import SPI, Pin from machine import SPI, Pin
from eeprom_spi import EEPROM from eeprom_spi import EEPROM
cspins = (Pin(Pin.board.Y5, Pin.OUT, value=1), Pin(Pin.board.Y4, Pin.OUT, value=1)) cspins = (Pin(Pin.board.Y5, Pin.OUT, value=1), Pin(Pin.board.Y4, Pin.OUT, value=1))
eep = EEPROM(SPI(2, baudrate=20_000_000), cspins) eep = EEPROM(SPI(2, baudrate=20_000_000), cspins)
uos.VfsFat.mkfs(eep) # Omit this to mount an existing filesystem # Format the filesystem
vfs = uos.VfsFat(eep) os.VfsLfs2.mkfs(eep) # Omit this to mount an existing filesystem
uos.mount(vfs,'/eeprom') os.mount(eep,'/eeprom')
``` ```
The above will reformat a drive with an existing filesystem: to mount an The above will reformat a drive with an existing filesystem: to mount an
existing filesystem simply omit the commented line. existing filesystem simply omit the commented line.
@ -122,7 +125,7 @@ Arguments:
SPI baudrate: The 25LC1024 supports baudrates of upto 20MHz. If this value is SPI baudrate: The 25LC1024 supports baudrates of upto 20MHz. If this value is
specified the platform will produce the highest available frequency not specified the platform will produce the highest available frequency not
exceeding this figure. exceeding this figure. Note that the STM chip has a maximum rate of 5MHz.
### 4.1.2 Methods providing byte level access ### 4.1.2 Methods providing byte level access

Wyświetl plik

@ -97,11 +97,19 @@ def test(stm=False):
# ***** TEST OF FILESYSTEM MOUNT ***** # ***** TEST OF FILESYSTEM MOUNT *****
def fstest(format=False, stm=False): def fstest(format=False, stm=False):
eep = get_eep(stm) eep = get_eep(stm)
# ***** CODE FOR FATFS *****
#if format:
#uos.VfsFat.mkfs(eep)
#vfs=uos.VfsFat(eep)
#try:
#uos.mount(vfs,'/eeprom')
#except OSError: # Already mounted
#pass
# ***** CODE FOR LITTLEFS *****
if format: if format:
uos.VfsFat.mkfs(eep) uos.VfsLfs2.mkfs(eep)
vfs=uos.VfsFat(eep)
try: try:
uos.mount(vfs,'/eeprom') uos.mount(eep,'/eeprom')
except OSError: # Already mounted except OSError: # Already mounted
pass pass
print('Contents of "/": {}'.format(uos.listdir('/'))) print('Contents of "/": {}'.format(uos.listdir('/')))
@ -113,9 +121,15 @@ def cptest(stm=False):
if 'eeprom' in uos.listdir('/'): if 'eeprom' in uos.listdir('/'):
print('Device already mounted.') print('Device already mounted.')
else: else:
vfs=uos.VfsFat(eep) #vfs=uos.VfsFat(eep)
#try:
#uos.mount(vfs,'/eeprom')
#except OSError:
#print('Fail mounting device. Have you formatted it?')
#return
#vfs=uos.VfsFat(eep)
try: try:
uos.mount(vfs,'/eeprom') uos.mount(eep,'/eeprom')
except OSError: except OSError:
print('Fail mounting device. Have you formatted it?') print('Fail mounting device. Have you formatted it?')
return return

Wyświetl plik

@ -163,4 +163,3 @@ class EEPROM(BlockDevice):
nbytes -= npage nbytes -= npage
start += npage start += npage
addr += npage addr += npage
return buf