Prepare for STM chip. Devolve further code to base class.

pull/1/head
Peter Hinch 2019-12-18 17:24:50 +00:00
rodzic ebea14bd6f
commit d792a2be7f
6 zmienionych plików z 142 dodań i 96 usunięć

Wyświetl plik

@ -29,7 +29,7 @@ The drivers have the following common features:
Currently supported technologies are EEPROM and FRAM (ferroelectric RAM). These Currently supported technologies are EEPROM and FRAM (ferroelectric RAM). These
are nonvolatile random access storage devices with much higher endurance than are nonvolatile random access storage devices with much higher endurance than
flash memory. Flash has a typical endurance of 10K writes per page. The figures flash memory. Flash has a typical endurance of 10K writes per page. The figures
for EEPROM and FRAM are 1M and 10^12 writes respectively. In the case of the for EEPROM and FRAM are 1-4M and 10^12 writes respectively. In the case of the
FAT filing system 1M page writes probably corresponds to 1M filesystem writes FAT filing system 1M page writes probably corresponds to 1M filesystem writes
because FAT repeatedly updates the allocation tables in the low numbered because FAT repeatedly updates the allocation tables in the low numbered
sectors. If `littlefs` is used I would expect the endurance to be substantially sectors. If `littlefs` is used I would expect the endurance to be substantially
@ -37,25 +37,27 @@ better owing to its wear levelling architecture.
## 1.3 Supported chips ## 1.3 Supported chips
These currently include Microchip EEPROM chips and These currently include Microchip and STM EEPROM chips and
[this Adafruit FRAM board](http://www.adafruit.com/product/1895). Note that the [this Adafruit FRAM board](http://www.adafruit.com/product/1895). Note that the
largest EEPROM chip uses SPI: see [below](./README.md#2-choice-of-interface) largest EEPROM chip uses SPI: see [below](./README.md#2-choice-of-interface)
for a discussion of the merits and drawbacks of each interface. for a discussion of the merits and drawbacks of each interface.
Supported devices. Microchip manufacture each chip in different variants with Supported devices. Microchip manufacture each chip in different variants with
letters denoted by "xx" below. The variants cover parameters such as minimum letters denoted by "xx" below. The variants cover parameters such as minimum
Vcc value and do not affect the API. Vcc value and do not affect the API. There are two variants of the STM chip,
M95M02-DRMN6TP and M95M02-DWMN3TP/K. The latter has a wider temperature range.
In the table below the Interface column includes page size in bytes. In the table below the Interface column includes page size in bytes.
| Manufacturer | Part | Interface | Bytes | Technology | Docs | | Manufacturer | Part | Interface | Bytes | Technology | Docs |
|:------------:|:--------:|:---------:|:------:|:----------:|:-------------------------:| |:------------:|:---------:|:---------:|:------:|:----------:|:-------------------------:|
| Microchip | 25xx1024 | SPI 256 | 128KiB | EEPROM | [SPI.md](./spi/SPI.md) | | STM | M95M02-DR | SPI 256 | 256KiB | EEPROM | [SPI.md](./spi/SPI.md) |
| Microchip | 24xx512 | I2C 128 | 64KiB | EEPROM | [I2C.md](./i2c/I2C.md) | | Microchip | 25xx1024 | SPI 256 | 128KiB | EEPROM | [SPI.md](./spi/SPI.md) |
| Microchip | 24xx256 | I2C 128 | 32KiB | EEPROM | [I2C.md](./i2c/I2C.md) | | Microchip | 24xx512 | I2C 128 | 64KiB | EEPROM | [I2C.md](./i2c/I2C.md) |
| Microchip | 24xx128 | I2C 128 | 16KiB | EEPROM | [I2C.md](./i2c/I2C.md) | | Microchip | 24xx256 | I2C 128 | 32KiB | EEPROM | [I2C.md](./i2c/I2C.md) |
| Microchip | 24xx64 | I2C 128 | 8KiB | EEPROM | [I2C.md](./i2c/I2C.md) | | Microchip | 24xx128 | I2C 128 | 16KiB | EEPROM | [I2C.md](./i2c/I2C.md) |
| Adafruit | 1895 | I2C n/a | 32KiB | FRAM | [FRAM.md](./fram/FRAM.md) | | Microchip | 24xx64 | I2C 128 | 8KiB | EEPROM | [I2C.md](./i2c/I2C.md) |
| Adafruit | 1895 | I2C n/a | 32KiB | FRAM | [FRAM.md](./fram/FRAM.md) |
Documentation: Documentation:
[SPI.md](./spi/SPI.md) [SPI.md](./spi/SPI.md)
@ -92,7 +94,7 @@ electrical limits may also apply).
In the case of the Microchip devices supported, the SPI chip is larger at In the case of the Microchip devices supported, the SPI chip is larger at
128KiB compared to a maximum of 64KiB in the I2C range. 128KiB compared to a maximum of 64KiB in the I2C range.
# 3. Design details # 3. Design details and test results
The fact that the API enables accessing blocks of data at arbitrary addresses The fact that the API enables accessing blocks of data at arbitrary addresses
implies that the handling of page addressing is done in the driver. This implies that the handling of page addressing is done in the driver. This
@ -100,5 +102,10 @@ contrasts with drivers intended only for filesystem access. These devolve the
detail of page addressing to the filesystem by specifying the correct page size detail of page addressing to the filesystem by specifying the correct page size
in the ioctl and (if necessary) implementing a block erase method. in the ioctl and (if necessary) implementing a block erase method.
The nature of the drivers in this repo implies that the block address in the The nature of the drivers in this repo implies that the page size in the ioctl
ioctl is arbitrary. 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.
Currently I have not had success with littlefs but it hasn't yet officially
been released. The test programs therefore use FAT.

Wyświetl plik

@ -18,10 +18,22 @@ class BlockDevice:
self._a_bytes = chip_size * nchips # Size of array self._a_bytes = chip_size * nchips # Size of array
self._nbits = nbits # Block size in bits self._nbits = nbits # Block size in bits
self._block_size = 2**nbits self._block_size = 2**nbits
self._rwbuf = bytearray(1)
def __len__(self): def __len__(self):
return self._a_bytes return self._a_bytes
def __setitem__(self, addr, value):
if isinstance(addr, slice):
return self._wslice(addr, value)
self._rwbuf[0] = value
self.readwrite(addr, self._rwbuf, False)
def __getitem__(self, addr):
if isinstance(addr, slice):
return self._rslice(addr)
return self.readwrite(addr, self._rwbuf, True)[0]
# Handle special cases of a slice. Always return a pair of positive indices. # Handle special cases of a slice. Always return a pair of positive indices.
def _do_slice(self, addr): def _do_slice(self, addr):
if not (addr.step is None or addr.step == 1): if not (addr.step is None or addr.step == 1):
@ -32,7 +44,7 @@ class BlockDevice:
stop = stop if stop >= 0 else self._a_bytes + stop stop = stop if stop >= 0 else self._a_bytes + stop
return start, stop return start, stop
def wslice(self, addr, value): def _wslice(self, addr, value):
start, stop = self._do_slice(addr) start, stop = self._do_slice(addr)
try: try:
if len(value) == (stop - start): if len(value) == (stop - start):
@ -43,7 +55,7 @@ class BlockDevice:
raise RuntimeError('Can only assign bytes/bytearray to a slice') raise RuntimeError('Can only assign bytes/bytearray to a slice')
return res return res
def rslice(self, addr): def _rslice(self, addr):
start, stop = self._do_slice(addr) start, stop = self._do_slice(addr)
buf = bytearray(stop - start) buf = bytearray(stop - start)
return self.readwrite(start, buf, True) return self.readwrite(start, buf, True)

Wyświetl plik

@ -53,22 +53,6 @@ class EEPROM(BlockDevice):
finally: finally:
time.sleep_ms(1) time.sleep_ms(1)
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))
self._wait_rdy() # Wait for write to complete
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]
# Given an address, set ._i2c_addr and ._addrbuf and return the number of # Given an address, set ._i2c_addr and ._addrbuf and return the number of
# bytes that can be processed in the current page # bytes that can be processed in the current page
def _getaddr(self, addr, nbytes): # Set up _addrbuf and _i2c_addr def _getaddr(self, addr, nbytes): # Set up _addrbuf and _i2c_addr

