1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
|
use core::{marker::PhantomData, num::NonZero};
use imxrt_drivers_ccm_11xx::ral_11xx as ccm;
use imxrt_drivers_flexspi as flexspi;
use imxrt_drivers_gpc_11xx::cpu_mode_ctrl as gpc_cpu;
use imxrt_drivers_pmu_11xx as pmu;
use imxrt_drivers_rtwdog as rtwdog;
const FLEXSPI1_BASE: u32 = 0x3000_0000;
/// Establish the core, bus, and FlexSPI
/// clock frequencies.
fn configure_clocks(
ccm: ccm::Instance,
pll: ccm::pll::Instance,
pmu: pmu::Instance,
gpc_cpu: gpc_cpu::Instance,
) {
// Switch the core to something stable before we
// start changing upstream sources.
ccm::set_clock_root(
ccm,
ccm::ClockRoot::M7,
const { ccm::mux(ccm::ClockRoot::M7, ccm::ClockSource::Xtal) },
NO_DIVIDER,
);
ccm::set_clock_root(
ccm,
ccm::ClockRoot::Bus,
const { ccm::mux(ccm::ClockRoot::Bus, ccm::ClockSource::Xtal) },
NO_DIVIDER,
);
ccm::set_clock_root(
ccm,
ccm::ClockRoot::BusLpsr,
const { ccm::mux(ccm::ClockRoot::BusLpsr, ccm::ClockSource::Xtal) },
NO_DIVIDER,
);
ccm::set_clock_root(
ccm,
ccm::ClockRoot::Flexspi1,
const { ccm::mux(ccm::ClockRoot::Flexspi1, ccm::ClockSource::Xtal) },
NO_DIVIDER,
);
// Prepare PLL power, GPC setpoints.
pmu::enable_pll_reference_voltage(pmu, true);
pmu::set_phy_ldo_setpoints(pmu, u16::MAX);
pmu::enable_phy_ldo_setpoints(pmu);
pmu::enable_pll_reference_setpoints(pmu);
for clock_source in {
use ccm::ClockSource::*;
[
Pll1, Pll1Clk, Pll1Div2, Pll1Div5, ArmPll, ArmPllClk, //
Pll2, Pll2Clk, Pll2Pfd0, Pll2Pfd1, Pll2Pfd2, Pll2Pfd3, //
Pll3, Pll3Clk, Pll3Div2, Pll3Pfd0, Pll3Pfd1, Pll3Pfd2, Pll3Pfd3, //
]
} {
ccm::set_source_setpoints(ccm, clock_source, u16::MAX, 0);
ccm::enable_source_setpoints(ccm, clock_source).unwrap();
}
ccm::pll::enable_sys_pll1_setpoints(pll);
ccm::pll::enable_arm_pll_setpoints(pll, ARM_PLL_POST_DIV, ARM_PLL_DIV_SELECT);
ccm::pll::enable_sys_pll2_setpoints(pll);
ccm::pll::enable_sys_pll3_setpoints(pll);
gpc_cpu::request_setpoint_transition(gpc_cpu, 1).unwrap();
ccm::pll::set_pll3_pfd_fracs(
pll,
[
SYS_PLL3_PFD0_DIV,
SYS_PLL3_PFD1_DIV,
SYS_PLL3_PFD2_DIV,
SYS_PLL3_PFD3_DIV,
],
);
ccm::pll::update_pll3_pfd_fracs(pll, [true, true, true, true]);
ccm::set_clock_root(
ccm,
ccm::ClockRoot::M7,
const { ccm::mux(ccm::ClockRoot::M7, ccm::ClockSource::ArmPll) },
M7_DIVIDER,
);
ccm::set_clock_root(
ccm,
ccm::ClockRoot::Bus,
const { ccm::mux(ccm::ClockRoot::Bus, ccm::ClockSource::Pll1Div5) },
BUS_DIVIDER,
);
ccm::set_clock_root(
ccm,
ccm::ClockRoot::Flexspi1,
const { ccm::mux(ccm::ClockRoot::Flexspi1, ccm::ClockSource::Pll3Pfd0) },
FLEXSPI1_DIVIDER,
);
}
const NO_DIVIDER: NonZero<u8> = NonZero::new(1).unwrap();
const M7_DIVIDER: NonZero<u8> = NO_DIVIDER;
const BUS_DIVIDER: NonZero<u8> = NO_DIVIDER;
const FLEXSPI1_DIVIDER: NonZero<u8> = NonZero::new(2).unwrap();
const ARM_PLL_DIV_SELECT: ccm::pll::ArmPllDivSelect = ccm::pll::ArmPllDivSelect::new(200).unwrap();
const ARM_PLL_POST_DIV: ccm::pll::ArmPllPostDiv = ccm::pll::ArmPllPostDiv::Div4;
const SYS_PLL3_PFD0_DIV: ccm::pll::PfdFrac = ccm::pll::PfdFrac::new(33).unwrap();
const SYS_PLL3_PFD1_DIV: ccm::pll::PfdFrac = ccm::pll::PfdFrac::new(27).unwrap();
const SYS_PLL3_PFD2_DIV: ccm::pll::PfdFrac = ccm::pll::PfdFrac::new(21).unwrap();
const SYS_PLL3_PFD3_DIV: ccm::pll::PfdFrac = ccm::pll::PfdFrac::new(17).unwrap();
pub trait Imxrt11xx: 'static {
const FLEXSPI1_INSTANCE: flexspi::Instance;
const CCM_INSTANCE: ccm::Instance;
const PMU_INSTANCE: pmu::Instance;
const CCM_PLL_INSTANCE: ccm::pll::Instance;
const GPC_CPU_INSTANCE: gpc_cpu::Instance;
const RTWDOG_INSTANCE: rtwdog::Instance;
const FLEXSPI_FIFO_CAPACITY_BYTES: usize;
}
pub struct Algorithm<C: Imxrt11xx, F: crate::ImxrtFlashAlgorithm>(PhantomData<(C, F)>);
impl<C: Imxrt11xx, F: crate::ImxrtFlashAlgorithm> Algorithm<C, F> {
pub const fn flash_size_bytes() -> usize {
F::FLASH_CAPACITY_BYTES
}
pub const fn flash_address() -> usize {
FLEXSPI1_BASE as _
}
pub const fn sector_size_bytes() -> usize {
F::FLASH_SECTOR_SIZE_BYTES
}
pub const fn page_size_bytes() -> usize {
F::FLASH_PAGE_SIZE_BYTES
}
pub fn initialize() -> Self {
rtwdog::disable(C::RTWDOG_INSTANCE);
configure_clocks(
C::CCM_INSTANCE,
C::CCM_PLL_INSTANCE,
C::PMU_INSTANCE,
C::GPC_CPU_INSTANCE,
);
crate::reset(
C::FLEXSPI1_INSTANCE,
F::FLASH_CAPACITY_BYTES / 1024,
C::FLEXSPI_FIFO_CAPACITY_BYTES,
);
F::initialize(C::FLEXSPI1_INSTANCE);
Algorithm(PhantomData)
}
pub fn flash_read(&mut self, address: usize, data: &mut [u8]) {
crate::flash::read(C::FLEXSPI1_INSTANCE, address, data);
}
pub fn flash_erase_sector(&mut self, address: usize) {
crate::flash::erase_sector(C::FLEXSPI1_INSTANCE, address);
}
pub fn flash_write(&mut self, address: usize, data: &[u8]) {
crate::flash::write(C::FLEXSPI1_INSTANCE, address, data);
}
}
impl<C: Imxrt11xx, F: crate::ImxrtFlashAlgorithm> flash_algorithm::FlashAlgorithm
for Algorithm<C, F>
{
fn new(
_: u32,
_: u32,
_: flash_algorithm::Function,
) -> Result<Self, flash_algorithm::ErrorCode> {
Ok(Self::initialize())
}
fn erase_all(&mut self) -> Result<(), flash_algorithm::ErrorCode> {
crate::flash::erase_chip(C::FLEXSPI1_INSTANCE);
Ok(())
}
fn erase_sector(&mut self, address: u32) -> Result<(), flash_algorithm::ErrorCode> {
self.flash_erase_sector(address.saturating_sub(FLEXSPI1_BASE) as usize);
Ok(())
}
fn program_page(
&mut self,
address: u32,
data: &[u8],
) -> Result<(), flash_algorithm::ErrorCode> {
self.flash_write(address.saturating_sub(FLEXSPI1_BASE) as usize, data);
Ok(())
}
fn read_flash(
&mut self,
address: u32,
data: &mut [u8],
) -> Result<(), flash_algorithm::ErrorCode> {
self.flash_read(address.saturating_sub(FLEXSPI1_BASE) as usize, data);
Ok(())
}
}
impl<C: Imxrt11xx, F: crate::ImxrtFlashAlgorithm> Drop for Algorithm<C, F> {
fn drop(&mut self) {
F::deinitialize(C::FLEXSPI1_INSTANCE);
}
}
|