1#![macro_use]
3
4mod v1;
9
10use core::future::Future;
11use core::iter;
12use core::marker::PhantomData;
13
14use embassy_hal_internal::{Peripheral, PeripheralRef};
15use embassy_sync::waitqueue::AtomicWaker;
16#[cfg(feature = "time")]
17use embassy_time::{Duration, Instant};
18
19#[cfg(dma)]
20use crate::dma::ChannelAndRequest;
21use crate::gpio::{AfType, AnyPin, OutputType, SealedPin as _, Speed};
22use crate::interrupt::typelevel::Interrupt;
23use crate::mode::{Async, Blocking, Mode};
24use crate::rcc::{RccInfo, SealedRccPeripheral};
25use crate::time::Hertz;
26use crate::{interrupt, peripherals};
27
28#[derive(Debug, PartialEq, Eq, Copy, Clone)]
30#[cfg_attr(feature = "defmt", derive(defmt::Format))]
31pub enum Error {
32 Bus,
34 Arbitration,
36 Nack,
38 Timeout,
40 Crc,
42 Overrun,
44 ZeroLengthTransfer,
46}
47
48#[non_exhaustive]
50#[derive(Copy, Clone)]
51pub struct Config {
52 #[cfg(feature = "time")]
64 pub timeout: embassy_time::Duration,
65}
66
67impl Default for Config {
68 fn default() -> Self {
69 Self {
70 #[cfg(feature = "time")]
73 timeout: embassy_time::Duration::from_millis(1000),
74 }
75 }
76}
77
78impl Config {
79 fn scl_af(&self) -> AfType {
80 return AfType::output(OutputType::OpenDrain, Speed::Medium);
81 }
90
91 fn sda_af(&self) -> AfType {
92 return AfType::output(OutputType::OpenDrain, Speed::Medium);
93 }
102}
103
104pub struct I2c<'d, M: Mode> {
106 info: &'static Info,
107 #[allow(dead_code)]
108 state: &'static State,
109 kernel_clock: Hertz,
110 scl: Option<PeripheralRef<'d, AnyPin>>,
111 sda: Option<PeripheralRef<'d, AnyPin>>,
112 #[cfg(dma)] tx_dma: Option<ChannelAndRequest<'d>>,
113 #[cfg(dma)] rx_dma: Option<ChannelAndRequest<'d>>,
114 #[cfg(feature = "time")]
115 timeout: Duration,
116 _phantom: PhantomData<M>,
117}
118
119impl<'d> I2c<'d, Async> {
120 pub fn new<T: Instance>(
122 peri: impl Peripheral<P = T> + 'd,
123 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
124 sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
125 _irq: impl interrupt::typelevel::Binding<T::GlobalInterrupt, GlobalInterruptHandler<T>> + 'd,
126 #[cfg(dma)] tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
127 #[cfg(dma)] rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
128 freq: Hertz,
129 config: Config,
130 ) -> Self {
131 Self::new_inner(
132 peri,
133 new_pin!(scl, config.scl_af()),
134 new_pin!(sda, config.sda_af()),
135 #[cfg(dma)] new_dma!(tx_dma),
136 #[cfg(dma)] new_dma!(rx_dma),
137 freq,
138 config,
139 )
140 }
141}
142
143impl<'d> I2c<'d, Blocking> {
144 pub fn new_blocking<T: Instance>(
146 peri: impl Peripheral<P = T> + 'd,
147 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
148 sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
149 freq: Hertz,
150 config: Config,
151 ) -> Self {
152 Self::new_inner(
153 peri,
154 new_pin!(scl, config.scl_af()),
155 new_pin!(sda, config.sda_af()),
156 #[cfg(dma)] None,
157 #[cfg(dma)] None,
158 freq,
159 config,
160 )
161 }
162}
163
164impl<'d, M: Mode> I2c<'d, M> {
165 fn new_inner<T: Instance>(
167 _peri: impl Peripheral<P = T> + 'd,
168 scl: Option<PeripheralRef<'d, AnyPin>>,
169 sda: Option<PeripheralRef<'d, AnyPin>>,
170 #[cfg(dma)] tx_dma: Option<ChannelAndRequest<'d>>,
171 #[cfg(dma)] rx_dma: Option<ChannelAndRequest<'d>>,
172 freq: Hertz,
173 config: Config,
174 ) -> Self {
175 unsafe { T::GlobalInterrupt::enable() };
176
177 let mut this = Self {
178 info: T::info(),
179 state: T::state(),
180 kernel_clock: T::frequency(),
181 scl,
182 sda,
183 #[cfg(dma)] tx_dma,
184 #[cfg(dma)] rx_dma,
185 #[cfg(feature = "time")]
186 timeout: config.timeout,
187 _phantom: PhantomData,
188 };
189 this.enable_and_init(freq, config);
190 this
191 }
192
193 fn enable_and_init(&mut self, freq: Hertz, config: Config) {
194 self.info.rcc.enable_and_reset();
195 self.init(freq, config);
196 }
197
198 fn timeout(&self) -> Timeout {
199 Timeout {
200 #[cfg(feature = "time")]
201 deadline: Instant::now() + self.timeout,
202 }
203 }
204}
205
206impl<'d, M: Mode> Drop for I2c<'d, M> {
207 fn drop(&mut self) {
208 self.scl.as_ref().map(|x| x.set_as_disconnected());
209 self.sda.as_ref().map(|x| x.set_as_disconnected());
210
211 self.info.rcc.disable()
212 }
213}
214
215#[derive(Copy, Clone)]
216struct Timeout {
217 #[cfg(feature = "time")]
218 deadline: Instant,
219}
220
221#[allow(dead_code)]
222impl Timeout {
223 #[inline]
224 fn check(self) -> Result<(), Error> {
225 #[cfg(feature = "time")]
226 if Instant::now() > self.deadline {
227 return Err(Error::Timeout);
228 }
229
230 Ok(())
231 }
232
233 #[inline]
234 fn with<R>(
235 self,
236 fut: impl Future<Output = Result<R, Error>>,
237 ) -> impl Future<Output = Result<R, Error>> {
238 #[cfg(feature = "time")]
239 {
240 use futures_util::FutureExt;
241
242 embassy_futures::select::select(embassy_time::Timer::at(self.deadline), fut).map(|r| {
243 match r {
244 embassy_futures::select::Either::First(_) => Err(Error::Timeout),
245 embassy_futures::select::Either::Second(r) => r,
246 }
247 })
248 }
249
250 #[cfg(not(feature = "time"))]
251 fut
252 }
253}
254
255struct State {
256 #[allow(unused)]
257 waker: AtomicWaker,
258}
259
260impl State {
261 const fn new() -> Self {
262 Self {
263 waker: AtomicWaker::new(),
264 }
265 }
266}
267
268struct Info {
269 regs: crate::pac::i2c::I2c,
270 rcc: RccInfo,
271}
272
273peri_trait!(
274 irqs: [GlobalInterrupt],
275);
276
277pin_trait!(SclPin, Instance);
278pin_trait!(SdaPin, Instance);
279#[cfg(dma)] dma_trait!(RxDma, Instance);
280#[cfg(dma)] dma_trait!(TxDma, Instance);
281
282pub struct GlobalInterruptHandler<T: Instance> {
284 _phantom: PhantomData<T>,
285}
286
287impl<T: Instance> interrupt::typelevel::Handler<T::GlobalInterrupt> for GlobalInterruptHandler<T> {
288 unsafe fn on_interrupt() {
289 v1::on_interrupt::<T>()
290 }
291}
292
293foreach_peripheral!(
294 (i2c, $inst:ident) => {
295 #[allow(private_interfaces)]
296 impl SealedInstance for peripherals::$inst {
297 fn info() -> &'static Info {
298 static INFO: Info = Info{
299 regs: crate::pac::$inst,
300 rcc: crate::peripherals::$inst::RCC_INFO,
301 };
302 &INFO
303 }
304 fn state() -> &'static State {
305 static STATE: State = State::new();
306 &STATE
307 }
308 }
309
310 impl Instance for peripherals::$inst {
311 type GlobalInterrupt = crate::_generated::peripheral_interrupts::$inst::GLOBAL;
312 }
313 };
314);
315
316impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, M> {
317 type Error = Error;
318
319 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
320 self.blocking_read(address, buffer)
321 }
322}
323
324impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, M> {
325 type Error = Error;
326
327 fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
328 self.blocking_write(address, write)
329 }
330}
331
332impl<'d, M: Mode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M> {
333 type Error = Error;
334
335 fn write_read(
336 &mut self,
337 address: u8,
338 write: &[u8],
339 read: &mut [u8],
340 ) -> Result<(), Self::Error> {
341 self.blocking_write_read(address, write, read)
342 }
343}
344
345impl embedded_hal_1::i2c::Error for Error {
346 fn kind(&self) -> embedded_hal_1::i2c::ErrorKind {
347 match *self {
348 Self::Bus => embedded_hal_1::i2c::ErrorKind::Bus,
349 Self::Arbitration => embedded_hal_1::i2c::ErrorKind::ArbitrationLoss,
350 Self::Nack => embedded_hal_1::i2c::ErrorKind::NoAcknowledge(
351 embedded_hal_1::i2c::NoAcknowledgeSource::Unknown,
352 ),
353 Self::Timeout => embedded_hal_1::i2c::ErrorKind::Other,
354 Self::Crc => embedded_hal_1::i2c::ErrorKind::Other,
355 Self::Overrun => embedded_hal_1::i2c::ErrorKind::Overrun,
356 Self::ZeroLengthTransfer => embedded_hal_1::i2c::ErrorKind::Other,
357 }
358 }
359}
360
361impl<'d, M: Mode> embedded_hal_1::i2c::ErrorType for I2c<'d, M> {
362 type Error = Error;
363}
364
365impl<'d, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, M> {
366 fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
367 self.blocking_read(address, read)
368 }
369
370 fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
371 self.blocking_write(address, write)
372 }
373
374 fn write_read(
375 &mut self,
376 address: u8,
377 write: &[u8],
378 read: &mut [u8],
379 ) -> Result<(), Self::Error> {
380 self.blocking_write_read(address, write, read)
381 }
382
383 fn transaction(
384 &mut self,
385 address: u8,
386 operations: &mut [embedded_hal_1::i2c::Operation<'_>],
387 ) -> Result<(), Self::Error> {
388 self.blocking_transaction(address, operations)
389 }
390}
391
392#[cfg(dma)]
393impl<'d> embedded_hal_async::i2c::I2c for I2c<'d, Async> {
394 async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
395 self.read(address, read).await
396 }
397
398 async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
399 self.write(address, write).await
400 }
401
402 async fn write_read(
403 &mut self,
404 address: u8,
405 write: &[u8],
406 read: &mut [u8],
407 ) -> Result<(), Self::Error> {
408 self.write_read(address, write, read).await
409 }
410
411 async fn transaction(
412 &mut self,
413 address: u8,
414 operations: &mut [embedded_hal_1::i2c::Operation<'_>],
415 ) -> Result<(), Self::Error> {
416 self.transaction(address, operations).await
417 }
418}
419
420#[derive(Copy, Clone)]
439#[allow(dead_code)]
440enum FrameOptions {
441 FirstAndLastFrame,
443 FirstFrame,
446 FirstAndNextFrame,
449 NextFrame,
451 LastFrame,
453 LastFrameNoStop,
455}
456
457#[allow(dead_code)]
458impl FrameOptions {
459 fn send_start(self) -> bool {
461 match self {
462 Self::FirstAndLastFrame | Self::FirstFrame | Self::FirstAndNextFrame => true,
463 Self::NextFrame | Self::LastFrame | Self::LastFrameNoStop => false,
464 }
465 }
466
467 fn send_stop(self) -> bool {
469 match self {
470 Self::FirstAndLastFrame | Self::LastFrame => true,
471 Self::FirstFrame
472 | Self::FirstAndNextFrame
473 | Self::NextFrame
474 | Self::LastFrameNoStop => false,
475 }
476 }
477
478 fn send_nack(self) -> bool {
480 match self {
481 Self::FirstAndLastFrame
482 | Self::FirstFrame
483 | Self::LastFrame
484 | Self::LastFrameNoStop => true,
485 Self::FirstAndNextFrame | Self::NextFrame => false,
486 }
487 }
488}
489
490#[allow(dead_code)]
497fn operation_frames<'a, 'b: 'a>(
498 operations: &'a mut [embedded_hal_1::i2c::Operation<'b>],
499) -> Result<
500 impl IntoIterator<Item = (&'a mut embedded_hal_1::i2c::Operation<'b>, FrameOptions)>,
501 Error,
502> {
503 use embedded_hal_1::i2c::Operation::{Read, Write};
504
505 if operations.iter().any(|op| match op {
512 Read(read) => read.is_empty(),
513 Write(_) => false,
514 }) {
515 return Err(Error::Overrun);
516 }
517
518 let mut operations = operations.iter_mut().peekable();
519
520 let mut next_first_frame = true;
521
522 Ok(iter::from_fn(move || {
523 let Some(op) = operations.next() else {
524 return None;
525 };
526
527 let first_frame = next_first_frame;
529 let next_op = operations.peek();
530
531 let frame = match (first_frame, next_op) {
543 (true, None) => FrameOptions::FirstAndLastFrame,
544 (true, Some(Read(_))) => FrameOptions::FirstAndNextFrame,
545 (true, Some(Write(_))) => FrameOptions::FirstFrame,
546 (false, None) => FrameOptions::LastFrame,
548 (false, Some(Read(_))) => FrameOptions::NextFrame,
549 (false, Some(Write(_))) => FrameOptions::LastFrameNoStop,
550 };
551
552 next_first_frame = match (&op, next_op) {
556 (_, None) => false,
557 (Read(_), Some(Write(_))) | (Write(_), Some(Read(_))) => true,
558 (Read(_), Some(Read(_))) | (Write(_), Some(Write(_))) => false,
559 };
560
561 Some((op, frame))
562 }))
563}