SD Card Storage with Pico 2 W

SD cards provide removable storage for logging data, storing files, or creating standalone data loggers with the Raspberry Pi Pico 2 W. SD cards communicate via SPI protocol, making them straightforward to interface with the Pico.

Hardware Requirements

Note

SD Card Module

Most SD card modules have built-in voltage regulators and level shifters, allowing safe operation with 3.3V microcontrollers like the Pico. They typically include pins for VCC, GND, MISO, MOSI, SCK, and CS.

SPI Connection

Connect the SD card module to the Pico using SPI:

VCC → 3.3V

GND → GND

MISO → GPIO 4 (SPI0 RX)

MOSI → GPIO 7 (SPI0 TX)

SCK → GPIO 6 (SPI0 SCK)

CS → GPIO 5 (Chip Select)

Required Crates

toml
[dependencies]
embedded-sdmmc = "0.7"
embedded-hal-bus = "0.2"

Initializing SD Card

rust
use embedded_sdmmc::{SdCard, VolumeManager, VolumeIdx};

// Setup SPI
let spi_mosi = pins.gpio7.into_function::<hal::gpio::FunctionSpi>();
let spi_miso = pins.gpio4.into_function::<hal::gpio::FunctionSpi>();
let spi_sclk = pins.gpio6.into_function::<hal::gpio::FunctionSpi>();
let spi_cs = pins.gpio5.into_push_pull_output();

let spi_bus = hal::spi::Spi::<_, _, _, 8>::new(
    pac.SPI0,
    (spi_mosi, spi_miso, spi_sclk)
);

let spi = spi_bus.init(
    &mut pac.RESETS,
    clocks.peripheral_clock.freq(),
    400.kHz(), // SD card init speed
    embedded_hal::spi::MODE_0,
);

// Create SD card controller
let sdcard = SdCard::new(spi, spi_cs, timer);
let mut volume_mgr = VolumeManager::new(sdcard, DummyTimesource);

Writing to SD Card

rust
// Open volume (partition)
let volume = volume_mgr.open_volume(VolumeIdx(0))?;

// Open root directory
let root_dir = volume.open_root_dir()?;

// Create/open file
let mut file = root_dir.open_file_in_dir(
    "DATA.TXT",
    embedded_sdmmc::Mode::ReadWriteCreateOrAppend
)?;

// Write data
let data = b"Temperature: 25.3C\n";
file.write(data)?;

Reading from SD Card

rust
// Open file for reading
let mut file = root_dir.open_file_in_dir(
    "DATA.TXT",
    embedded_sdmmc::Mode::ReadOnly
)?;

// Read data
let mut buffer = [0u8; 512];
let bytes_read = file.read(&mut buffer)?;

// Process read data
let text = core::str::from_utf8(&buffer[..bytes_read])?;

Pico 2 W Considerations

The Pico 2 W's SPI functionality works perfectly with SD cards. Key points:

Common Applications

Best Practices