Wyświetl plik

@ -1,6 +1,9 @@
# 1. A MicroPython SPI EEPROM driver # 1. A MicroPython SPI EEPROM driver
This driver supports the Microchip 25xx1024 series of 128KiB SPI EEPROMs. 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).
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.
@ -13,13 +16,23 @@ The driver has the following attributes:
5. The SPI bus can be shared with other chips. 5. The SPI bus can be shared with other chips.
6. It supports filesystem mounting. 6. It supports filesystem mounting.
7. Alternatively it can support byte-level access using Python slice syntax. 7. Alternatively it can support byte-level access using Python slice syntax.
8. RAM allocations are minimised. 8. RAM allocations are minimised. Buffer sizes are tiny.
## 1.1 This document
Code samples assume one or more Microchip devices. If using the STM chip the
SPI baudrate should be 5MHz and the chip size must be specified to the `EEPROM`
constructor, e.g.:
```python
eep = EEPROM(SPI(2, baudrate=5_000_000), cspins, 256)
```
# 2. Connections # 2. Connections
Any SPI interface may be used. The table below assumes a Pyboard running SPI(2) Any SPI interface may be used. The table below assumes a Pyboard running SPI(2)
as per the test program. To wire up a single EEPROM chip, connect to a Pyboard as per the test program. To wire up a single EEPROM chip, connect to a Pyboard
as below. Pin numbers assume a PDIP package (8 pin plastic dual-in-line). as below. Pin numbers assume a PDIP package (8 pin plastic dual-in-line) for
the Microchip device and 8 pin SOIC for the STM chip.
| EEPROM | Signal | PB | Signal | | EEPROM | Signal | PB | Signal |
|:-------:|:------:|:---:|:------:| |:-------:|:------:|:---:|:------:|
@ -34,8 +47,7 @@ as below. Pin numbers assume a PDIP package (8 pin plastic dual-in-line).
For multiple chips a separate CS pin must be assigned to each chip: each one For multiple chips a separate CS pin must be assigned to each chip: each one
must be wired to a single chip's CS line. Multiple chips should have 3V3, Gnd, must be wired to a single chip's CS line. Multiple chips should have 3V3, Gnd,
SCL, MOSI and MISO lines wired in parallel. The SPI bus is fast: wiring should SCL, MOSI and MISO lines wired in parallel.
be short and direct.
If you use a Pyboard D and power the EEPROMs from the 3V3 output you will need If you use a Pyboard D and power the EEPROMs from the 3V3 output you will need
to enable the voltage rail by issuing: to enable the voltage rail by issuing:
@ -44,6 +56,14 @@ machine.Pin.board.EN_3V3.value(1)
``` ```
Other platforms may vary. Other platforms may vary.
## 2.1 SPI Bus
The Microchip devices support baudrates up to 20MHz. The STM chip has a maximum
of 5MHz. Both support the default SPI mode: simply specify the baudrate to the
constructor.
The SPI bus is fast: wiring should be short and direct.
# 3. Files # 3. Files
1. `eeprom_spi.py` Device driver. 1. `eeprom_spi.py` Device driver.
@ -56,7 +76,7 @@ Installation: copy files 1 and 2 (optionally 3) to the target filesystem.
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 to
format the device. Code assumes two devices: format the device. Code assumes two Microchip devices:
```python ```python
import uos import uos
@ -94,9 +114,10 @@ Arguments:
1. `spi` Mandatory. An initialised SPI bus created by `machine`. 1. `spi` Mandatory. An initialised SPI bus created by `machine`.
2. `cspins` A list or tuple of `Pin` instances. Each `Pin` must be initialised 2. `cspins` A list or tuple of `Pin` instances. Each `Pin` must be initialised
as an output (`Pin.OUT`) and with `value=1` and be created by `machine`. as an output (`Pin.OUT`) and with `value=1` and be created by `machine`.
3. `verbose=True` If `True`, the constructor issues information on the EEPROM 3. `size=128` Chip size in KiB. Set to 256 for the STM chip.
4. `verbose=True` If `True`, the constructor issues information on the EEPROM
devices it has detected. devices it has detected.
4. `block_size=9` The block size reported to the filesystem. The size in bytes 5. `block_size=9` The block size reported to the filesystem. The size in bytes
is `2**block_size` so is 512 bytes by default. is `2**block_size` so is 512 bytes by default.
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
@ -108,7 +129,8 @@ exceeding this figure.
It is possible to read and write individual bytes or arrays of arbitrary size. It is possible to read and write individual bytes or arrays of arbitrary size.
Larger arrays are faster, especially when writing: the driver uses the chip's Larger arrays are faster, especially when writing: the driver uses the chip's
hardware page access where possible. Writing a page (256 bytes) takes the same hardware page access where possible. Writing a page (256 bytes) takes the same
time (~5ms) as writing a single byte. time as writing a single byte. This is 6ms max on the Microchip and 10ms max on
the STM.
The examples below assume two devices, one with `CS` connected to Pyboard pin The examples below assume two devices, one with `CS` connected to Pyboard pin
Y4 and the other with `CS` connected to Y5. Y4 and the other with `CS` connected to Y5.
@ -171,7 +193,7 @@ identify the chip.
#### erase #### erase
Erases the entire array. Erases the entire array. Available only on the Microchip device.
### 4.1.4 Methods providing the block protocol ### 4.1.4 Methods providing the block protocol
@ -216,28 +238,29 @@ possible to use JSON/pickle to store objects in a filesystem.
# 5. Test program eep_spi.py # 5. Test program eep_spi.py
This assumes a Pyboard 1.x or Pyboard D with EEPROM(s) wired as above. It This assumes a Pyboard 1.x or Pyboard D with two EEPROMs wired to SPI(2) as
provides the following. above with chip selects connected to pins `Y4` and `Y5`. It provides the
following. In all cases the stm arg should be `True` if using the STM chips.
## 5.1 test() ## 5.1 test(stm=False)
This performs a basic test of single and multi-byte access to chip 0. The test This performs a basic test of single and multi-byte access to chip 0. The test
reports how many chips can be accessed. Existing array data will be lost. This reports how many chips can be accessed. Existing array data will be lost. This
primarily tests the driver: as a hardware test it is not exhaustive. primarily tests the driver: as a hardware test it is not exhaustive.
## 5.2 full_test() ## 5.2 full_test(stm=False)
This is a hardware test. Tests the entire array. Fills each 256 byte page with This is a hardware test. Tests the entire array. Fills each 256 byte page with
random data, reads it back, and checks the outcome. Existing array data will be random data, reads it back, and checks the outcome. Existing array data will be
lost. lost.
## 5.3 fstest(format=False) ## 5.3 fstest(format=False, stm=False)
If `True` is passed, formats the EEPROM array as a FAT filesystem and mounts If `True` is passed, formats the EEPROM array as a FAT filesystem and mounts
the device on `/eeprom`. If no arg is passed it mounts the array and lists the the device on `/eeprom`. If no arg is passed it mounts the array and lists the
contents. It also prints the outcome of `uos.statvfs` on the array. contents. It also prints the outcome of `uos.statvfs` on the array.
## 5.4 cptest() ## 5.4 cptest(stm=False)
Tests copying the source files to the filesystem. The test will fail if the Tests copying the source files to the filesystem. The test will fail if the
filesystem was not formatted. Lists the contents of the mountpoint and prints filesystem was not formatted. Lists the contents of the mountpoint and prints

