forked from imxrt-rs/imxrt-hal
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathteensy4.rs
249 lines (215 loc) · 7.34 KB
/
teensy4.rs
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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
//! Teensy 4.0 and 4.1 board configuration.
//!
//! Peripheral pins and instances are documented inline.
//!
//! # `"spi"` feature
//!
//! When activated, [`Led`] is the unit type, `()`. The
//! SPI peripheral uses pin 13 as the clock output. When
//! not activated, the SPI peripheral is the unit type `()`.
use crate::{hal, iomuxc::imxrt1060 as iomuxc, ral};
mod imxrt10xx {
pub mod clock;
}
pub use imxrt10xx::clock::*;
#[cfg(not(feature = "spi"))]
/// The board LED.
pub type Led = hal::gpio::Output<iomuxc::gpio_b0::GPIO_B0_03>;
#[cfg(feature = "spi")]
/// LED output repurposed for SPI SCLK.
pub type Led = ();
/// The UART console. Baud specified in lib.rs.
pub type Console = hal::lpuart::Lpuart<ConsolePins, 2>;
pub type ConsolePins = hal::lpuart::Pins<
iomuxc::gpio_ad_b1::GPIO_AD_B1_02, // TX, P14
iomuxc::gpio_ad_b1::GPIO_AD_B1_03, // RX, P15
>;
pub type SpiPins = hal::lpspi::Pins<
iomuxc::gpio_b0::GPIO_B0_02, // SDO, P11
iomuxc::gpio_b0::GPIO_B0_01, // SDI, P12
iomuxc::gpio_b0::GPIO_B0_03, // SCK, P13
iomuxc::gpio_b0::GPIO_B0_00, // PCS0, P10
>;
#[cfg(not(feature = "spi"))]
/// Activate the `"spi"` feature to configure the SPI peripheral.
pub type Spi = ();
#[cfg(feature = "spi")]
/// SPI peripheral.
pub type Spi = hal::lpspi::LpspiMaster<SpiPins, 4>;
pub type I2cPins = hal::lpi2c::Pins<
iomuxc::gpio_ad_b1::GPIO_AD_B1_07, // SCL, P16
iomuxc::gpio_ad_b1::GPIO_AD_B1_06, // SDA, P17
>;
pub type I2c = hal::lpi2c::Lpi2cMaster<I2cPins, 3>;
/// PWM components.
pub mod pwm {
use super::iomuxc;
use crate::hal::flexpwm;
pub type Peripheral = flexpwm::Pwm<2>;
pub type Submodule = flexpwm::Submodule<{ Peripheral::N }, 2>;
pub type Outputs = (
flexpwm::Output<iomuxc::gpio_b0::GPIO_B0_10>, // A, P6
flexpwm::Output<iomuxc::gpio_b0::GPIO_B0_11>, // B, P9
);
}
/// The board's PWM components.
pub struct Pwm {
/// Core PWM peripheral.
pub module: pwm::Peripheral,
/// PWM submodule control registers.
pub submodule: pwm::Submodule,
/// The output pairs (tuple of A, B outputs).
pub outputs: pwm::Outputs,
}
/// Teensy 4 specific peripherals.
pub struct Specifics {
pub led: Led,
pub console: Console,
pub spi: Spi,
pub i2c: I2c,
pub pwm: Pwm,
pub trng: hal::trng::Trng,
}
impl Specifics {
pub(crate) fn new() -> Self {
let iomuxc = unsafe { ral::iomuxc::IOMUXC::instance() };
let mut iomuxc = super::convert_iomuxc(iomuxc);
configure_pins(&mut iomuxc);
let _gpio2 = unsafe { ral::gpio::GPIO2::instance() };
let mut _gpio2 = hal::gpio::Port::new(_gpio2);
#[cfg(not(feature = "spi"))]
let led = _gpio2.output(iomuxc.gpio_b0.p03);
#[cfg(feature = "spi")]
let led = ();
let lpuart2 = unsafe { ral::lpuart::LPUART2::instance() };
let mut console = hal::lpuart::Lpuart::new(
lpuart2,
hal::lpuart::Pins {
tx: iomuxc.gpio_ad_b1.p02,
rx: iomuxc.gpio_ad_b1.p03,
},
);
console.disable(|console| {
console.set_baud(&super::CONSOLE_BAUD);
console.set_parity(None);
});
#[cfg(feature = "spi")]
let spi = {
let lpspi4 = unsafe { ral::lpspi::LPSPI4::instance() };
let pins = SpiPins {
sdo: iomuxc.gpio_b0.p02,
sdi: iomuxc.gpio_b0.p01,
sck: iomuxc.gpio_b0.p03,
pcs0: iomuxc.gpio_b0.p00,
};
let mut spi = Spi::new(lpspi4, pins);
spi.disabled(|spi| {
spi.set_clock_hz(super::LPSPI_CLK_FREQUENCY, super::SPI_BAUD_RATE_FREQUENCY);
});
spi
};
#[cfg(not(feature = "spi"))]
#[allow(clippy::let_unit_value)]
let spi = ();
let lpi2c3 = unsafe { ral::lpi2c::LPI2C3::instance() };
let i2c = I2c::new(
lpi2c3,
I2cPins {
scl: iomuxc.gpio_ad_b1.p07,
sda: iomuxc.gpio_ad_b1.p06,
},
&super::I2C_BAUD_RATE,
);
let flexpwm2 = unsafe { ral::pwm::PWM2::instance() };
let pwm = {
let (pwm, (_, _, sm, _)) = hal::flexpwm::new(flexpwm2);
let out_a = hal::flexpwm::Output::new_a(iomuxc.gpio_b0.p10);
let out_b = hal::flexpwm::Output::new_b(iomuxc.gpio_b0.p11);
Pwm {
module: pwm,
submodule: sm,
outputs: (out_a, out_b),
}
};
let trng = hal::trng::Trng::new(
unsafe { ral::trng::TRNG::instance() },
Default::default(),
Default::default(),
);
Self {
led,
console,
spi,
i2c,
pwm,
trng,
}
}
}
use hal::ccm::clock_gate;
/// The clock gates for this board's peripherals.
pub(crate) const CLOCK_GATES: &[clock_gate::Locator] = &[
clock_gate::gpio::<2>(),
clock_gate::lpuart::<{ Console::N }>(),
#[cfg(feature = "spi")]
clock_gate::lpspi::<{ Spi::N }>(),
clock_gate::lpi2c::<{ I2c::N }>(),
clock_gate::flexpwm::<{ pwm::Peripheral::N }>(),
];
/// Configure board pins.
///
/// Peripherals are responsible for pin muxing, so there's no need to
/// set alternates here.
fn configure_pins(
super::Pads {
ref mut gpio_ad_b1, ..
}: &mut super::Pads,
) {
use crate::iomuxc;
const I2C_PIN_CONFIG: iomuxc::Config = iomuxc::Config::zero()
.set_open_drain(iomuxc::OpenDrain::Enabled)
.set_slew_rate(iomuxc::SlewRate::Fast)
.set_drive_strength(iomuxc::DriveStrength::R0_4)
.set_speed(iomuxc::Speed::Fast)
.set_pull_keeper(Some(iomuxc::PullKeeper::Pullup22k));
iomuxc::configure(&mut gpio_ad_b1.p07, I2C_PIN_CONFIG);
iomuxc::configure(&mut gpio_ad_b1.p06, I2C_PIN_CONFIG);
}
#[cfg(target_arch = "arm")]
use teensy4_fcb as _;
#[cfg(target_arch = "arm")]
use teensy4_panic as _;
/// Helpers for the clock_out example.
///
/// The Teensy 4 does not have these outputs, so the configuration enables
/// no functionality.
pub mod clock_out {
use crate::hal::ccm::output_source::{clko1::Selection as Clko1, clko2::Selection as Clko2};
pub const CLKO1_SELECTIONS: [Clko1; 0] = [];
pub const CLKO2_SELECTIONS: [Clko2; 0] = [];
}
pub mod interrupt {
use crate::board_interrupts as syms;
use crate::ral::Interrupt;
pub const BOARD_CONSOLE: Interrupt = Interrupt::LPUART2;
pub const BOARD_SPI: Interrupt = Interrupt::LPSPI4;
pub const BOARD_PWM: Interrupt = Interrupt::PWM2_2;
pub const BOARD_DMA_A: Interrupt = Interrupt::DMA7_DMA23;
pub const BOARD_PIT: Interrupt = Interrupt::PIT;
pub const BOARD_GPT1: Interrupt = Interrupt::GPT1;
pub const BOARD_GPT2: Interrupt = Interrupt::GPT2;
pub const BOARD_USB1: Interrupt = Interrupt::USB_OTG1;
pub const BOARD_SWTASK0: Interrupt = Interrupt::KPP;
pub const INTERRUPTS: &[(Interrupt, syms::Vector)] = &[
(BOARD_CONSOLE, syms::BOARD_CONSOLE),
(BOARD_SPI, syms::BOARD_SPI),
(BOARD_PWM, syms::BOARD_PWM),
(BOARD_DMA_A, syms::BOARD_DMA_A),
(BOARD_PIT, syms::BOARD_PIT),
(BOARD_GPT1, syms::BOARD_GPT1),
(BOARD_GPT2, syms::BOARD_GPT2),
(BOARD_USB1, syms::BOARD_USB1),
(BOARD_SWTASK0, syms::BOARD_SWTASK0),
];
}
pub use interrupt as Interrupt;