flash_spi.py: Can specify size where auto-detect fails.

pull/16/head
adminpete 2022-12-09 17:41:37 +00:00
rodzic 7d804c5b59
commit 6b42d58b8c
2 zmienionych plików z 45 dodań i 30 usunięć

Wyświetl plik

@ -12,8 +12,8 @@ chips including those with 24-bit addressing. He tested an XPX XT25F32B; I
tested Winbond W25Q32JV 4MiB and Cypress S25FL064L 8MiB devices. 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 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 to be able to support hardware I don't possess. See
for compatibility. [Section 6](./FLASH.md#6-unsupported-chips) for recommendations on settings.
## 1.2 The driver ## 1.2 The driver
@ -34,9 +34,9 @@ an inevitable price for the large capacity of flash chips.
FAT and littlefs filesystems are supported but the latter is preferred owing to FAT and littlefs filesystems are supported but the latter is preferred owing to
its resilience and wear levelling characteristics. Please note that this driver its resilience and wear levelling characteristics. Please note that this driver
has been tested on LFS2 only. Users requiring a driver with minimum code size has been tested on LFS2 only. Users requiring a driver with minimum RAM use
may want to consider [this driver](https://github.com/robert-hh/SPI_Flash) with may want to consider [this driver](https://github.com/robert-hh/SPI_Flash).
LFS1. This supports an LFS1 filesystem on a single flash chip.
Arguably byte level access on such large devices has few use cases other than Arguably byte level access on such large devices has few use cases other than
for facilitating effective hardware tests and for diagnostics. for facilitating effective hardware tests and for diagnostics.
@ -149,21 +149,22 @@ Arguments. In most cases only the first two mandatory args are required:
1. `spi` An initialised SPI bus created by `machine`. 1. `spi` 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. `size=None` Chip size in KiB. The size is read from the chip. If a value 3. `size=None` Chip size in KiB. By default the size is read from the chip; a
is passed, the actual size is compared with the passed value: a mismatch will `ValueError` will occur if chips in the array have differing sizes. See table
raise a `ValueError`. A `ValueError` will also occur if chips in the array below for values of chips tested to date. If a `size` is specified, the driver
have differing sizes. See table below for values of chips tested to date. will assume that the value given is correct. If no `size` is specified and the
chip returns an unexpected value, a `ValueError` will be raised.
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.
7. `cmd5=None` Flash chips can support two low level command sets, an old 4 7. `cmd5=None` Flash chips can support two low level command sets, a 4 byte
byte set and a newer 5 byte set capable of supporting a larger address set and a 5 byte set. By default if the size read from the chip's ID is
space. By default if the size read from the chip's ID is <= 4096KiB the 4 byte <= 4096KiB the 4 byte set is used oterwise the 5 byte set is adopted. This
set is used oterwise the 5 byte set is adopted. This works for supported works for supported chips. Setting `cmd5` `True` forces 5 byte commands,
chips. Setting `cmd5` `True` forces 5 byte commands, `False` forces 4 byte. `False` forces 4 byte. This override is necessary for certain chip types
This override is necessary for certain chip types (e.g. WinBond W25Q64FV). (e.g. WinBond W25Q64FV).
Size values (KiB): Size values (KiB):
| Chip | Size | | Chip | Size |
@ -173,6 +174,9 @@ Size values (KiB):
| Cypress S25FL064L | 8192 | | Cypress S25FL064L | 8192 |
| Winbond W25Q32JV | 4096 | | Winbond W25Q32JV | 4096 |
See [main readme](../README.md#141-chips-tested-by-users) for updates to the
list of supported chips.
### 4.1.2 Methods providing byte level access ### 4.1.2 Methods providing byte level access
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.
@ -319,3 +323,21 @@ cp('/flash/main.py','/fl_ext/')
See `upysh` in [micropython-lib](https://github.com/micropython/micropython-lib.git) See `upysh` in [micropython-lib](https://github.com/micropython/micropython-lib.git)
for other filesystem tools for use at the REPL. for other filesystem tools for use at the REPL.
# 6. Unsupported chips
Flash chips have fairly standard commands so there is a good chance that
unsupported chips will work so long as they are specified correctly.
Automatic size detection for unsupported chips is not guaranteed: some chips
produce nonstandard output on the relevant byte. Specifying the `size`
constructor arg is highly recommended.
It is also best to establish whether it uses 4 or 5 byte commands. This can be
determined from the datasheet. Look up the code for `READ MEMORY`. If it is
`03H` the device uses 4 byte instructions; if `13H` it uses 5-byte instructions.
Instantiate with `cmd5` set `True` or `False` appropriately.
If you have success with a new chip please raise an issue with the part no. and
the `cmd5` setting and I will update the docs.

Wyświetl plik

@ -9,7 +9,7 @@ from bdevice import FlashDevice
# Supported instruction set: # Supported instruction set:
# 3 and 4 byte address commands # 3 and 4 byte address commands
_READ = const(0) _READ = const(0) # Index of _CMDSxBA
_PP = const(1) _PP = const(1)
_SE = const(2) _SE = const(2)
_CMDS3BA = b"\x03\x02\x20" _CMDS3BA = b"\x03\x02\x20"
@ -25,14 +25,7 @@ _SEC_SIZE = const(4096) # Flash sector size 0x1000
# Logical Flash device comprising one or more physical chips sharing an SPI bus. # Logical Flash device comprising one or more physical chips sharing an SPI bus.
class FLASH(FlashDevice): class FLASH(FlashDevice):
def __init__( def __init__(
self, self, spi, cspins, size=None, verbose=True, sec_size=_SEC_SIZE, block_size=9, cmd5=None
spi,
cspins,
size=None,
verbose=True,
sec_size=_SEC_SIZE,
block_size=9,
cmd5=None,
): ):
self._spi = spi self._spi = spi
self._cspins = cspins self._cspins = cspins
@ -46,7 +39,8 @@ class FLASH(FlashDevice):
cs(1) cs(1)
time.sleep_ms(1) # Meet Tpu 300μs time.sleep_ms(1) # Meet Tpu 300μs
size = self.scan(verbose, size) # KiB if size is None: # Get from chip
size = self.scan(verbose, size) # KiB
super().__init__(block_size, len(cspins), size * 1024, sec_size) super().__init__(block_size, len(cspins), size * 1024, sec_size)
# Select the correct command set # Select the correct command set
@ -73,11 +67,10 @@ class FLASH(FlashDevice):
if size is None: if size is None:
size = scansize # Save size of 1st chip size = scansize # Save size of 1st chip
if size != scansize: # Mismatch passed size or 1st chip. if size != scansize: # Mismatch passed size or 1st chip.
raise ValueError( raise ValueError(f"Flash size mismatch: expected {size}KiB, found {scansize}KiB")
"Flash size mismatch: expected {}KiB, found {}KiB".format( if not 0x10 < mvp[3] < 0x22:
size, scansize raise ValueError(f"Invalid chip size {size}KiB. Specify size arg.")
)
)
if verbose: if verbose:
s = "{} chips detected. Total flash size {}MiB." s = "{} chips detected. Total flash size {}MiB."
n += 1 n += 1