Wyświetl plik

@ -10,10 +10,13 @@ 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))
# Return an EEPROM array. Adapt for platforms other than Pyboard. # Return an EEPROM array. Adapt for platforms other than Pyboard.
def get_eep(): def get_eep(stm):
if uos.uname().machine.split(' ')[0][:4] == 'PYBD': if uos.uname().machine.split(' ')[0][:4] == 'PYBD':
Pin.board.EN_3V3.value(1) Pin.board.EN_3V3.value(1)
eep = EEPROM(SPI(2, baudrate=20_000_000), cspins) if stm:
eep = EEPROM(SPI(2, baudrate=5_000_000), cspins, 256)
else:
eep = EEPROM(SPI(2, baudrate=20_000_000), cspins)
print('Instantiated EEPROM') print('Instantiated EEPROM')
return eep return eep
@ -56,8 +59,8 @@ def _testblock(eep, bs):
if res != d2: if res != d2:
return 'Block test fail 3:' + res return 'Block test fail 3:' + res
def test(): def test(stm=False):
eep = get_eep() eep = get_eep(stm)
sa = 1000 sa = 1000
for v in range(256): for v in range(256):
eep[sa + v] = v eep[sa + v] = v
@ -92,8 +95,8 @@ def test():
print('Test chip boundary skipped: only one chip!') print('Test chip boundary skipped: only one chip!')
# ***** TEST OF FILESYSTEM MOUNT ***** # ***** TEST OF FILESYSTEM MOUNT *****
def fstest(format=False): def fstest(format=False, stm=False):
eep = get_eep() eep = get_eep(stm)
if format: if format:
uos.VfsFat.mkfs(eep) uos.VfsFat.mkfs(eep)
vfs=uos.VfsFat(eep) vfs=uos.VfsFat(eep)
@ -105,8 +108,8 @@ def fstest(format=False):
print('Contents of "/eeprom": {}'.format(uos.listdir('/eeprom'))) print('Contents of "/eeprom": {}'.format(uos.listdir('/eeprom')))
print(uos.statvfs('/eeprom')) print(uos.statvfs('/eeprom'))
def cptest(): def cptest(stm=False):
eep = get_eep() eep = get_eep(stm)
if 'eeprom' in uos.listdir('/'): if 'eeprom' in uos.listdir('/'):
print('Device already mounted.') print('Device already mounted.')
else: else:
@ -124,8 +127,8 @@ def cptest():
# ***** TEST OF HARDWARE ***** # ***** TEST OF HARDWARE *****
def full_test(): def full_test(stm=False):
eep = get_eep() eep = get_eep(stm)
page = 0 page = 0
for sa in range(0, len(eep), 256): for sa in range(0, len(eep), 256):
data = uos.urandom(256) data = uos.urandom(256)

