From fd5412ffc50384c5e5e32c1a2bc499b558a99e8b Mon Sep 17 00:00:00 2001
From: kalkyl <henrik.alser@me.com>
Date: Sat, 11 May 2024 15:16:20 +0200
Subject: [PATCH 1/2] rp: Add embedded-sdmmc example

---
 examples/rp/Cargo.toml           |  1 +
 examples/rp/src/bin/spi_sdmmc.rs | 80 ++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+)
 create mode 100644 examples/rp/src/bin/spi_sdmmc.rs

diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index 8162e4dcb..73d19c28b 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -49,6 +49,7 @@ log = "0.4"
 pio-proc = "0.2"
 pio = "0.2.1"
 rand = { version = "0.8.5", default-features = false }
+embedded-sdmmc = "0.7.0"
 
 [profile.release]
 debug = 2
diff --git a/examples/rp/src/bin/spi_sdmmc.rs b/examples/rp/src/bin/spi_sdmmc.rs
new file mode 100644
index 000000000..0912490d8
--- /dev/null
+++ b/examples/rp/src/bin/spi_sdmmc.rs
@@ -0,0 +1,80 @@
+//! This example shows how to use `embedded-sdmmc` with the RP2040 chip, over SPI.
+//!
+//! The example will attempt to read a file `MY_FILE.TXT` from the root directory
+//! of the SD card and print its contents.
+
+#![no_std]
+#![no_main]
+
+use defmt::*;
+use embassy_embedded_hal::SetConfig;
+use embassy_executor::Spawner;
+use embassy_rp::spi::Spi;
+use embassy_rp::{gpio, spi};
+use embedded_hal_bus::spi::ExclusiveDevice;
+use embedded_sdmmc::sdcard::{DummyCsPin, SdCard};
+use gpio::{Level, Output};
+use {defmt_rtt as _, panic_probe as _};
+
+struct DummyTimesource();
+
+impl embedded_sdmmc::TimeSource for DummyTimesource {
+    fn get_timestamp(&self) -> embedded_sdmmc::Timestamp {
+        embedded_sdmmc::Timestamp {
+            year_since_1970: 0,
+            zero_indexed_month: 0,
+            zero_indexed_day: 0,
+            hours: 0,
+            minutes: 0,
+            seconds: 0,
+        }
+    }
+}
+
+#[embassy_executor::main]
+async fn main(_spawner: Spawner) {
+    let p = embassy_rp::init(Default::default());
+
+    // SPI clock needs to be running at <= 400kHz during initialization
+    let mut config = spi::Config::default();
+    config.frequency = 400_000;
+    let spi = Spi::new_blocking(p.SPI1, p.PIN_10, p.PIN_11, p.PIN_12, config);
+    // Use a dummy cs pin here, for embedded-hal SpiDevice compatibility reasons
+    let spi_dev = ExclusiveDevice::new_no_delay(spi, DummyCsPin);
+    // Real cs pin
+    let cs = Output::new(p.PIN_16, Level::High);
+
+    let sdcard = SdCard::new(spi_dev, cs, embassy_time::Delay);
+    info!("Card size is {} bytes", sdcard.num_bytes().unwrap());
+
+    // Now that the card is initialized, the SPI clock can go faster
+    let mut config = spi::Config::default();
+    config.frequency = 16_000_000;
+    sdcard.spi(|dev| dev.bus_mut().set_config(&config)).ok();
+
+    // Now let's look for volumes (also known as partitions) on our block device.
+    // To do this we need a Volume Manager. It will take ownership of the block device.
+    let mut volume_mgr = embedded_sdmmc::VolumeManager::new(sdcard, DummyTimesource());
+
+    // Try and access Volume 0 (i.e. the first partition).
+    // The volume object holds information about the filesystem on that volume.
+    let mut volume0 = volume_mgr.open_volume(embedded_sdmmc::VolumeIdx(0)).unwrap();
+    info!("Volume 0: {:?}", defmt::Debug2Format(&volume0));
+
+    // Open the root directory (mutably borrows from the volume).
+    let mut root_dir = volume0.open_root_dir().unwrap();
+
+    // Open a file called "MY_FILE.TXT" in the root directory
+    // This mutably borrows the directory.
+    let mut my_file = root_dir
+        .open_file_in_dir("MY_FILE.TXT", embedded_sdmmc::Mode::ReadOnly)
+        .unwrap();
+
+    // Print the contents of the file
+    while !my_file.is_eof() {
+        let mut buf = [0u8; 32];
+        if let Ok(n) = my_file.read(&mut buf) {
+            info!("{:a}", buf[..n]);
+        }
+    }
+}

From 17d4f0173cc7a3078112a0dca6a4c0de39373b13 Mon Sep 17 00:00:00 2001
From: kalkyl <henrik.alser@me.com>
Date: Sat, 11 May 2024 16:09:20 +0200
Subject: [PATCH 2/2] spinlock + loop at end to allow defmt to flush properly

---
 examples/rp/src/bin/spi_sdmmc.rs | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/examples/rp/src/bin/spi_sdmmc.rs b/examples/rp/src/bin/spi_sdmmc.rs
index 0912490d8..4cbc82f7b 100644
--- a/examples/rp/src/bin/spi_sdmmc.rs
+++ b/examples/rp/src/bin/spi_sdmmc.rs
@@ -33,6 +33,7 @@ impl embedded_sdmmc::TimeSource for DummyTimesource {
 
 #[embassy_executor::main]
 async fn main(_spawner: Spawner) {
+    embassy_rp::pac::SIO.spinlock(31).write_value(1);
     let p = embassy_rp::init(Default::default());
 
     // SPI clock needs to be running at <= 400kHz during initialization
@@ -77,4 +78,6 @@ async fn main(_spawner: Spawner) {
             info!("{:a}", buf[..n]);
         }
     }
+
+    loop {}
 }