teensy4_fcb/
lib.rs

1//! FlexSPI Configuration Block (FCB) for the Teensy 4
2//!
3//! See the [`imxrt-boot-gen`] crate to learn how this was generated.
4//!
5//! # Usage
6//!
7//! Add `teensy4-fcb` to your dependencies:
8//!
9//! ```toml
10//! [dependencies]
11//! teensy4-fcb = "0.4"
12//! ```
13//!
14//! Properly place the FCB in your program's memory. See the `FLEXSPI_CONFIGURATION_BLOCK`
15//! declaration below, or the [`imxrt-boot-gen`] documentation, for more information on
16//! how you could refer to the FCB.
17//!
18//! Make sure that you reference this crate somewhere in your program!
19//! Otherwise, it might get removed from the output. Either use
20//!
21//! ```
22//! use teensy4_fcb as _;
23//! ```
24//! or
25//! ```
26//! extern crate teensy4_fcb;
27//! ```
28//!
29//! to reference the FCB in either your library or binary.
30//!
31//! [`imxrt-boot-gen`]: https://docs.rs/imxrt-boot-gen/latest/imxrt_boot_gen/
32
33#![no_std]
34
35use imxrt_boot_gen::flexspi::{self, opcodes::sdr::*, *};
36use imxrt_boot_gen::serial_flash::*;
37
38pub use nor::ConfigurationBlock;
39
40/// Instructions for the Winbond W25Q16JV
41/// SPI flash memory controller
42mod winbond {
43    pub const FAST_READ_QUAD_IO: u8 = 0xEB;
44    pub const READ_STATUS_REGISTER_1: u8 = 0x05;
45    pub const WRITE_ENABLE: u8 = 0x06;
46    pub const SECTOR_ERASE: u8 = 0x20;
47    pub const PAGE_PROGRAM: u8 = 0x02;
48    pub const CHIP_ERASE: u8 = 0x60;
49}
50
51use winbond::*;
52
53//
54// Sequences for lookup table
55//
56
57const SEQ_READ: Sequence = SequenceBuilder::new()
58    .instr(Instr::new(CMD, Pads::One, FAST_READ_QUAD_IO))
59    .instr(Instr::new(RADDR, Pads::Four, 0x18))
60    .instr(Instr::new(DUMMY, Pads::Four, 0x06))
61    .instr(Instr::new(READ, Pads::Four, 0x04))
62    .build();
63
64const SEQ_READ_STATUS: Sequence = SequenceBuilder::new()
65    .instr(Instr::new(CMD, Pads::One, READ_STATUS_REGISTER_1))
66    .instr(Instr::new(READ, Pads::One, 0x04))
67    .build();
68
69const SEQ_WRITE_ENABLE: Sequence = SequenceBuilder::new()
70    .instr(Instr::new(CMD, Pads::One, WRITE_ENABLE))
71    .build();
72
73const SEQ_ERASE_SECTOR: Sequence = SequenceBuilder::new()
74    .instr(Instr::new(CMD, Pads::One, SECTOR_ERASE))
75    .instr(Instr::new(RADDR, Pads::One, 0x18))
76    .build();
77
78const SEQ_PAGE_PROGRAM: Sequence = SequenceBuilder::new()
79    .instr(Instr::new(CMD, Pads::One, PAGE_PROGRAM))
80    .instr(Instr::new(RADDR, Pads::One, 0x18))
81    .instr(Instr::new(WRITE, Pads::One, 0x04))
82    .build();
83
84const SEQ_CHIP_ERASE: Sequence = SequenceBuilder::new()
85    .instr(Instr::new(CMD, Pads::One, CHIP_ERASE))
86    .build();
87
88//
89// Lookup table
90//
91
92const LUT: LookupTable = LookupTable::new()
93    .command(Command::Read, SEQ_READ)
94    .command(Command::ReadStatus, SEQ_READ_STATUS)
95    .command(Command::WriteEnable, SEQ_WRITE_ENABLE)
96    .command(Command::EraseSector, SEQ_ERASE_SECTOR)
97    .command(Command::PageProgram, SEQ_PAGE_PROGRAM)
98    .command(Command::ChipErase, SEQ_CHIP_ERASE);
99
100//
101// Common FlexSPI configuration block
102//
103
104const COMMON_CONFIGURATION_BLOCK: flexspi::ConfigurationBlock =
105    flexspi::ConfigurationBlock::new(LUT)
106        .read_sample_clk_src(ReadSampleClockSource::LoopbackFromDQSPad)
107        .cs_hold_time(0x01)
108        .cs_setup_time(0x02)
109        .column_address_width(ColumnAddressWidth::OtherDevices)
110        .device_mode_configuration(DeviceModeConfiguration::Disabled)
111        .wait_time_cfg_commands(WaitTimeConfigurationCommands::disable())
112        .flash_size(SerialFlashRegion::A1, 0x0020_0000)
113        .serial_clk_freq(SerialClockFrequency::MHz60)
114        .serial_flash_pad_type(FlashPadType::Quad);
115
116//
117// Final serial NOR configuration block
118//
119
120/// Value for the serial NOR FlexSPI configuration block.
121///
122/// Use this constant if you need to create a new static variable with a different name
123/// or link section.
124pub const SERIAL_NOR_CONFIGURATION_BLOCK: nor::ConfigurationBlock =
125    nor::ConfigurationBlock::new(COMMON_CONFIGURATION_BLOCK)
126        .page_size(256)
127        .sector_size(4096)
128        .ip_cmd_serial_clk_freq(nor::SerialClockFrequency::MHz30);
129
130/// The FlexSPI configuration block.
131///
132/// The name is intentionally unmangled. You may precisely place this structure to boot
133/// your Teensy 4.
134#[no_mangle]
135#[cfg_attr(all(target_arch = "arm", target_os = "none"), link_section = ".fcb")]
136pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK;