aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan McIntyre <me@mciantyre.dev>2025-12-13 13:30:49 -0500
committerIan McIntyre <me@mciantyre.dev>2025-12-13 13:39:35 -0500
commit7514ffe3b565669f6535ce05826613a884fb0665 (patch)
treee400aab5b130409733b2aac1091321fab3b425d7
parentfe3e7300fe42013705144712843c80d1f198a253 (diff)
Support ISSI LP and WP configs in one algo
The configurations and sequences need to vary depending on the connected part. We can determine the part at runtime to vary the config. We could probably do this for all the parts. Maybe I'll try that later.
-rw-r--r--README.md4
-rw-r--r--imxrt1160evk/src/lib.rs2
-rw-r--r--imxrt1160evk/src/main.rs2
-rw-r--r--imxrt1170evk/src/lib.rs2
-rw-r--r--imxrt1170evk/src/main.rs2
-rw-r--r--src/flash/issi.rs37
-rw-r--r--src/lib.rs24
-rw-r--r--src/sequences/common.rs8
8 files changed, 70 insertions, 11 deletions
diff --git a/README.md b/README.md
index 9962fe3..e52f598 100644
--- a/README.md
+++ b/README.md
@@ -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);
diff --git a/src/lib.rs b/src/lib.rs
index 38ae43e..15e835b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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)
+};