From ea7e2661820a8075ae30d226c8be8db83cd47f1b Mon Sep 17 00:00:00 2001 From: Frederik Menke Date: Sun, 21 Jul 2024 21:42:01 +0200 Subject: [PATCH] Log data to SDCard --- Cargo.lock | 10 ++++++++ Cargo.toml | 2 +- justfile | 8 ++++++- src/main.rs | 68 +++++++++++++++++++++++++++++++++-------------------- 4 files changed, 60 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f24a4b..0c9f2c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,6 +125,7 @@ version = "0.1.0" dependencies = [ "byte-slice-cast 1.2.2", "byteorder", + "core2", "cortex-m", "cortex-m-rt", "critical-section", @@ -176,6 +177,15 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + [[package]] name = "cortex-m" version = "0.7.6" diff --git a/Cargo.toml b/Cargo.toml index ee3d0cf..6158a6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,7 @@ embedded-sdmmc = "0.7.0" # Dependencies of embedded-sdmmc that I need to use directly byteorder = {version = "1", default-features = false} - +core2 = { version = "0.4.0", default-features = false} [profile.release] debug = 2 diff --git a/justfile b/justfile index d2affd8..0d7c585 100644 --- a/justfile +++ b/justfile @@ -1,6 +1,12 @@ build: cargo build +attach: + probe-rs attach --chip RP2040 target/thumbv6m-none-eabi/debug/co2_sensing + +run: + cargo run + rerun: probe-rs reset --chip RP2040 - probe-rs attach --chip RP2040 target/thumbv6m-none-eabi/debug/co2_sensing + just attach diff --git a/src/main.rs b/src/main.rs index 99432c7..ea58c25 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ mod co2; use byteorder::ByteOrder; +use core2::io::{Cursor, Write}; use defmt::*; use embassy_embedded_hal::SetConfig; use embassy_executor::Spawner; @@ -16,6 +17,8 @@ use embassy_rp::bind_interrupts; use embassy_rp::peripherals::{PIN_10, PIN_11, PIN_12, PIN_16, SPI1}; use embassy_rp::spi::Spi; use embassy_rp::{gpio, spi}; +use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; +use embassy_sync::channel::Channel; use embedded_hal_bus::spi::ExclusiveDevice; use embedded_sdmmc::sdcard::{DummyCsPin, SdCard}; use embedded_sdmmc::{Block, BlockDevice, BlockIdx, VolumeIdx}; @@ -29,6 +32,8 @@ bind_interrupts!(struct Irqs { I2C1_IRQ => i2c::InterruptHandler; }); +static MEASUREMENT_VALUES: Channel = Channel::new(); + struct DummyTimesource(); impl embedded_sdmmc::TimeSource for DummyTimesource { @@ -49,9 +54,9 @@ async fn main(spawner: Spawner) { embassy_rp::pac::SIO.spinlock(31).write_value(1); let p = embassy_rp::init(Default::default()); - // spawner - // .spawn(write_to_sd(p.SPI1, p.PIN_10, p.PIN_11, p.PIN_12, p.PIN_16)) - // .unwrap(); + spawner + .spawn(write_to_sd(p.SPI1, p.PIN_10, p.PIN_11, p.PIN_12, p.PIN_16)) + .unwrap(); // Wake pin is not required as long as its kept low at all times // let mut nWAKE = gpio::Output::new(p.PIN_13, Level::High); @@ -96,14 +101,14 @@ async fn main(spawner: Spawner) { status, measured_value ); + MEASUREMENT_VALUES.send(measured_value).await; + Timer::after(Duration::from_secs(2)).await; } } #[embassy_executor::task] async fn write_to_sd(spi1: SPI1, pin10: PIN_10, pin11: PIN_11, pin12: PIN_12, pin16: PIN_16) { - Timer::after(Duration::from_secs(2)).await; - // SPI clock needs to be running at <= 400kHz during initialization let mut config = spi::Config::default(); config.frequency = 400_000; @@ -127,6 +132,7 @@ async fn write_to_sd(spi1: SPI1, pin10: PIN_10, pin11: PIN_11, pin12: PIN_12, pi let mut volume_mgr = embedded_sdmmc::VolumeManager::new(sdcard, DummyTimesource()); { let device = volume_mgr.device(); + info!("Listing devices:"); for (index, label) in valid_volumes(device).into_iter().flatten() { info!( "Volume {}: name: {:?}", @@ -141,35 +147,45 @@ async fn write_to_sd(spi1: SPI1, pin10: PIN_10, pin11: PIN_11, pin12: PIN_12, pi 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) + let mut file_count: usize = 0; + root_dir.iterate_dir(|_| file_count += 1).unwrap(); + info!("Found {} files", file_count); + + // ShortFileName::FILENAME_MAX_LEN == 11. Therefore, we can't go any longer + // However, this should be fine as we have 8 chars => 10^8 = 100000000 + // possible files. + let mut file_name_buffer = [0; 11]; + let mut cursor = Cursor::new(&mut file_name_buffer[..]); + core::write!(&mut cursor, "{}.txt", file_count + 1) + .expect("File count + extension should definetly fit into 11 bytes"); + let final_position = cursor.position() as usize; + let file_name = core::str::from_utf8(&file_name_buffer[..final_position]) + .expect("We only put ASCII into the buffer"); + + info!("Creating new text file: {}", file_name); + + loop { + let new_value = MEASUREMENT_VALUES.receive().await; + + let mut file = root_dir + .open_file_in_dir(file_name, embedded_sdmmc::Mode::ReadWriteCreateOrAppend) .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]); - } - } - } - { - // Append some text to the end of the file - let mut my_file = root_dir - .open_file_in_dir("MY_FILE.TXT", embedded_sdmmc::Mode::ReadWriteAppend) - .unwrap(); + info!("Writing measurement value {} to file", new_value); - my_file.write(b"Another one\n").unwrap(); + // Space for five characters to fit numbers up to 65535 + '\n' + let mut to_write = [b' '; 6]; + let mut cursor = Cursor::new(&mut to_write[..]); + core::write!(&mut cursor, "{}", new_value) + .expect("We have more than enough bytes to fit an u16"); + to_write[5] = b'\n'; + file.write(&to_write).unwrap(); + drop(file); } - debug!("TASK ENDED: SdCard") } pub fn valid_volumes(block_device: &mut D) -> [Option<(VolumeIdx, [u8; 11])>; 4]