kopia lustrzana https://github.com/peterhinch/micropython_eeprom
Prepare for STM chip. Devolve further code to base class.
rodzic
ebea14bd6f
commit
d792a2be7f
35
README.md
35
README.md
|
@ -29,7 +29,7 @@ The drivers have the following common features:
|
|||
Currently supported technologies are EEPROM and FRAM (ferroelectric RAM). These
|
||||
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
|
||||
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
|
||||
because FAT repeatedly updates the allocation tables in the low numbered
|
||||
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
|
||||
|
||||
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
|
||||
largest EEPROM chip uses SPI: see [below](./README.md#2-choice-of-interface)
|
||||
for a discussion of the merits and drawbacks of each interface.
|
||||
|
||||
Supported devices. Microchip manufacture each chip in different variants with
|
||||
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.
|
||||
|
||||
| Manufacturer | Part | Interface | Bytes | Technology | Docs |
|
||||
|:------------:|:--------:|:---------:|:------:|:----------:|:-------------------------:|
|
||||
| Microchip | 25xx1024 | SPI 256 | 128KiB | EEPROM | [SPI.md](./spi/SPI.md) |
|
||||
| Microchip | 24xx512 | I2C 128 | 64KiB | EEPROM | [I2C.md](./i2c/I2C.md) |
|
||||
| Microchip | 24xx256 | I2C 128 | 32KiB | EEPROM | [I2C.md](./i2c/I2C.md) |
|
||||
| Microchip | 24xx128 | I2C 128 | 16KiB | 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) |
|
||||
| Manufacturer | Part | Interface | Bytes | Technology | Docs |
|
||||
|:------------:|:---------:|:---------:|:------:|:----------:|:-------------------------:|
|
||||
| STM | M95M02-DR | SPI 256 | 256KiB | EEPROM | [SPI.md](./spi/SPI.md) |
|
||||
| Microchip | 25xx1024 | SPI 256 | 128KiB | EEPROM | [SPI.md](./spi/SPI.md) |
|
||||
| Microchip | 24xx512 | I2C 128 | 64KiB | EEPROM | [I2C.md](./i2c/I2C.md) |
|
||||
| Microchip | 24xx256 | I2C 128 | 32KiB | EEPROM | [I2C.md](./i2c/I2C.md) |
|
||||
| Microchip | 24xx128 | I2C 128 | 16KiB | 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) |
|
||||
|
||||
Documentation:
|
||||
[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
|
||||
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
|
||||
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
|
||||
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
|
||||
ioctl is arbitrary.
|
||||
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.
|
||||
|
||||
Currently I have not had success with littlefs but it hasn't yet officially
|
||||
been released. The test programs therefore use FAT.
|
||||
|
|
16
bdevice.py
16
bdevice.py
|
@ -18,10 +18,22 @@ class BlockDevice:
|
|||
self._a_bytes = chip_size * nchips # Size of array
|
||||
self._nbits = nbits # Block size in bits
|
||||
self._block_size = 2**nbits
|
||||
self._rwbuf = bytearray(1)
|
||||
|
||||
def __len__(self):
|
||||
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.
|
||||
def _do_slice(self, addr):
|
||||
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
|
||||
return start, stop
|
||||
|
||||
def wslice(self, addr, value):
|
||||
def _wslice(self, addr, value):
|
||||
start, stop = self._do_slice(addr)
|
||||
try:
|
||||
if len(value) == (stop - start):
|
||||
|
@ -43,7 +55,7 @@ class BlockDevice:
|
|||
raise RuntimeError('Can only assign bytes/bytearray to a slice')
|
||||
return res
|
||||
|
||||
def rslice(self, addr):
|
||||
def _rslice(self, addr):
|
||||
start, stop = self._do_slice(addr)
|
||||
buf = bytearray(stop - start)
|
||||
return self.readwrite(start, buf, True)
|
||||
|
|
|
@ -53,22 +53,6 @@ class EEPROM(BlockDevice):
|
|||
finally:
|
||||
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
|
||||
# bytes that can be processed in the current page
|
||||
def _getaddr(self, addr, nbytes): # Set up _addrbuf and _i2c_addr
|
||||
|
|
55
spi/SPI.md
55
spi/SPI.md
|
@ -1,6 +1,9 @@
|
|||
# 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
|
||||
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.
|
||||
|
@ -13,13 +16,23 @@ The driver has the following attributes:
|
|||
5. The SPI bus can be shared with other chips.
|
||||
6. It supports filesystem mounting.
|
||||
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
|
||||
|
||||
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 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 |
|
||||
|:-------:|:------:|:---:|:------:|
|
||||
|
@ -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
|
||||
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
|
||||
be short and direct.
|
||||
SCL, MOSI and MISO lines wired in parallel.
|
||||
|
||||
If you use a Pyboard D and power the EEPROMs from the 3V3 output you will need
|
||||
to enable the voltage rail by issuing:
|
||||
|
@ -44,6 +56,14 @@ machine.Pin.board.EN_3V3.value(1)
|
|||
```
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
import uos
|
||||
|
@ -94,9 +114,10 @@ Arguments:
|
|||
1. `spi` Mandatory. An initialised SPI bus created by `machine`.
|
||||
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`.
|
||||
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.
|
||||
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.
|
||||
|
||||
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.
|
||||
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
|
||||
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
|
||||
Y4 and the other with `CS` connected to Y5.
|
||||
|
@ -171,7 +193,7 @@ identify the chip.
|
|||
|
||||
#### erase
|
||||
|
||||
Erases the entire array.
|
||||
Erases the entire array. Available only on the Microchip device.
|
||||
|
||||
### 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
|
||||
|
||||
This assumes a Pyboard 1.x or Pyboard D with EEPROM(s) wired as above. It
|
||||
provides the following.
|
||||
This assumes a Pyboard 1.x or Pyboard D with two EEPROMs wired to SPI(2) as
|
||||
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
|
||||
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.
|
||||
|
||||
## 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
|
||||
random data, reads it back, and checks the outcome. Existing array data will be
|
||||
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
|
||||
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.
|
||||
|
||||
## 5.4 cptest()
|
||||
## 5.4 cptest(stm=False)
|
||||
|
||||
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
|
||||
|
|
|
@ -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))
|
||||
|
||||
# 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':
|
||||
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')
|
||||
return eep
|
||||
|
||||
|
@ -56,8 +59,8 @@ def _testblock(eep, bs):
|
|||
if res != d2:
|
||||
return 'Block test fail 3:' + res
|
||||
|
||||
def test():
|
||||
eep = get_eep()
|
||||
def test(stm=False):
|
||||
eep = get_eep(stm)
|
||||
sa = 1000
|
||||
for v in range(256):
|
||||
eep[sa + v] = v
|
||||
|
@ -92,8 +95,8 @@ def test():
|
|||
print('Test chip boundary skipped: only one chip!')
|
||||
|
||||
# ***** TEST OF FILESYSTEM MOUNT *****
|
||||
def fstest(format=False):
|
||||
eep = get_eep()
|
||||
def fstest(format=False, stm=False):
|
||||
eep = get_eep(stm)
|
||||
if format:
|
||||
uos.VfsFat.mkfs(eep)
|
||||
vfs=uos.VfsFat(eep)
|
||||
|
@ -105,8 +108,8 @@ def fstest(format=False):
|
|||
print('Contents of "/eeprom": {}'.format(uos.listdir('/eeprom')))
|
||||
print(uos.statvfs('/eeprom'))
|
||||
|
||||
def cptest():
|
||||
eep = get_eep()
|
||||
def cptest(stm=False):
|
||||
eep = get_eep(stm)
|
||||
if 'eeprom' in uos.listdir('/'):
|
||||
print('Device already mounted.')
|
||||
else:
|
||||
|
@ -124,8 +127,8 @@ def cptest():
|
|||
|
||||
|
||||
# ***** TEST OF HARDWARE *****
|
||||
def full_test():
|
||||
eep = get_eep()
|
||||
def full_test(stm=False):
|
||||
eep = get_eep(stm)
|
||||
page = 0
|
||||
for sa in range(0, len(eep), 256):
|
||||
data = uos.urandom(256)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# eeprom_spi.py MicroPython driver for Microchip SPI EEPROM devices,
|
||||
# currently only 25xx1024.
|
||||
# eeprom_spi.py MicroPython driver for Microchip 128KiB SPI EEPROM device,
|
||||
# also STM 256KiB chip
|
||||
# TODO the latter not yet tested.
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2019 Peter Hinch
|
||||
|
@ -8,24 +9,29 @@ import time
|
|||
from micropython import const
|
||||
from bdevice import BlockDevice
|
||||
|
||||
_SIZE = const(131072) # Chip size 128KiB
|
||||
# Supported instruction set
|
||||
_READ = const(3)
|
||||
_WRITE = const(2)
|
||||
_WREN = const(6) # Write enable
|
||||
_RDSR = const(5) # Read status register
|
||||
_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
|
||||
# _WRDI = const(4)
|
||||
# _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.
|
||||
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
|
||||
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._cspins = cspins
|
||||
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.scan(verbose)
|
||||
|
||||
# Check for a valid hardware configuration
|
||||
def scan(self, verbose):
|
||||
# STM Datasheet too vague about the ID block. Do we need _WREN? Do we need to poll ready?
|
||||
#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
|
||||
for n, cs in enumerate(self._cspins):
|
||||
mvp[:] = b'\0\0\0\0\0'
|
||||
mvp[0] = _RDID
|
||||
cs(0)
|
||||
self._spi.write_readinto(mvp[:5], mvp[:5])
|
||||
self._spi.write_readinto(mvp, mvp)
|
||||
cs(1)
|
||||
if mvp[4] != 0x29:
|
||||
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:
|
||||
s = '{} chips detected. Total EEPROM size {}bytes.'
|
||||
print(s.format(n + 1, self._a_bytes))
|
||||
|
||||
def erase(self):
|
||||
if self._stm:
|
||||
raise RuntimeError('Erase not available on STM chip')
|
||||
mvp = self._mvp
|
||||
for cs in self._cspins: # For each chip
|
||||
mvp[0] = _WREN
|
||||
|
@ -73,35 +119,6 @@ class EEPROM(BlockDevice):
|
|||
break
|
||||
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.
|
||||
# Return the number of bytes that can be processed in the current page.
|
||||
def _getaddr(self, addr, nbytes):
|
||||
|
|
Ładowanie…
Reference in New Issue