diff options
| -rw-r--r-- | README.md | 4 | ||||
| -rw-r--r-- | imxrt1160evk/src/lib.rs | 2 | ||||
| -rw-r--r-- | imxrt1160evk/src/main.rs | 2 | ||||
| -rw-r--r-- | imxrt1170evk/src/lib.rs | 2 | ||||
| -rw-r--r-- | imxrt1170evk/src/main.rs | 2 | ||||
| -rw-r--r-- | src/flash/issi.rs | 37 | ||||
| -rw-r--r-- | src/lib.rs | 24 | ||||
| -rw-r--r-- | src/sequences/common.rs | 8 |
8 files changed, 70 insertions, 11 deletions
@@ -56,4 +56,8 @@ configuration for your MCU as well as your package. [probe-rs]: https://probe.rs [probe-rs-fork]: https://github.com/mciantyre/probe-rs +Eventually, I might try to define a universal flash programming algorithm, +one that works across different flash parts. But for now, they're separate by +manufacturer. + License: APACHE-2.0 diff --git a/imxrt1160evk/src/lib.rs b/imxrt1160evk/src/lib.rs index 82292dc..5ed3257 100644 --- a/imxrt1160evk/src/lib.rs +++ b/imxrt1160evk/src/lib.rs @@ -2,5 +2,5 @@ use cortex_m as _; -pub use imxrt1160_flash_algos::flash::issi::Is25WP128 as Flash; +pub use imxrt1160_flash_algos::flash::issi::Is25xP128 as Flash; pub type Algorithm = imxrt1160_flash_algos::Algorithm<Flash>; diff --git a/imxrt1160evk/src/main.rs b/imxrt1160evk/src/main.rs index 8c50649..26c6c92 100644 --- a/imxrt1160evk/src/main.rs +++ b/imxrt1160evk/src/main.rs @@ -7,7 +7,7 @@ use panic_probe as _; use imxrt1160evk::Algorithm; flash_algorithm::algorithm!(Algorithm, { - device_name: "imxrt1160_is25wp128_133mhz", + device_name: "imxrt1160_is25xp128_133mhz", device_type: DeviceType::Onchip, flash_address: Algorithm::flash_address() as _, flash_size: Algorithm::flash_size_bytes() as _, diff --git a/imxrt1170evk/src/lib.rs b/imxrt1170evk/src/lib.rs index 5410acd..12da464 100644 --- a/imxrt1170evk/src/lib.rs +++ b/imxrt1170evk/src/lib.rs @@ -2,5 +2,5 @@ use cortex_m as _; -pub use imxrt1170_flash_algos::flash::issi::Is25WP128 as Flash; +pub use imxrt1170_flash_algos::flash::issi::Is25xP128 as Flash; pub type Algorithm = imxrt1170_flash_algos::Algorithm<Flash>; diff --git a/imxrt1170evk/src/main.rs b/imxrt1170evk/src/main.rs index 6b8483b..4d7a55c 100644 --- a/imxrt1170evk/src/main.rs +++ b/imxrt1170evk/src/main.rs @@ -7,7 +7,7 @@ use panic_probe as _; use imxrt1170evk::Algorithm; flash_algorithm::algorithm!(Algorithm, { - device_name: "imxrt1170_is25wp128_133mhz", + device_name: "imxrt1170_is25xp128_133mhz", device_type: DeviceType::Onchip, flash_address: Algorithm::flash_address() as _, flash_size: Algorithm::flash_size_bytes() as _, diff --git a/src/flash/issi.rs b/src/flash/issi.rs index 1d36bb0..6b517af 100644 --- a/src/flash/issi.rs +++ b/src/flash/issi.rs @@ -1,27 +1,50 @@ //! ISSI Serial NOR Flash. +//! +//! The same algorithm will query the flash part to differentiate +//! the 3.3V part ("LP") from the 1.8V part ("WP"). Sequences and +//! configurations vary by part. Replace the W and L with 'x'. use super::*; use crate::{ImxrtFlashAlgorithm, sequences::common as sequences}; -pub type Is25WP128 = Issi<{ 128 / 8 * 1024 * 1024 }, 15>; +pub type Is25xP128 = Issi<{ 128 / 8 * 1024 * 1024 }>; /// An ISSI serial NOR flash driver. -pub struct Issi<const FLASH_CAPACITY_BYTES: usize, const DUMMY_CYCLES: u8>; +pub struct Issi<const FLASH_CAPACITY_BYTES: usize>; -impl<const FLASH_CAPACITY_BYTES: usize, const DUMMY_CYCLES: u8> ImxrtFlashAlgorithm - for Issi<FLASH_CAPACITY_BYTES, DUMMY_CYCLES> -{ +const ISSI_WP_MEM_TYPE: u8 = 0x70; +const ISSI_LP_MEM_TYPE: u8 = 0x60; + +impl<const FLASH_CAPACITY_BYTES: usize> ImxrtFlashAlgorithm for Issi<FLASH_CAPACITY_BYTES> { const FLASH_CAPACITY_BYTES: usize = FLASH_CAPACITY_BYTES; const FLASH_PAGE_SIZE_BYTES: usize = 256; const FLASH_SECTOR_SIZE_BYTES: usize = 4096; fn initialize(flexspi: imxrt_drivers_flexspi::Instance) { 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] + )) + ); + + let jedec_id = super::read_jedec_id(flexspi); + defmt::assert_eq!(jedec_id.mnf_id, 0x9D); + + let (dummy_cycles, set_read_params_data) = match jedec_id.mem_type { + ISSI_WP_MEM_TYPE => (15, 15 << 3), + ISSI_LP_MEM_TYPE => (10, (0b111 << 5) | (0b11) << 3), + _ => defmt::panic!("{=u8:#X}", jedec_id.mem_type), + }; + + defmt::assert_eq!( READ, defmt::unwrap!(crate::install_ip_cmd( flexspi, READ.seq_id, - &[sequences::seq_fast_read_quad_io(DUMMY_CYCLES)], + &[sequences::seq_fast_read_quad_io(dummy_cycles)], )) ); @@ -91,7 +114,7 @@ impl<const FLASH_CAPACITY_BYTES: usize, const DUMMY_CYCLES: u8> ImxrtFlashAlgori )) ); - let set_read_params_data = [DUMMY_CYCLES << 3]; + let set_read_params_data = [set_read_params_data]; crate::start_ip_cmd(flexspi, SET_READ_PARAMS, 0, &set_read_params_data); crate::transmit_bytes(flexspi, &set_read_params_data); crate::wait_for_ip_cmd_done(flexspi); @@ -24,6 +24,7 @@ pub mod flash { 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 PAGE_SIZE_BYTES: usize = 256; @@ -116,6 +117,29 @@ pub mod flash { wait_for_wip_clear(flexspi); } + #[derive(Debug, Clone, Copy, PartialEq, defmt::Format)] + pub struct JedecId { + pub mnf_id: u8, + pub mem_type: u8, + pub cap: u8, + } + + /// Read the JEDEC ID. + pub fn read_jedec_id(flexspi: flexspi::Instance) -> JedecId { + let mut buffer = [0_u8; 3]; + crate::start_ip_cmd(flexspi, READ_ID_JEDEC_ID, 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); + + JedecId { + mnf_id: buffer[0], + mem_type: buffer[1], + cap: buffer[2], + } + } + /// 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); diff --git a/src/sequences/common.rs b/src/sequences/common.rs index cd3d573..4bb9493 100644 --- a/src/sequences/common.rs +++ b/src/sequences/common.rs @@ -80,3 +80,11 @@ pub const SEQ_RST: Sequence = { instr[0] = Instr::new(SDR_CMD, Pads::One, 0x99); Sequence(instr) }; + +/// Read product ID by JEDEC ID. +pub const SEQ_READ_ID_JEDEC_ID: Sequence = { + let mut instr = [Instr::STOP; _]; + instr[0] = Instr::new(SDR_CMD, Pads::One, 0x9F); + instr[1] = Instr::new(SDR_READ, Pads::One, 0); + Sequence(instr) +}; |