Wyświetl plik

@ -1,5 +1,6 @@
# eeprom_spi.py MicroPython driver for Microchip SPI EEPROM devices, # eeprom_spi.py MicroPython driver for Microchip 128KiB SPI EEPROM device,
# currently only 25xx1024. # also STM 256KiB chip
# TODO the latter not yet tested.
# Released under the MIT License (MIT). See LICENSE. # Released under the MIT License (MIT). See LICENSE.
# Copyright (c) 2019 Peter Hinch # Copyright (c) 2019 Peter Hinch
@ -8,24 +9,29 @@ import time
from micropython import const from micropython import const
from bdevice import BlockDevice from bdevice import BlockDevice
_SIZE = const(131072) # Chip size 128KiB
# Supported instruction set # Supported instruction set
_READ = const(3) _READ = const(3)
_WRITE = const(2) _WRITE = const(2)
_WREN = const(6) # Write enable _WREN = const(6) # Write enable
_RDSR = const(5) # Read status register _RDSR = const(5) # Read status register
_RDID = const(0xab) # Read chip ID _RDID = const(0xab) # Read chip ID
_CE = const(0xc7) # Chip erase _CE = const(0xc7) # Chip erase (Microchip only)
# Not implemented: Write disable and Write status register # Not implemented: Write disable and Write status register
# _WRDI = const(4) # _WRDI = const(4)
# _WRSR = const(1) # _WRSR = const(1)
#_RDID_STM = const(0x83) # STM only read ID page
#_WRID_STM = const(0x82)
#_STM_ID = const(0x30) # Arbitrary ID for STM chip
# Logical EEPROM device comprising one or more physical chips sharing an SPI bus. # Logical EEPROM device comprising one or more physical chips sharing an SPI bus.
class EEPROM(BlockDevice): class EEPROM(BlockDevice):
def __init__(self, spi, cspins, verbose=True, block_size=9): def __init__(self, spi, cspins, size=128, verbose=True, block_size=9):
# args: virtual block size in bits, no. of chips, bytes in each chip # args: virtual block size in bits, no. of chips, bytes in each chip
super().__init__(block_size, len(cspins), _SIZE) if size not in (128, 256):
raise ValueError('Valid sizes are 128 or 256')
super().__init__(block_size, len(cspins), size * 1024)
self._stm = size == 256
self._spi = spi self._spi = spi
self._cspins = cspins self._cspins = cspins
self._ccs = None # Chip select Pin object for current chip self._ccs = None # Chip select Pin object for current chip
@ -33,22 +39,62 @@ class EEPROM(BlockDevice):
self._mvp = memoryview(self._bufp) # cost-free slicing self._mvp = memoryview(self._bufp) # cost-free slicing
self.scan(verbose) self.scan(verbose)
# Check for a valid hardware configuration # STM Datasheet too vague about the ID block. Do we need _WREN? Do we need to poll ready?
def scan(self, verbose): #def _stm_rdid(self):
#mvp = self._mvp
#mvp[:] = b'\0\0\0\0\0'
#mvp[0] = _RDID_STM
#cs(0)
#self._spi.write_readinto(mvp, mvp)
#cs(1)
#return mvp[4]
#def _stm_wrid(self):
#mvp = self._mvp
#mvp[:] = b'\0\0\0\0\0'
#mvp[0] = _WRID_STM
#mvp[5] = _STM_ID
#cs(0)
#self._spi.write(mvp)
#cs(1)
# Check for a valid hardware configuration: just see if we can write to offset 0
# Tested (on Microchip), but probably better to use ID block
def _stm_scan(self):
for n in range(len(self._cspins)):
ta = n * self._c_bytes
v = self[ta]
vx = v^0xff
self[ta] = vx
if self[ta] == vx: # Wrote OK, put back
self[ta] = v
else:
raise RuntimeError('EEPROM not found at cs[{}].'.format(n))
return n
# Scan for Microchip devices: read manf ID
def _mc_scan(self):
mvp = self._mvp mvp = self._mvp
for n, cs in enumerate(self._cspins): for n, cs in enumerate(self._cspins):
mvp[:] = b'\0\0\0\0\0' mvp[:] = b'\0\0\0\0\0'
mvp[0] = _RDID mvp[0] = _RDID
cs(0) cs(0)
self._spi.write_readinto(mvp[:5], mvp[:5]) self._spi.write_readinto(mvp, mvp)
cs(1) cs(1)
if mvp[4] != 0x29: if mvp[4] != 0x29:
raise RuntimeError('EEPROM not found at cs[{}].'.format(n)) raise RuntimeError('EEPROM not found at cs[{}].'.format(n))
return n
# Check for a valid hardware configuration
def scan(self, verbose):
n = self._stm_scan() if self._stm else self._mc_scan()
if verbose: if verbose:
s = '{} chips detected. Total EEPROM size {}bytes.' s = '{} chips detected. Total EEPROM size {}bytes.'
print(s.format(n + 1, self._a_bytes)) print(s.format(n + 1, self._a_bytes))
def erase(self): def erase(self):
if self._stm:
raise RuntimeError('Erase not available on STM chip')
mvp = self._mvp mvp = self._mvp
for cs in self._cspins: # For each chip for cs in self._cspins: # For each chip
mvp[0] = _WREN mvp[0] = _WREN
@ -73,35 +119,6 @@ class EEPROM(BlockDevice):
break break
time.sleep_ms(1) time.sleep_ms(1)
def __setitem__(self, addr, value):
if isinstance(addr, slice):
return self.wslice(addr, value)
mvp = self._mvp
mvp[0] = _WREN
self._getaddr(addr, 1) # Sets mv[1:4], updates ._ccs
cs = self._ccs # Retrieve current cs pin
cs(0)
self._spi.write(mvp[:1])
cs(1)
mvp[0] = _WRITE
mvp[4] = value
cs(0)
self._spi.write(mvp[:5])
cs(1) # Trigger write
self._wait_rdy() # Wait for write to complete
def __getitem__(self, addr):
if isinstance(addr, slice):
return self.rslice(addr)
mvp = self._mvp
mvp[0] = _READ
self._getaddr(addr, 1)
cs = self._ccs
cs(0)
self._spi.write_readinto(mvp[:5], mvp[:5])
cs(1)
return mvp[4]
# Given an address, set current chip select and address buffer. # Given an address, set current chip select and address buffer.
# Return the number of bytes that can be processed in the current page. # Return the number of bytes that can be processed in the current page.
def _getaddr(self, addr, nbytes): def _getaddr(self, addr, nbytes):