kopia lustrzana https://github.com/peterhinch/micropython_eeprom
Document support for extra flash chips.
rodzic
cb1c33303e
commit
33f4dc0658
35
README.md
35
README.md
|
@ -57,19 +57,30 @@ 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 |
|
||||||
|:------------:|:---------:|:---------:|:------:|:----------:|:-----------------------------:|
|
|:------------:|:---------:|:---------:|:-------:|:----------:|:-----------------------------:|
|
||||||
| Cypress | S25FL256L | SPI 4096 | 32MiB | Flash | [FLASH.md](./flash/FLASH.md) |
|
| Various | Various | SPI 4096 | <=32MiB | Flash | [FLASH.md](./flash/FLASH.md) |
|
||||||
| Cypress | S25FL128L | SPI 4096 | 16MiB | Flash | [FLASH.md](./flash/FLASH.md) |
|
| STM | M95M02-DR | SPI 256 | 256KiB | EEPROM | [SPI.md](./eeprom/spi/SPI.md) |
|
||||||
| STM | M95M02-DR | SPI 256 | 256KiB | EEPROM | [SPI.md](./eeprom/spi/SPI.md) |
|
| Microchip | 25xx1024 | SPI 256 | 128KiB | EEPROM | [SPI.md](./eeprom/SPI.md) |
|
||||||
| Microchip | 25xx1024 | SPI 256 | 128KiB | EEPROM | [SPI.md](./eeprom/SPI.md) |
|
| Microchip | 24xx512 | I2C 128 | 64KiB | EEPROM | [I2C.md](./eeprom/i2c/I2C.md) |
|
||||||
| Microchip | 24xx512 | I2C 128 | 64KiB | EEPROM | [I2C.md](./eeprom/i2c/I2C.md) |
|
| Microchip | 24xx256 | I2C 128 | 32KiB | EEPROM | [I2C.md](./eeprom/i2c/I2C.md) |
|
||||||
| Microchip | 24xx256 | I2C 128 | 32KiB | EEPROM | [I2C.md](./eeprom/i2c/I2C.md) |
|
| Microchip | 24xx128 | I2C 128 | 16KiB | EEPROM | [I2C.md](./eeprom/i2c/I2C.md) |
|
||||||
| Microchip | 24xx128 | I2C 128 | 16KiB | EEPROM | [I2C.md](./eeprom/i2c/I2C.md) |
|
| Microchip | 24xx64 | I2C 128 | 8KiB | EEPROM | [I2C.md](./eeprom/i2c/I2C.md) |
|
||||||
| Microchip | 24xx64 | I2C 128 | 8KiB | EEPROM | [I2C.md](./eeprom/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) |
|
|
||||||
|
|
||||||
The flash driver now has the capability to support smaller chips.
|
The flash driver now has the capability to support a variety of chips. The
|
||||||
|
following have been tested to date:
|
||||||
|
|
||||||
|
| Chip | Size (MiB) |
|
||||||
|
|:-----------------:|:----------:|
|
||||||
|
| Cypress S25FL256L | 32 |
|
||||||
|
| Cypress S25FL128L | 16 |
|
||||||
|
| Cypress S25FL064L | 8 |
|
||||||
|
| Winbond W25Q32JV | 4 |
|
||||||
|
|
||||||
|
It is likely that other chips with 4096 byte blocks will work but I am unlikely
|
||||||
|
to be able to support hardware I don't possess. Users should check datasheets
|
||||||
|
for compatibility.
|
||||||
|
|
||||||
## 1.5 Performance
|
## 1.5 Performance
|
||||||
|
|
||||||
|
|
|
@ -63,10 +63,7 @@ class BlockDevice:
|
||||||
return
|
return
|
||||||
|
|
||||||
def readblocks(self, blocknum, buf, offset=0):
|
def readblocks(self, blocknum, buf, offset=0):
|
||||||
if blocknum < 0 or (offset + (blocknum << self._nbits)) > self._a_bytes:
|
self.readwrite(offset + (blocknum << self._nbits), buf, True)
|
||||||
print('rb', hex(blocknum), offset, hex(offset + (blocknum << self._nbits)))
|
|
||||||
else:
|
|
||||||
self.readwrite(offset + (blocknum << self._nbits), buf, True)
|
|
||||||
|
|
||||||
def writeblocks(self, blocknum, buf, offset=0):
|
def writeblocks(self, blocknum, buf, offset=0):
|
||||||
self.readwrite(offset + (blocknum << self._nbits), buf, False)
|
self.readwrite(offset + (blocknum << self._nbits), buf, False)
|
||||||
|
|
|
@ -1,13 +1,21 @@
|
||||||
# 1. A MicroPython Flash memory driver
|
# 1. A MicroPython Flash memory driver
|
||||||
|
|
||||||
|
## 1.1 Device support
|
||||||
|
|
||||||
This driver supports the Cypress S25FL256L and S25FL128L chips, providing 32MiB
|
This driver supports the Cypress S25FL256L and S25FL128L chips, providing 32MiB
|
||||||
and 16MiB respectively. These have 100K cycles of write endurance (compared to
|
and 16MiB respectively. These have 100K cycles of write endurance (compared to
|
||||||
10K for Pyboard Flash memory). These were the largest capacity available with a
|
10K for Pyboard Flash memory). These were the largest capacity available with a
|
||||||
sector size small enough for microcontroller use.
|
sector size small enough for microcontroller use.
|
||||||
|
|
||||||
Thanks to a patch from Daniel Thompson this now has the capability to support
|
Thanks to a patch from Daniel Thompson this now supports a variety of NOR Flash
|
||||||
smaller NOR Flash chips with 24-bit addressing. I lack the chips to test this
|
chips including those with 24-bit addressing. He tested an XPX XT25F32B; I
|
||||||
so am unable to support such use. The author tested on an XPX XT25F32B.
|
tested Winbond W25Q32JV 4MiB and Cypress S25FL064L 8MiB devices.
|
||||||
|
|
||||||
|
It is likely that other chips with 4096 byte blocks will work but I am unlikely
|
||||||
|
to be able to support hardware I don't possess. Users should check datasheets
|
||||||
|
for compatibility.
|
||||||
|
|
||||||
|
## 1.2 The driver
|
||||||
|
|
||||||
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
|
||||||
|
@ -36,8 +44,8 @@ for facilitating effective hardware tests and for diagnostics.
|
||||||
|
|
||||||
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 flash chip, connect to a Pyboard
|
as per the test program. To wire up a single flash chip, connect to a Pyboard
|
||||||
as below. Pin numbers an 8 pin SOIC or WSON package. Inputs marked `nc` may be
|
as below. Pin numbers relate to an 8 pin SOIC or WSON package. Inputs marked
|
||||||
connected to 3V3 or left unconnected.
|
`nc` may be connected to 3V3 or left unconnected.
|
||||||
|
|
||||||
| Flash | Signal | PB | Signal |
|
| Flash | Signal | PB | Signal |
|
||||||
|:-----:|:-------:|:---:|:------:|
|
|:-----:|:-------:|:---:|:------:|
|
||||||
|
@ -50,7 +58,7 @@ connected to 3V3 or left unconnected.
|
||||||
| 7 | RESET/ | nc | - |
|
| 7 | RESET/ | nc | - |
|
||||||
| 8 | Vcc | 3V3 | 3V3 |
|
| 8 | Vcc | 3V3 | 3V3 |
|
||||||
|
|
||||||
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
|
||||||
being wired to a single chip's CS line. The test program assumes a second chip
|
being wired to a single chip's CS line. The test program assumes a second chip
|
||||||
with CS connected to Y4. Multiple chips should have 3V3, Gnd, SCL, MOSI and
|
with CS connected to Y4. Multiple chips should have 3V3, Gnd, SCL, MOSI and
|
||||||
MISO lines wired in parallel.
|
MISO lines wired in parallel.
|
||||||
|
@ -61,7 +69,7 @@ to enable the voltage rail by issuing:
|
||||||
machine.Pin.board.EN_3V3.value(1)
|
machine.Pin.board.EN_3V3.value(1)
|
||||||
time.sleep(0.1) # Allow decouplers to charge
|
time.sleep(0.1) # Allow decouplers to charge
|
||||||
```
|
```
|
||||||
Other platforms may vary but the Cypress chips require a 3.3V supply.
|
Other devices may vary but the Cypress chips require a 3.3V supply.
|
||||||
|
|
||||||
It is wise to add a pullup resistor (say 10KΩ) from each CS/ line to 3.3V. This
|
It is wise to add a pullup resistor (say 10KΩ) from each CS/ line to 3.3V. This
|
||||||
ensures that chips are deselected at initial power up when the microcontroller
|
ensures that chips are deselected at initial power up when the microcontroller
|
||||||
|
@ -85,9 +93,10 @@ Bus lines should be short and direct.
|
||||||
5. `wemos_flash.py` Test program running on a Wemos D1 Mini ESP8266 board.
|
5. `wemos_flash.py` Test program running on a Wemos D1 Mini ESP8266 board.
|
||||||
|
|
||||||
Installation: copy files 1 and 2 (3 - 5 are optional) to the target filesystem.
|
Installation: copy files 1 and 2 (3 - 5 are optional) to the target filesystem.
|
||||||
The `flash_test` script assumes two S25FL256L chips connected to SPI(2) with
|
The `flash_test` script assumes two chips connected to SPI(2) with CS/ pins
|
||||||
CS/ pins wired to Pyboard pins Y4 and Y5. The `get_device` function may be
|
wired to Pyboard pins Y4 and Y5. Device size is detected at runtime. The
|
||||||
adapted for other setups and is shared with `littlefs_test`.
|
`get_device` function may be adapted for other setups and is shared with
|
||||||
|
`littlefs_test`.
|
||||||
|
|
||||||
For a quick check of hardware issue:
|
For a quick check of hardware issue:
|
||||||
```python
|
```python
|
||||||
|
@ -140,18 +149,20 @@ Arguments. In most cases only the first two mandatory args are required:
|
||||||
3. `size=None` Chip size in KiB. The size is read from the chip. If a value
|
3. `size=None` Chip size in KiB. The size is read from the chip. If a value
|
||||||
is passed, the actual size is compared with the passed value: a mismatch will
|
is passed, the actual size is compared with the passed value: a mismatch will
|
||||||
raise a `ValueError`. A `ValueError` will also occur if chips in the array
|
raise a `ValueError`. A `ValueError` will also occur if chips in the array
|
||||||
have differing sizes. See table below for values.
|
have differing sizes. See table below for values of chips tested to date.
|
||||||
4. `verbose=True` If `True`, the constructor issues information on the flash
|
4. `verbose=True` If `True`, the constructor issues information on the flash
|
||||||
devices it has detected.
|
devices it has detected.
|
||||||
5. `sec_size=4096` Chip sector size.
|
5. `sec_size=4096` Chip sector size.
|
||||||
6. `block_size=9` The block size reported to the filesystem. The size in bytes
|
6. `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.
|
||||||
|
|
||||||
Size values:
|
Size values (KiB):
|
||||||
| Chip | Size |
|
| Chip | Size |
|
||||||
|:---------:|:-----:|
|
|:-----------------:|:-----:|
|
||||||
| S25FL256L | 32768 |
|
| Cypress S25FL256L | 32768 |
|
||||||
| S25FL128L | 16384 |
|
| Cypress S25FL128L | 16384 |
|
||||||
|
| Cypress S25FL064L | 8192 |
|
||||||
|
| Winbond W25Q32JV | 4096 |
|
||||||
|
|
||||||
### 4.1.2 Methods providing byte level access
|
### 4.1.2 Methods providing byte level access
|
||||||
|
|
||||||
|
@ -195,8 +206,7 @@ print(flash[2000:2002]) # Returns a bytearray
|
||||||
```
|
```
|
||||||
Three argument slices are not supported: a third arg (other than 1) will cause
|
Three argument slices are not supported: a third arg (other than 1) will cause
|
||||||
an exception. One argument slices (`flash[:5]` or `flash[13100:]`) and negative
|
an exception. One argument slices (`flash[:5]` or `flash[13100:]`) and negative
|
||||||
args are supported. See [section 4.2](./SPI.md#42-byte-addressing-usage-example)
|
args are supported.
|
||||||
for a typical application.
|
|
||||||
|
|
||||||
#### 4.1.2.2 readwrite
|
#### 4.1.2.2 readwrite
|
||||||
|
|
||||||
|
@ -224,13 +234,18 @@ where `flash` is the `FLASH` instance.
|
||||||
|
|
||||||
#### scan
|
#### scan
|
||||||
|
|
||||||
Activate each chip select in turn checking for a valid device and returns the
|
Args:
|
||||||
number of flash devices detected. A `RuntimeError` will be raised if any CS
|
1. `verbose` `bool`. If `True` print information on chips detected.
|
||||||
pin does not correspond to a valid chip.
|
2. `size` `int` or `None`. If an `int` is passed a `ValueError` is thrown if
|
||||||
|
the detected chip size does not match the passed value.
|
||||||
|
|
||||||
Other than for debugging there is no need to call `scan()`: the constructor
|
Activate each chip select in turn checking for a valid device and returns the
|
||||||
will throw a `RuntimeError` if it fails to communicate with and correctly
|
size in KiB of one instance of the flash devices detected. A `RuntimeError`
|
||||||
identify each chip.
|
will be raised if any CS pin does not correspond to a valid chip. A
|
||||||
|
`ValueError` is thrown if the detected chips are not of the same size.
|
||||||
|
|
||||||
|
Other than for debugging there is no need to call `scan()`: it is called by the
|
||||||
|
constructor.
|
||||||
|
|
||||||
#### erase
|
#### erase
|
||||||
|
|
||||||
|
@ -246,7 +261,7 @@ also [here](http://docs.micropython.org/en/latest/reference/filesystem.html#cust
|
||||||
`writeblocks()`
|
`writeblocks()`
|
||||||
`ioctl()`
|
`ioctl()`
|
||||||
|
|
||||||
# 5. Test program flash_spi.py
|
# 5. Test program flash_test.py
|
||||||
|
|
||||||
This assumes a Pyboard 1.x or Pyboard D with two chips wired to SPI(2) as
|
This assumes a Pyboard 1.x or Pyboard D with two chips wired to SPI(2) as
|
||||||
above with chip selects connected to pins `Y4` and `Y5`. It provides the
|
above with chip selects connected to pins `Y4` and `Y5`. It provides the
|
||||||
|
|
|
@ -152,16 +152,10 @@ class FLASH(FlashDevice):
|
||||||
# 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 chip.
|
# Return the number of bytes that can be processed in the current chip.
|
||||||
def _getaddr(self, addr, nbytes):
|
def _getaddr(self, addr, nbytes):
|
||||||
# print(hex(addr), hex(self._a_bytes), hex(self._c_bytes), self._nbits, self._block_size, divmod(addr, self._c_bytes))
|
|
||||||
if addr >= self._a_bytes:
|
if addr >= self._a_bytes:
|
||||||
# print(hex(addr), hex(self._a_bytes), hex(self._c_bytes), self._nbits, self._block_size, divmod(addr, self._c_bytes))
|
|
||||||
raise RuntimeError("Flash Address is out of range")
|
raise RuntimeError("Flash Address is out of range")
|
||||||
ca, la = divmod(addr, self._c_bytes) # ca == chip no, la == offset into chip
|
ca, la = divmod(addr, self._c_bytes) # ca == chip no, la == offset into chip
|
||||||
try:
|
self._ccs = self._cspins[ca] # Current chip select
|
||||||
self._ccs = self._cspins[ca] # Current chip select
|
|
||||||
except:
|
|
||||||
print(ca, la)
|
|
||||||
raise
|
|
||||||
cmdlen = self._cmdlen
|
cmdlen = self._cmdlen
|
||||||
mvp = self._mvp[:cmdlen]
|
mvp = self._mvp[:cmdlen]
|
||||||
if cmdlen > 3:
|
if cmdlen > 3:
|
||||||
|
|
|
@ -159,3 +159,12 @@ def full_test(count=10):
|
||||||
if g != data[n]:
|
if g != data[n]:
|
||||||
print('{} {:2x} {:2x} {:2x}'.format(n, data[n], g, got1[n]))
|
print('{} {:2x} {:2x} {:2x}'.format(n, data[n], g, got1[n]))
|
||||||
break
|
break
|
||||||
|
|
||||||
|
helpstr = '''Available tests:
|
||||||
|
test() Basic hardware test.
|
||||||
|
full_test(count=10) Full hardware test, count is no. of passes.
|
||||||
|
fstest(format=False) Check or create littlefs filesystem.
|
||||||
|
cptest() Copy 2 files to filesystem.
|
||||||
|
cp() Primitive copy routine. See docs.
|
||||||
|
'''
|
||||||
|
print(helpstr)
|
||||||
|
|
|
@ -73,3 +73,5 @@ def main():
|
||||||
print('Rewrote', n, length)
|
print('Rewrote', n, length)
|
||||||
check_all()
|
check_all()
|
||||||
remove_all()
|
remove_all()
|
||||||
|
|
||||||
|
print('main() to run littlefs test. Filesystem must exist.')
|
||||||
|
|
Ładowanie…
Reference in New Issue