diff options
Diffstat (limited to 'src/lib.rs')
| -rw-r--r-- | src/lib.rs | 194 |
1 files changed, 171 insertions, 23 deletions
@@ -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); -} |
