Log data to SDCard

This commit is contained in:
Frederik Menke 2024-07-21 21:42:01 +02:00
parent d8ff2b7775
commit ea7e266182
4 changed files with 60 additions and 28 deletions

10
Cargo.lock generated
View file

@ -125,6 +125,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"byte-slice-cast 1.2.2", "byte-slice-cast 1.2.2",
"byteorder", "byteorder",
"core2",
"cortex-m", "cortex-m",
"cortex-m-rt", "cortex-m-rt",
"critical-section", "critical-section",
@ -176,6 +177,15 @@ dependencies = [
"unicode-width", "unicode-width",
] ]
[[package]]
name = "core2"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "cortex-m" name = "cortex-m"
version = "0.7.6" version = "0.7.6"

View file

@ -53,7 +53,7 @@ embedded-sdmmc = "0.7.0"
# Dependencies of embedded-sdmmc that I need to use directly # Dependencies of embedded-sdmmc that I need to use directly
byteorder = {version = "1", default-features = false} byteorder = {version = "1", default-features = false}
core2 = { version = "0.4.0", default-features = false}
[profile.release] [profile.release]
debug = 2 debug = 2

View file

@ -1,6 +1,12 @@
build: build:
cargo build cargo build
attach:
probe-rs attach --chip RP2040 target/thumbv6m-none-eabi/debug/co2_sensing
run:
cargo run
rerun: rerun:
probe-rs reset --chip RP2040 probe-rs reset --chip RP2040
probe-rs attach --chip RP2040 target/thumbv6m-none-eabi/debug/co2_sensing just attach

View file

@ -9,6 +9,7 @@
mod co2; mod co2;
use byteorder::ByteOrder; use byteorder::ByteOrder;
use core2::io::{Cursor, Write};
use defmt::*; use defmt::*;
use embassy_embedded_hal::SetConfig; use embassy_embedded_hal::SetConfig;
use embassy_executor::Spawner; 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::peripherals::{PIN_10, PIN_11, PIN_12, PIN_16, SPI1};
use embassy_rp::spi::Spi; use embassy_rp::spi::Spi;
use embassy_rp::{gpio, 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_hal_bus::spi::ExclusiveDevice;
use embedded_sdmmc::sdcard::{DummyCsPin, SdCard}; use embedded_sdmmc::sdcard::{DummyCsPin, SdCard};
use embedded_sdmmc::{Block, BlockDevice, BlockIdx, VolumeIdx}; use embedded_sdmmc::{Block, BlockDevice, BlockIdx, VolumeIdx};
@ -29,6 +32,8 @@ bind_interrupts!(struct Irqs {
I2C1_IRQ => i2c::InterruptHandler<embassy_rp::peripherals::I2C1>; I2C1_IRQ => i2c::InterruptHandler<embassy_rp::peripherals::I2C1>;
}); });
static MEASUREMENT_VALUES: Channel<ThreadModeRawMutex, u16, 8> = Channel::new();
struct DummyTimesource(); struct DummyTimesource();
impl embedded_sdmmc::TimeSource for 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); embassy_rp::pac::SIO.spinlock(31).write_value(1);
let p = embassy_rp::init(Default::default()); let p = embassy_rp::init(Default::default());
// spawner spawner
// .spawn(write_to_sd(p.SPI1, p.PIN_10, p.PIN_11, p.PIN_12, p.PIN_16)) .spawn(write_to_sd(p.SPI1, p.PIN_10, p.PIN_11, p.PIN_12, p.PIN_16))
// .unwrap(); .unwrap();
// Wake pin is not required as long as its kept low at all times // 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); // let mut nWAKE = gpio::Output::new(p.PIN_13, Level::High);
@ -96,14 +101,14 @@ async fn main(spawner: Spawner) {
status, measured_value status, measured_value
); );
MEASUREMENT_VALUES.send(measured_value).await;
Timer::after(Duration::from_secs(2)).await; Timer::after(Duration::from_secs(2)).await;
} }
} }
#[embassy_executor::task] #[embassy_executor::task]
async fn write_to_sd(spi1: SPI1, pin10: PIN_10, pin11: PIN_11, pin12: PIN_12, pin16: PIN_16) { 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 // SPI clock needs to be running at <= 400kHz during initialization
let mut config = spi::Config::default(); let mut config = spi::Config::default();
config.frequency = 400_000; 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 mut volume_mgr = embedded_sdmmc::VolumeManager::new(sdcard, DummyTimesource());
{ {
let device = volume_mgr.device(); let device = volume_mgr.device();
info!("Listing devices:");
for (index, label) in valid_volumes(device).into_iter().flatten() { for (index, label) in valid_volumes(device).into_iter().flatten() {
info!( info!(
"Volume {}: name: {:?}", "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 let mut volume0 = volume_mgr
.open_volume(embedded_sdmmc::VolumeIdx(0)) .open_volume(embedded_sdmmc::VolumeIdx(0))
.unwrap(); .unwrap();
info!("Volume 0: {:?}", defmt::Debug2Format(&volume0));
// Open the root directory (mutably borrows from the volume). // Open the root directory (mutably borrows from the volume).
let mut root_dir = volume0.open_root_dir().unwrap(); let mut root_dir = volume0.open_root_dir().unwrap();
{ let mut file_count: usize = 0;
// Open a file called "MY_FILE.TXT" in the root directory root_dir.iterate_dir(|_| file_count += 1).unwrap();
// This mutably borrows the directory. info!("Found {} files", file_count);
let mut my_file = root_dir
.open_file_in_dir("MY_FILE.TXT", embedded_sdmmc::Mode::ReadOnly) // 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(); .unwrap();
// Print the contents of the file info!("Writing measurement value {} to file", new_value);
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();
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<D>(block_device: &mut D) -> [Option<(VolumeIdx, [u8; 11])>; 4] pub fn valid_volumes<D>(block_device: &mut D) -> [Option<(VolumeIdx, [u8; 11])>; 4]