micropython_eeprom icon indicating copy to clipboard operation
micropython_eeprom copied to clipboard

How to use the driver properly

Open Yordan01 opened this issue 3 years ago • 9 comments

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

Yordan01 avatar Mar 28 '23 19:03 Yordan01

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.

peterhinch avatar Mar 29 '23 08:03 peterhinch

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.

Yordan01 avatar Mar 29 '23 09:03 Yordan01

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.

peterhinch avatar Mar 29 '23 17:03 peterhinch

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:)

MlgmXyysd avatar Sep 25 '23 17:09 MlgmXyysd

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

MlgmXyysd avatar Sep 25 '23 17:09 MlgmXyysd

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

MlgmXyysd avatar Sep 25 '23 18:09 MlgmXyysd

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.

peterhinch avatar Sep 26 '23 11:09 peterhinch

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. wx_camera_1695665535966.jpg

MlgmXyysd avatar Sep 26 '23 11:09 MlgmXyysd

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.

peterhinch avatar Sep 27 '23 08:09 peterhinch