aboutsummaryrefslogtreecommitdiff
path: root/embassy-mcxa/src/i2c/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-mcxa/src/i2c/mod.rs')
-rw-r--r--embassy-mcxa/src/i2c/mod.rs194
1 files changed, 194 insertions, 0 deletions
diff --git a/embassy-mcxa/src/i2c/mod.rs b/embassy-mcxa/src/i2c/mod.rs
new file mode 100644
index 000000000..9a014224a
--- /dev/null
+++ b/embassy-mcxa/src/i2c/mod.rs
@@ -0,0 +1,194 @@
1//! I2C Support
2
3use core::marker::PhantomData;
4
5use embassy_hal_internal::PeripheralType;
6use maitake_sync::WaitCell;
7use paste::paste;
8
9use crate::clocks::periph_helpers::Lpi2cConfig;
10use crate::clocks::{ClockError, Gate};
11use crate::gpio::{GpioPin, SealedPin};
12use crate::{interrupt, pac};
13
14/// Shorthand for `Result<T>`.
15pub type Result<T> = core::result::Result<T, Error>;
16
17pub mod controller;
18
19/// Error information type
20#[derive(Debug, Copy, Clone, PartialEq, Eq)]
21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
22pub enum Error {
23 /// Clock configuration error.
24 ClockSetup(ClockError),
25 /// FIFO Error
26 FifoError,
27 /// Reading for I2C failed.
28 ReadFail,
29 /// Writing to I2C failed.
30 WriteFail,
31 /// I2C address NAK condition.
32 AddressNack,
33 /// Bus level arbitration loss.
34 ArbitrationLoss,
35 /// Address out of range.
36 AddressOutOfRange(u8),
37 /// Invalid write buffer length.
38 InvalidWriteBufferLength,
39 /// Invalid read buffer length.
40 InvalidReadBufferLength,
41 /// Other internal errors or unexpected state.
42 Other,
43}
44
45/// I2C interrupt handler.
46pub struct InterruptHandler<T: Instance> {
47 _phantom: PhantomData<T>,
48}
49
50impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
51 unsafe fn on_interrupt() {
52 if T::regs().mier().read().bits() != 0 {
53 T::regs().mier().write(|w| {
54 w.tdie()
55 .disabled()
56 .rdie()
57 .disabled()
58 .epie()
59 .disabled()
60 .sdie()
61 .disabled()
62 .ndie()
63 .disabled()
64 .alie()
65 .disabled()
66 .feie()
67 .disabled()
68 .pltie()
69 .disabled()
70 .dmie()
71 .disabled()
72 .stie()
73 .disabled()
74 });
75
76 T::wait_cell().wake();
77 }
78 }
79}
80
81mod sealed {
82 /// Seal a trait
83 pub trait Sealed {}
84}
85
86impl<T: GpioPin> sealed::Sealed for T {}
87
88trait SealedInstance {
89 fn regs() -> &'static pac::lpi2c0::RegisterBlock;
90 fn wait_cell() -> &'static WaitCell;
91}
92
93/// I2C Instance
94#[allow(private_bounds)]
95pub trait Instance: SealedInstance + PeripheralType + 'static + Send + Gate<MrccPeriphConfig = Lpi2cConfig> {
96 /// Interrupt for this I2C instance.
97 type Interrupt: interrupt::typelevel::Interrupt;
98 /// Clock instance
99 const CLOCK_INSTANCE: crate::clocks::periph_helpers::Lpi2cInstance;
100}
101
102macro_rules! impl_instance {
103 ($($n:expr),*) => {
104 $(
105 paste!{
106 impl SealedInstance for crate::peripherals::[<LPI2C $n>] {
107 fn regs() -> &'static pac::lpi2c0::RegisterBlock {
108 unsafe { &*pac::[<Lpi2c $n>]::ptr() }
109 }
110
111 fn wait_cell() -> &'static WaitCell {
112 static WAIT_CELL: WaitCell = WaitCell::new();
113 &WAIT_CELL
114 }
115 }
116
117 impl Instance for crate::peripherals::[<LPI2C $n>] {
118 type Interrupt = crate::interrupt::typelevel::[<LPI2C $n>];
119 const CLOCK_INSTANCE: crate::clocks::periph_helpers::Lpi2cInstance
120 = crate::clocks::periph_helpers::Lpi2cInstance::[<Lpi2c $n>];
121 }
122 }
123 )*
124 };
125}
126
127impl_instance!(0, 1, 2, 3);
128
129/// SCL pin trait.
130pub trait SclPin<Instance>: GpioPin + sealed::Sealed + PeripheralType {
131 fn mux(&self);
132}
133
134/// SDA pin trait.
135pub trait SdaPin<Instance>: GpioPin + sealed::Sealed + PeripheralType {
136 fn mux(&self);
137}
138
139/// Driver mode.
140#[allow(private_bounds)]
141pub trait Mode: sealed::Sealed {}
142
143/// Blocking mode.
144pub struct Blocking;
145impl sealed::Sealed for Blocking {}
146impl Mode for Blocking {}
147
148/// Async mode.
149pub struct Async;
150impl sealed::Sealed for Async {}
151impl Mode for Async {}
152
153macro_rules! impl_pin {
154 ($pin:ident, $peri:ident, $fn:ident, $trait:ident) => {
155 impl $trait<crate::peripherals::$peri> for crate::peripherals::$pin {
156 fn mux(&self) {
157 self.set_pull(crate::gpio::Pull::Disabled);
158 self.set_slew_rate(crate::gpio::SlewRate::Fast.into());
159 self.set_drive_strength(crate::gpio::DriveStrength::Double.into());
160 self.set_function(crate::pac::port0::pcr0::Mux::$fn);
161 self.set_enable_input_buffer();
162 }
163 }
164 };
165}
166
167impl_pin!(P0_16, LPI2C0, Mux2, SdaPin);
168impl_pin!(P0_17, LPI2C0, Mux2, SclPin);
169impl_pin!(P0_18, LPI2C0, Mux2, SclPin);
170impl_pin!(P0_19, LPI2C0, Mux2, SdaPin);
171impl_pin!(P1_0, LPI2C1, Mux3, SdaPin);
172impl_pin!(P1_1, LPI2C1, Mux3, SclPin);
173impl_pin!(P1_2, LPI2C1, Mux3, SdaPin);
174impl_pin!(P1_3, LPI2C1, Mux3, SclPin);
175impl_pin!(P1_8, LPI2C2, Mux3, SdaPin);
176impl_pin!(P1_9, LPI2C2, Mux3, SclPin);
177impl_pin!(P1_10, LPI2C2, Mux3, SdaPin);
178impl_pin!(P1_11, LPI2C2, Mux3, SclPin);
179impl_pin!(P1_12, LPI2C1, Mux2, SdaPin);
180impl_pin!(P1_13, LPI2C1, Mux2, SclPin);
181impl_pin!(P1_14, LPI2C1, Mux2, SclPin);
182impl_pin!(P1_15, LPI2C1, Mux2, SdaPin);
183impl_pin!(P1_30, LPI2C0, Mux3, SdaPin);
184impl_pin!(P1_31, LPI2C0, Mux3, SclPin);
185impl_pin!(P3_27, LPI2C3, Mux2, SclPin);
186impl_pin!(P3_28, LPI2C3, Mux2, SdaPin);
187// impl_pin!(P3_29, LPI2C3, Mux2, HreqPin); What is this HREQ pin?
188impl_pin!(P3_30, LPI2C3, Mux2, SclPin);
189impl_pin!(P3_31, LPI2C3, Mux2, SdaPin);
190impl_pin!(P4_2, LPI2C2, Mux2, SdaPin);
191impl_pin!(P4_3, LPI2C0, Mux2, SclPin);
192impl_pin!(P4_4, LPI2C2, Mux2, SdaPin);
193impl_pin!(P4_5, LPI2C0, Mux2, SclPin);
194// impl_pin!(P4_6, LPI2C0, Mux2, HreqPin); What is this HREQ pin?