diff --git a/README.md b/README.md index aee235a..ffdf55e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 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 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. 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 - 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 `machine` module. 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) | | Adafruit | 1895 | I2C n/a | 32KiB | FRAM | [FRAM.md](./fram/FRAM.md) | +**STM chip support under development** + Documentation: [SPI.md](./spi/SPI.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 is arbitrary. Littlefs requires a minimum size of 128 bytes - -[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. +[theoretically 104](https://github.com/ARMmbed/littlefs/blob/master/DESIGN.md). +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 -been released. The test programs therefore use FAT. +The test programs use littlefs and therefore require MicroPython V1.12 or +later. diff --git a/bdevice.py b/bdevice.py index d9ef53b..7e25c2a 100644 --- a/bdevice.py +++ b/bdevice.py @@ -62,13 +62,13 @@ class BlockDevice: # IOCTL protocol. 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) def ioctl(self, op, arg): - #print("ioctl(%d, %r)" % (op, arg)) if op == 4: # BP_IOCTL_SEC_COUNT return self._a_bytes >> self._nbits if op == 5: # BP_IOCTL_SEC_SIZE diff --git a/fram/FRAM.md b/fram/FRAM.md index 2547866..87ef3af 100644 --- a/fram/FRAM.md +++ b/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 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 -import uos +import os from machine import I2C from fram_i2c import FRAM fram = FRAM(I2C(2)) -uos.VfsFat.mkfs(fram) # Omit this to mount an existing filesystem -vfs = uos.VfsFat(fram) -uos.mount(vfs,'/fram') +# Format the filesystem +os.VfsLfs2.mkfs(fram) # Omit this to mount an existing filesystem +os.mount(fram,'/fram') ``` The above will reformat a drive with an existing filesystem: to mount an existing filesystem simply omit the commented line. diff --git a/fram/fram_i2c.py b/fram/fram_i2c.py index ce4784d..7a98b5b 100644 --- a/fram/fram_i2c.py +++ b/fram/fram_i2c.py @@ -47,21 +47,6 @@ class FRAM(BlockDevice): productID = ((res[1] & 0x0F) << 8) + res[2] 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. # 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. diff --git a/i2c/I2C.md b/i2c/I2C.md index bbc5be0..8ec10ad 100644 --- a/i2c/I2C.md +++ b/i2c/I2C.md @@ -77,17 +77,18 @@ Installation: copy files 1 and 2 (optionally 3) to the target filesystem. # 4. The device driver 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 -format the device. Code assumes one or more 64KiB devices: +device will be unformatted so it is necessary to issue code along these lines +to format the device. Code assumes one or more 64KiB devices and also assumes +the littlefs filesystem: ```python -import uos +import os from machine import I2C from eeprom_i2c import EEPROM, T24C512 eep = EEPROM(I2C(2), T24C512) -uos.VfsFat.mkfs(eep) # Omit this to mount an existing filesystem -vfs = uos.VfsFat(eep) -uos.mount(vfs,'/eeprom') +# Format the filesystem +os.VfsLfs2.mkfs(eep) # Omit this to mount an existing filesystem +os.mount(eep,'/eeprom') ``` The above will reformat a drive with an existing filesystem: to mount an existing filesystem simply omit the commented line. diff --git a/i2c/eep_i2c.py b/i2c/eep_i2c.py index 126f1c5..b78869d 100644 --- a/i2c/eep_i2c.py +++ b/i2c/eep_i2c.py @@ -93,11 +93,19 @@ def test(): # ***** TEST OF FILESYSTEM MOUNT ***** def fstest(format=False): 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: - uos.VfsFat.mkfs(eep) - vfs=uos.VfsFat(eep) + uos.VfsLfs2.mkfs(eep) try: - uos.mount(vfs,'/eeprom') + uos.mount(eep,'/eeprom') except OSError: # Already mounted pass print('Contents of "/": {}'.format(uos.listdir('/'))) @@ -109,9 +117,14 @@ def cptest(): if 'eeprom' in uos.listdir('/'): print('Device already mounted.') 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: - uos.mount(vfs,'/eeprom') + uos.mount(eep,'/eeprom') except OSError: print('Fail mounting device. Have you formatted it?') return diff --git a/i2c/eeprom_i2c.py b/i2c/eeprom_i2c.py index 6d177f0..8d6fdc9 100644 --- a/i2c/eeprom_i2c.py +++ b/i2c/eeprom_i2c.py @@ -82,4 +82,3 @@ class EEPROM(BlockDevice): nbytes -= npage start += npage addr += npage - return buf diff --git a/spi/SPI.md b/spi/SPI.md index e00cb4c..5db3537 100644 --- a/spi/SPI.md +++ b/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 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 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. @@ -75,18 +77,19 @@ Installation: copy files 1 and 2 (optionally 3) to the target filesystem. # 4. The device driver 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 -format the device. Code assumes two Microchip devices: +device will be unformatted so it is necessary to issue code along these lines +to format the device. Code assumes two Microchip devices and also assumes the +littlefs filesystem: ```python -import uos +import os from machine import SPI, Pin from eeprom_spi import EEPROM 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) -uos.VfsFat.mkfs(eep) # Omit this to mount an existing filesystem -vfs = uos.VfsFat(eep) -uos.mount(vfs,'/eeprom') +# Format the filesystem +os.VfsLfs2.mkfs(eep) # Omit this to mount an existing filesystem +os.mount(eep,'/eeprom') ``` The above will reformat a drive with an existing filesystem: to mount an 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 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 diff --git a/spi/eep_spi.py b/spi/eep_spi.py index 3984f63..dafa1d8 100644 --- a/spi/eep_spi.py +++ b/spi/eep_spi.py @@ -97,11 +97,19 @@ def test(stm=False): # ***** TEST OF FILESYSTEM MOUNT ***** def fstest(format=False, stm=False): 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: - uos.VfsFat.mkfs(eep) - vfs=uos.VfsFat(eep) + uos.VfsLfs2.mkfs(eep) try: - uos.mount(vfs,'/eeprom') + uos.mount(eep,'/eeprom') except OSError: # Already mounted pass print('Contents of "/": {}'.format(uos.listdir('/'))) @@ -113,9 +121,15 @@ def cptest(stm=False): if 'eeprom' in uos.listdir('/'): print('Device already mounted.') 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: - uos.mount(vfs,'/eeprom') + uos.mount(eep,'/eeprom') except OSError: print('Fail mounting device. Have you formatted it?') return diff --git a/spi/eeprom_spi.py b/spi/eeprom_spi.py index b92e413..77ade0a 100644 --- a/spi/eeprom_spi.py +++ b/spi/eeprom_spi.py @@ -163,4 +163,3 @@ class EEPROM(BlockDevice): nbytes -= npage start += npage addr += npage - return buf