Skip to content

Commit

Permalink
staging
Browse files Browse the repository at this point in the history
  • Loading branch information
jeandudey committed Oct 21, 2023
1 parent 12903d5 commit 07caea0
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 13 deletions.
1 change: 1 addition & 0 deletions extmod/foundation-rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions extmod/foundation-rust/spi-nor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ edition = "2021"
[dependencies]
bitflags = { version = "2", default-features = false }
embedded-hal = "0.2.1"
nb = "1"
69 changes: 56 additions & 13 deletions extmod/foundation-rust/spi-nor/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
// SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. <hello@foundationdevices.com>
// SPDX-License-Identifier: GPL-3.0-or-later

//! Driver for SPI-NOR memory flashes.
//!
//! NOTE: perhaps this requires it's own repository if we need it for anything
//! else.
//!
//! TODO: This could be tested with qemu.
//!
//! See:
//!
//! https://github.com/qemu/qemu/blob/master/hw/block/m25p80.c

#![no_std]

use bitflags::bitflags;
Expand All @@ -19,28 +30,57 @@ impl<SPI: Transfer<u8>, CS: OutputPin> Flash<SPI, CS> {
Self { spi, cs }
}

/// Probe that the flash memory is present.
pub fn probe(&mut self) -> Result<(), Error<SPI, CS>> {
self.read_jedec_id()?;
/// Read from the memory.
///
/// # Errors
///
/// Returns [`nb::Error::WouldBlock`] if the memory has not finished yet
/// an operation.
pub fn read(
&mut self,
address: u32,
buf: &mut [u8],
) -> nb::Result<(), Error<SPI, CS>> {
let status = self.read_status()?;
if status.intersects(Status::BUSY) {
return Err(nb::Error::WouldBlock);
}

let mut instruction = [
Instruction::ReadData as u8,
((address >> 16) & 0xFF) as u8,
((address >> 8) & 0xFF) as u8,
(address & 0xFF) as u8,
];

self.cs.set_low().map_err(Error::Pin)?;

// Send the READ DATA instruction first.
let result = self.spi.transfer(&mut instruction).map_err(Error::Spi);
if result.is_err() {
self.cs.set_high().map_err(Error::Pin)?;
return Err(nb::Error::Other(result.unwrap_err()));
}

// Perform the read.
let result = self.spi.transfer(buf).map_err(Error::Spi);

self.cs.set_high().map_err(Error::Pin)?;

result?;

Ok(())
}

/// Reads the status register.
pub fn read_status(&mut self) -> Result<Status, Error<SPI, CS>> {
let mut buf = [Instruction::ReadStatusRegister as u8, 0];
let res = self.transfer(&mut buf)?;
let res = self.instruction(&mut buf)?;
Ok(Status::from_bits(res[0])
.expect("all of status bits should be defined"))
}

/// Reads the JEDEC ID.
pub fn read_jedec_id(&mut self) -> Result<(), Error<SPI, CS>> {
let mut buf = [Instruction::ReadJedecId as u8, 0, 0, 0];
let _res = self.transfer(&mut buf)?;
Ok(())
}

fn transfer<'b>(
fn instruction<'b>(
&mut self,
buf: &'b mut [u8],
) -> Result<&'b [u8], Error<SPI, CS>> {
Expand All @@ -51,15 +91,18 @@ impl<SPI: Transfer<u8>, CS: OutputPin> Flash<SPI, CS> {
}
}

#[derive(Debug)]
pub enum Error<SPI: Transfer<u8>, CS: OutputPin> {
/// SPI error.
Spi(SPI::Error),
/// GPIO pin error.
Pin(CS::Error),
}

#[derive(Debug)]
enum Instruction {
ReadData = 0x03,
ReadStatusRegister = 0x05,
ReadJedecId = 0x9F,
}

bitflags! {
Expand Down

0 comments on commit 07caea0

Please sign in to comment.