Raspberry Pi Pico File System & SD Card Reader
Written by Mike James & Harry Fairhead   
Monday, 29 May 2023
Article Index
Raspberry Pi Pico File System & SD Card Reader
File Systems
sdcard Driver

File Systems

Working at the block level is fairly tedious and something you can generally avoid. As already mentioned, when MicroPython is first started it ensures that there is a file system installed in the partition and mounts it on the root ready for you to use.

The Pico supports two general file systems - a traditional FAT system and MicroPython’s own littlefs v2. You can create either type of file system on the data partition.The advantage of FAT is that it is a standard file system that can be read by other devices, but as we are using the internal Flash memory this isn’t relevant. FAT is more prone to errors than the alternative littlefs v2 which has the advantage of supporting wear leveling. For these reasons the Pico creates a littlefs v2 file system for you to use.

To work with a file system you first have to create it in a suitable partition – usually indicated by bdev:

os.VfsFat.mkfs(block_dev)

creates a FAT file system and:

os.VfsLfs2.mkfs(block_dev, readsize=32, progsize=32, 
lookahead=32, mtime=True)

creates a littlefs v2 file system. Creating a file system on a partition is essentially formatting it and hence all existing data is lost.

Once you have created a file system it can be mounted either as the root file system or on any existing subdirectory:

os.mount(fsobj, mount_point, *, readonly)

To make modifications to the file system you have to unmount it:

os.umount(mount_point)

You can install an alternative file system or just reformat the partition to remove all of the data. For example:

from rp2 import Flash
import os
flash=Flash()
os.umount('/')
os.VfsLfs2.mkfs(flash)
os.mount(flash, '/')

Most of the time you simply use a file system via the standard MicroPython os functions:

os.chdir(path) Change current directory
os.getcwd() Get the current directory.
os.ilistdir(dir) Iterate through directories returns
(name, type, inode[, size]):
os.listdir(dir) list the given directory.
os.mkdir(path) Create a new directory.
os.remove(path) Remove a file.
os.rmdir(path) Remove a directory.
os.rename(old_path, new_path) Rename a file.
os.stat(path) Get the status of a file or directory.
os.sync() Sync all filesystems.

There is also:

os.statvfs(path) Get the status of a filesystem.

which returns a tuple with the filesystem information in the following order:

f_bsize – file system block size
f_frsize – fragment size
f_blocks – size of fs in f_frsize units
f_bfree – number of free blocks
f_bavail – number of free blocks for unprivileged users
f_files – number of inodes
f_ffree – number of free inodes
f_favail – number of free inodes for unprivileged users
f_flag – mount flags
f_namemax – maximum filename length

Not all values are returned for a littlefs v2 file system.

You can also open a file and work with it using the standard stream functions:

read(), write(), readinto(), seek(), flush(), close()

For example:

from rp2 import Flash
import os

print(os.listdir("/"))
f=open("Hello.txt","wt")
f.write("Hello World")
f.close
f.flush()
print(os.listdir("/"))
f=open("Hello.txt","rt")
s=f.read()
f.close
print(s)

If you try this out you will discover that there is a new file called “Hello.txt” and you should see its contents displayed. Notice that you do need the flush as the system is buffered and if you simply open the file after closing it you will find that it is empty.

As this is non-volatile storage, you can use it to save state between boots.

Adding an External SD Card Reader

Although the Pico doesn’t have an SD card reader it is fairly easy to add one. Add-on SD card readers are available to order at very reasonable prices ($1.50):

sdreader

The only problem is that most have no documentation or specifications and they lack a card-detect and a write-protect pin. Connection to the Pico is fairly easy via one of the SPI buses. The only complication is that most of the devices need a 5V supply. They work at 3.3V logic levels and so can be directly connected to the Pico and have an onboard voltage regulator to reduce the supply to 3.3V. Most claim to work if powered from 3.3V but this depends on the regulator used and some fail or become unreliable,. The Pico has a suitable 5V supply pin in the form of VBUS but notice that this only works if it is being powered from the USB connection. In most cases this is the VCC connection to use.

Notice that you don't actually need an SD card reader as the pins on an SD card are nothing more than an SPI bus. The problem is you have to find a way to connect to them!

You can use any GPIO lines for the SPI connection and in this example the following are used:

sck

GP10

cs

GP9

miso

GP11

mosi

GP8

 sdreader2

Once you have this wired up you need an SD card freshly formatted using FAT and a single partition – which is what you get if you use a new SD card. Make sure the card is correctly inserted before moving on to the software.



Last Updated ( Thursday, 08 June 2023 )