How to use the driver properly
Hi Peter,
I am trying to use your driver for a university project, which will involve writing some data to a FLASH memory and then extracting it via the Pi Pico. The flash that I am using is W25Q32JVSSIQ and it passes all the tests well, except for the fstest(), for which I had to manually create a directory with the Pi in order for it to pass.
I installed flash_spi.py and bdevice_py on my pico and modified the code to fit my communication connections:
from machine import UART, Pin, SPI import time, os from flash_spi import FLASH
cspins = (Pin(1, Pin.OUT, value=1),) flash = FLASH(SPI(0, baudrate=50_000_000, sck=Pin(2), mosi=Pin(3), miso=Pin(0)), cspins, size=4096)
Format the filesystem
os.VfsLfs2.mkfs(flash) # Omit this to mount an existing filesystem os.mount(flash,'/fl_ext')
Everything works well, but from this point on I do not know how exactly to use this file system. I try to open and close a file in the flash:
Open File
file = open('fl_ext/DataRaw.dat', 'w')
###################################
Write the NMEA data into FLASH memory until memory is full
rxData = bytearray()
while time.ticks_ms() < 60 * 1000: if uart1.any(): byte = uart1.read(1) if byte == b'\n': file.write(rxData.decode('UTF-8')) rxData = bytearray() # Reset rxData variable else: rxData += byte file.close()
But once I close it, the file system is lost, so I cannot extract the data that I have saved. Any tips?
Yordan
Please enclose code with triple backtick characters to preserve indentation. I assume it should read
rxData = bytearray()
while time.ticks_ms() < 60 * 1000:
if uart1.any():
byte = uart1.read(1)
if byte == b'\n':
file.write(rxData.decode('UTF-8'))
rxData = bytearray() # Reset rxData variable
else:
rxData += byte
file.close()
Note that Python's "w" mode overwrites the file, so you will only see the last record. I suspect you really wanted "a".
I cannot see a reason why the file is lost, unless you are re-formatting the disk each time you mount it. This will erase everything.
I suggest you practice using the Flash filesystem by using the supplied cp routine or upysh to create and remove files, and to convince yourself that the Flash contents are retained during a power outage.
Hi Peter,
Thanks for the response! I apologize for the indentation, I assumed that it was preserved and didn't notice that it was lost, also I am new to GitHub and am getting used to the interface.
The main issue I am having is that if uncomment the line:
os.VfsLfs2.mkfs(flash) # Omit this to mount an existing filesystem
then I get Errno19 ENODEV when I run os.mount(flash, '/fl_ext'):
OSError: [Errno 19] ENODEV
fstest(True) works well now and gives the following output:
1 chips detected. Total flash size 4MiB.
Instantiated Flash
Contents of "/": ['fl_ext', 'bdevice.py', 'flash_spi.py', 'main.py']
Contents of "/fl_ext": []
(512, 512, 8192, 8190, 8190, 0, 0, 0, 0, 255)
The cp() and cptest() both fail at the following line:
def cp(source, dest):
if dest.endswith("/"): # minimal way to allow
dest = "".join((dest, source.split("/")[-1])) # cp /sd/file /fl_ext/
with open(source, "rb") as infile: # Caller should handle any OSError
with open(dest, "wb") as outfile: # e.g file not found ->> **Fail here**
while True:
buf = infile.read(100)
outfile.write(buf)
if len(buf) < 100:
break
And the error that I get is OSError: 84.
On the assumption that you've modified flash_test.py so that it works with your hardware, the following works here:
import os
from flash_test import get_device, cp
os.mount(get_device(), '/fl_ext')
os.listdir('/fl_ext') # Shows [] because the filesystem was previously formatted
cp('/flash/main.py','/fl_ext/') # NOTE: check the source path! This is for a Pyboard.
os.listdir('/fl_ext') # now shows ['main.py']
os.umount('/fl_ext')
I then power cycled the system and ran
import os
from flash_test import get_device, cp
os.mount(get_device(), '/fl_ext')
os.listdir('/fl_ext') # Shows ['main.py']
The filesystem has persisted.
Same here. My device is Raspberry Pi Pico WH with WinBond W25Q128.
| W25Q128 | connect to | Raspberry Pi Pico WH |
|---|---|---|
| Data Input (DI) | -> | GPIO 19 (SPI0 TX) |
| SLK | -> | GPIO 18 (SPI0 SCK) |
| CS | -> | GPIO 17 (SPI0 CSn) |
| Data Output (DO) | -> | GPIO 16 (SPI0 RX) |
So I modify get_device in flash_test.py:
def get_device():
PIN_DI = Pin(19) # GP19 (SPI0 TX)
PIN_SLK = Pin(18) # GP18 (SPI0 SCK)
PIN_CS = Pin(17, mode=Pin.OUT, value=1) # GP17 (SPI0 CSn)
PIN_DO = Pin(16) # GP16 (SPI0 RX)
flash = FLASH(SPI(0, baudrate=20_000_000, sck=PIN_SLK, mosi=PIN_DI, miso=PIN_DO), (PIN_CS,), cmd5=False)
return flash
I run these test:
import os
from machine import SPI, Pin
from flash_spi import FLASH
import flash_test
flash_test.test()
flash_test.full_test(count=10)
flash_test.fstest(format=True)
flash_test.cptest()
Test failed at cptest with OSError: 84:
MPY: soft reboot
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.
1 chips detected. Total flash size 16MiB.
Test of byte addressing passed
Test of slice readback passed
Test block boundary 256 passed
Test chip boundary skipped: only one chip!
1 chips detected. Total flash size 16MiB.
Pass 0 address 00570070 passed
Pass 1 address 0069a230 passed
Pass 2 address 00f16491 passed
Pass 3 address 002663ad passed
Pass 4 address 000a9d0f passed
Pass 5 address 0045bdb6 passed
Pass 6 address 009620fd passed
Pass 7 address 00d54032 passed
Pass 8 address 008eb9c4 passed
Pass 9 address 00deea44 passed
1 chips detected. Total flash size 16MiB.
Contents of "/": ['fl_ext', 'bdevice.py', 'boot.py', 'flash_spi.py', 'flash_test.py', 'lib', 'littlefs_test.py']
Contents of "/fl_ext": []
(512, 512, 32768, 32766, 32766, 0, 0, 0, 0, 255)
1 chips detected. Total flash size 16MiB.
Device already mounted.
Traceback (most recent call last):
File "<stdin>", line 9, in <module>
File "flash_test.py", line 132, in cptest
File "flash_test.py", line 31, in cp
OSError: 84
(line 31 is with open(dest, "wb") as outfile:)
While I try to write file with VfsLfs2, FS lost after reset machine.
- Input
import os
from flash_test import get_device
flash = get_device()
os.VfsLfs2.mkfs(flash)
os.mount(flash, '/mnt')
with open('/mnt/example.txt', 'w') as file:
file.write('This is an example file.')
with open('/mnt/example.txt', 'r') as file:
print(file.read())
print(uos.listdir('/mnt'))
machine.reset()
- Output
MPY: soft reboot
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.
1 chips detected. Total flash size 16MiB.
This is an example file.
['example.txt']
After reset machine:
- Input
import os
from flash_test import get_device
flash = get_device()
os.mount(flash, '/mnt')
with open('/mnt/example.txt', 'r') as file:
print(file.read())
- Output
MPY: soft reboot
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.
1 chips detected. Total flash size 16MiB.
Traceback (most recent call last):
File "<stdin>", line 5, in <module>
OSError: [Errno 19] ENODEV
Write test failed on byte write by this method too:
- Input
import os
from flash_test import get_device
flash = get_device()
flash[20] = 100
print(flash[20])
flash.sync()
- Output
1 chips detected. Total flash size 16MiB.
100
After reset:
import os
from flash_test import get_device
flash = get_device()
print(flash[20])
- Output (byte reset after machine reset)
1 chips detected. Total flash size 16MiB.
127
You appear to have an old version of flash_test.py:
(line 31 is with open(dest, "wb") as outfile:)
does not correspond with this line.
We both need to be running the same code. Please ensure that all executable files are up to date.
You appear to have an old version of
flash_test.py:(line 31 is with open(dest, "wb") as outfile:)
does not correspond with this line.
We both need to be running the same code. Please ensure that all executable files are up to date.
No it's latest. I modified 'get_device' func to adapt to my machine. So the correct line is L38.
How is your system powered? The reason I ask is that the Flash chip's maximum Vcc is 3.6V and Vbus will be about 5V if you connect a USB cable.
The fact that it fails the simple test of writing a single byte with the data not surviving a power cycle suggests that there is a basic fault somewhere.
import os
from flash_test import get_device
flash = get_device()
flash[20] = 100
print(flash[20])
flash.sync()
The fact that this prints 100 does not mean that the device has successfully been written: the data will be read back from the driver's buffer. I suspect that an electrical problem is preventing the write. Consequently after a power cycle you are getting invalid data. It's odd that it reads 127 because the unwritten state is 255 (0xFF).
This is hard for me to debug on the other side of the world.