1#![no_std]
6
7pub use nor::ConfigurationBlock;
8
9use imxrt_boot_gen::Imxrt;
10use imxrt_boot_gen::flexspi::{self, opcodes::sdr::*, *};
11use imxrt_boot_gen::flexspi::{FlashPadType, ReadSampleClockSource, SerialFlashRegion};
12use imxrt_boot_gen::serial_flash::*;
13
14const CHIP: Imxrt = Imxrt::Imxrt1180;
15
16const SEQ_READ: Sequence = SequenceBuilder::new()
17 .instr(Instr::new(CMD, Pads::One, 0xEB))
18 .instr(Instr::new(RADDR, Pads::Four, 0x18))
19 .instr(Instr::new(DUMMY, Pads::Four, 0x06))
20 .instr(Instr::new(READ, Pads::Four, 0x04))
21 .build();
22const SEQ_READ_STATUS: Sequence = SequenceBuilder::new()
23 .instr(Instr::new(CMD, Pads::One, 0x05))
24 .instr(Instr::new(READ, Pads::One, 0x04))
25 .build();
26const SEQ_WRITE_ENABLE: Sequence = SequenceBuilder::new()
27 .instr(Instr::new(CMD, Pads::One, 0x06))
28 .build();
29const SEQ_ERASE_SECTOR: Sequence = SequenceBuilder::new()
30 .instr(Instr::new(CMD, Pads::One, 0x20))
31 .instr(Instr::new(RADDR, Pads::One, 0x18))
32 .build();
33const SEQ_PAGE_PROGRAM: Sequence = SequenceBuilder::new()
34 .instr(Instr::new(CMD, Pads::One, 0x02))
35 .instr(Instr::new(RADDR, Pads::One, 0x18))
36 .instr(Instr::new(WRITE, Pads::One, 0x04))
37 .build();
38const SEQ_CHIP_ERASE: Sequence = SequenceBuilder::new()
39 .instr(Instr::new(CMD, Pads::One, 0x60))
40 .build();
41
42const LUT: LookupTable = LookupTable::new()
43 .command(Command::Read, SEQ_READ)
44 .command(Command::ReadStatus, SEQ_READ_STATUS)
45 .command(Command::WriteEnable, SEQ_WRITE_ENABLE)
46 .command(Command::EraseSector, SEQ_ERASE_SECTOR)
47 .command(Command::PageProgram, SEQ_PAGE_PROGRAM)
48 .command(Command::ChipErase, SEQ_CHIP_ERASE);
49
50const COMMON_CONFIGURATION_BLOCK: flexspi::ConfigurationBlock =
51 flexspi::ConfigurationBlock::new(LUT)
52 .version(Version::new(1, 4, 0))
53 .read_sample_clk_src(ReadSampleClockSource::LoopbackFromDQSPad)
54 .cs_hold_time(3)
55 .cs_setup_time(3)
56 .controller_misc_options(0x10)
57 .serial_flash_pad_type(FlashPadType::Quad)
58 .serial_clk_freq(CHIP.serial_clock_frequency(SerialClockOption::MHz133))
59 .flash_size(SerialFlashRegion::A1, 16 * 1024 * 1024);
60
61pub const SERIAL_NOR_CONFIGURATION_BLOCK: nor::ConfigurationBlock = {
62 let mut cb = nor::ConfigurationBlock::new(CHIP, COMMON_CONFIGURATION_BLOCK)
63 .page_size(256)
64 .sector_size(4 * 1024)
65 .ip_cmd_serial_clk_freq(Some(
66 CHIP.ip_serial_clock_frequency(SerialClockOption::MHz30),
67 ));
68 cb.extras(CHIP).unwrap().block_size(64 * 1024);
69 cb
70};
71
72#[unsafe(no_mangle)]
73#[cfg_attr(
74 all(target_arch = "arm", target_os = "none"),
75 unsafe(link_section = ".fcb")
76)]
77pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK;
78
79#[cfg(test)]
80mod tests {
81 use super::SERIAL_NOR_CONFIGURATION_BLOCK;
82
83 const EXPECTED: [u32; 128] = [
90 0x46434642, 0x00040156, 0x00000000, 0x01030300, 0x00000000, 0x00000000, 0x00000000,
91 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
92 0x00000000, 0x00000000, 0x10000000, 0x01040700, 0x00000000, 0x00000000, 0x00000001,
93 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
94 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xeb04180a, 0x06320426, 0x00000000,
95 0x00000000, 0x05040424, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
96 0x00000000, 0x00000000, 0x06040000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
97 0x00000000, 0x00000000, 0x00000000, 0x20041808, 0x00000000, 0x00000000, 0x00000000,
98 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
99 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02041808, 0x04200000,
100 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x60040000,
101 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
102 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
103 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
104 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
105 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
106 0x00010000, 0x00100000, 0x01000000, 0x00000000, 0x00000100, 0x00000000, 0x00000000,
107 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
108 0x00000000, 0x00000000,
109 ];
110
111 #[test]
112 fn imxrt1180evk() {
113 let actual: [u32; 128] = unsafe { core::mem::transmute(SERIAL_NOR_CONFIGURATION_BLOCK) };
114 for (i, (a, e)) in actual.iter().zip(EXPECTED).enumerate() {
115 let offset = i * 4;
116 assert_eq!(
117 a.to_be_bytes(),
118 e.to_le_bytes(),
119 "Offset {offset:#X}\nACTUAL: {actual:?}\nEXPECTED: {EXPECTED:?}"
120 );
121 }
122 }
123}