aboutsummaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs194
1 files changed, 171 insertions, 23 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 8f1203f..eeaa022 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -12,10 +12,6 @@ pub mod sequences {
pub mod flash {
use super::{IpCmd, SeqId, flexspi};
- pub mod adesto;
- pub mod issi;
- pub mod winbond;
-
/// Conveniently the default AHB read sequence index.
const READ: IpCmd = IpCmd::new(SeqId::Seq00, 1).unwrap();
const READ_STATUS: IpCmd = IpCmd::new(SeqId::Seq01, 1).unwrap();
@@ -24,9 +20,8 @@ pub mod flash {
const PAGE_PROGRAM: IpCmd = IpCmd::new(SeqId::Seq09, 2).unwrap();
const CHIP_ERASE: IpCmd = IpCmd::new(SeqId::Seq11, 2).unwrap();
- const SET_READ_PARAMS: IpCmd = IpCmd::new(SeqId::Seq02, 1).unwrap();
const READ_ID_JEDEC_ID: IpCmd = IpCmd::new(SeqId::Seq04, 1).unwrap();
- const RESET: IpCmd = IpCmd::new(SeqId::Seq07, 2).unwrap();
+ const READ_READ_PARAMS: IpCmd = IpCmd::new(SeqId::Seq02, 1).unwrap();
const PAGE_SIZE_BYTES: usize = 256;
@@ -109,15 +104,6 @@ pub mod flash {
wait_for_wip_clear(flexspi);
}
- /// Reset the flash chip.
- pub fn reset(flexspi: flexspi::Instance) {
- crate::start_ip_cmd(flexspi, RESET, 0, &[]);
- crate::wait_for_ip_cmd_done(flexspi);
- crate::wait_for_idle(flexspi);
-
- wait_for_wip_clear(flexspi);
- }
-
#[derive(Debug, Clone, Copy, PartialEq, defmt::Format)]
pub struct JedecId {
pub mnf_id: u8,
@@ -141,6 +127,17 @@ pub mod flash {
}
}
+ /// Read the read register parameters.
+ pub fn read_read_params(flexspi: flexspi::Instance) -> u8 {
+ let mut buffer = [0_u8; 1];
+ crate::start_ip_cmd(flexspi, READ_READ_PARAMS, 0, &buffer);
+ crate::receive_bytes(flexspi, &mut buffer);
+ crate::wait_for_ip_cmd_done(flexspi);
+ crate::clear_rx_fifo(flexspi);
+ crate::wait_for_idle(flexspi);
+ buffer[0]
+ }
+
/// Produce chunks of bytes suitable for page aligned writing.
fn aligned_chunks(start: usize, bytes: &[u8], page_size: usize) -> impl Iterator<Item = &[u8]> {
let next_page_start = page_size - (start % page_size);
@@ -199,6 +196,165 @@ pub mod flash {
assert_eq!(chunks.next(), None);
}
}
+
+ /// Supported NOR flash parts.
+ #[derive(Clone, Copy, defmt::Format)]
+ enum FlashKind {
+ /// Issi 1.8V
+ Is25wp,
+ /// Issi 3.3V
+ Is25lp,
+ /// Adesto 3.3V.
+ At25sf,
+ /// Winbond.
+ W25q,
+ }
+
+ const ISSI_MF_ID: u8 = 0x9D;
+ const WINBOND_MF_ID: u8 = 0xEF;
+ const ADESTO_MF_ID: u8 = 0x1F;
+
+ impl FlashKind {
+ fn discover(jedec_id: &JedecId) -> Option<Self> {
+ let flash = match jedec_id.mnf_id {
+ ISSI_MF_ID => Self::discover_issi(jedec_id)?,
+ WINBOND_MF_ID => Self::discover_winbond(jedec_id)?,
+ ADESTO_MF_ID => Self::discover_adesto(jedec_id)?,
+ _ => return None,
+ };
+
+ Some(flash)
+ }
+
+ fn discover_winbond(_: &JedecId) -> Option<FlashKind> {
+ Some(FlashKind::W25q)
+ }
+
+ fn discover_adesto(_: &JedecId) -> Option<FlashKind> {
+ Some(FlashKind::At25sf)
+ }
+
+ fn discover_issi(jedec_id: &JedecId) -> Option<FlashKind> {
+ const ISSI_WP_MEM_TYPE: u8 = 0x70;
+ const ISSI_LP_MEM_TYPE: u8 = 0x60;
+
+ Some(match jedec_id.mem_type {
+ ISSI_WP_MEM_TYPE => FlashKind::Is25wp,
+ ISSI_LP_MEM_TYPE => FlashKind::Is25lp,
+ _ => return None,
+ })
+ }
+ }
+
+ /// Figure the fast read quad I/O dummy cycles, possibly
+ /// querying the part to discover the value.
+ ///
+ /// This function should check against rated speeds, when
+ /// applicable, to make sure you're not going too fast.
+ fn discover_frqio_dummy_cycles(kind: FlashKind, flexspi: flexspi::Instance) -> u8 {
+ match kind {
+ FlashKind::At25sf | FlashKind::W25q => 6,
+ FlashKind::Is25wp => {
+ let read_params = read_read_params(flexspi);
+ let dummy_cycles = (read_params >> 3) & 0b1111;
+ if dummy_cycles == 0 { 6 } else { dummy_cycles }
+ }
+ FlashKind::Is25lp => {
+ // READ_READ_PARAMS not supported.
+ // Guess that the user has set the
+ // default value.
+ 6
+ }
+ }
+ }
+
+ use super::sequences::common as sequences;
+
+ pub fn initialize(
+ flexspi: flexspi::Instance,
+ flash_size_bytes: usize,
+ fifo_capacity_bytes: usize,
+ ) {
+ crate::reset(flexspi, flash_size_bytes / 1024, fifo_capacity_bytes);
+
+ defmt::assert_eq!(
+ READ_ID_JEDEC_ID,
+ defmt::unwrap!(crate::install_ip_cmd(
+ flexspi,
+ READ_ID_JEDEC_ID.seq_id,
+ &[sequences::SEQ_READ_ID_JEDEC_ID]
+ ))
+ );
+ defmt::assert_eq!(
+ READ_READ_PARAMS,
+ defmt::unwrap!(crate::install_ip_cmd(
+ flexspi,
+ READ_READ_PARAMS.seq_id,
+ &[sequences::SEQ_READ_READ_PARAMS]
+ ))
+ );
+
+ let jedec_id = read_jedec_id(flexspi);
+ let flash = defmt::unwrap!(FlashKind::discover(&jedec_id), "{:?}", jedec_id);
+ let dummy_cycles = discover_frqio_dummy_cycles(flash, flexspi);
+
+ defmt::assert_eq!(
+ READ,
+ defmt::unwrap!(crate::install_ip_cmd(
+ flexspi,
+ READ.seq_id,
+ &[sequences::seq_fast_read_quad_io(dummy_cycles)],
+ ))
+ );
+
+ defmt::assert_eq!(
+ WRITE_ENABLE,
+ defmt::unwrap!(crate::install_ip_cmd(
+ flexspi,
+ WRITE_ENABLE.seq_id,
+ &[sequences::SEQ_WRITE_ENABLE]
+ ))
+ );
+
+ defmt::assert_eq!(
+ ERASE_SECTOR,
+ defmt::unwrap!(crate::install_ip_cmd(
+ flexspi,
+ ERASE_SECTOR.seq_id,
+ &[sequences::SEQ_WRITE_ENABLE, sequences::SEQ_ERASE_SECTOR]
+ ))
+ );
+
+ defmt::assert_eq!(
+ READ_STATUS,
+ defmt::unwrap!(crate::install_ip_cmd(
+ flexspi,
+ READ_STATUS.seq_id,
+ &[sequences::SEQ_READ_STATUS]
+ ))
+ );
+
+ defmt::assert_eq!(
+ PAGE_PROGRAM,
+ defmt::unwrap!(crate::install_ip_cmd(
+ flexspi,
+ PAGE_PROGRAM.seq_id,
+ &[
+ sequences::SEQ_WRITE_ENABLE,
+ sequences::SEQ_PAGE_PROGRAM_QUAD_INPUT
+ ]
+ ))
+ );
+
+ defmt::assert_eq!(
+ CHIP_ERASE,
+ defmt::unwrap!(crate::install_ip_cmd(
+ flexspi,
+ CHIP_ERASE.seq_id,
+ &[sequences::SEQ_WRITE_ENABLE, sequences::SEQ_ERASE_CHIP]
+ ))
+ );
+ }
}
pub mod imxrt10xx;
@@ -491,11 +647,3 @@ impl Iterator for FifoReader {
Some(word)
}
}
-
-pub trait ImxrtFlashAlgorithm: 'static {
- const FLASH_CAPACITY_BYTES: usize;
- const FLASH_SECTOR_SIZE_BYTES: usize;
- const FLASH_PAGE_SIZE_BYTES: usize;
-
- fn initialize(flexspi: flexspi::Instance);
-}