kopia lustrzana https://github.com/peterhinch/micropython_eeprom
Littlefs support. Test scripts adapted to use it.
rodzic
d792a2be7f
commit
4624fb41c6
14
README.md
14
README.md
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
11
fram/FRAM.md
11
fram/FRAM.md
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
13
i2c/I2C.md
13
i2c/I2C.md
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -82,4 +82,3 @@ class EEPROM(BlockDevice):
|
||||||
nbytes -= npage
|
nbytes -= npage
|
||||||
start += npage
|
start += npage
|
||||||
addr += npage
|
addr += npage
|
||||||
return buf
|
|
||||||
|
|
17
spi/SPI.md
17
spi/SPI.md
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -163,4 +163,3 @@ class EEPROM(BlockDevice):
|
||||||
nbytes -= npage
|
nbytes -= npage
|
||||||
start += npage
|
start += npage
|
||||||
addr += npage
|
addr += npage
|
||||||
return buf
|
|
||||||
|
|
Ładowanie…
Reference in New Issue