embassy_stm32/i2c/
mod.rs

1//! Inter-Integrated-Circuit (I2C)
2#![macro_use]
3
4#[cfg_attr(i2c_v1, path = "v1.rs")]
5#[cfg_attr(any(i2c_v2, i2c_v3), path = "v2.rs")]
6mod _version;
7
8mod config;
9
10use core::future::Future;
11use core::iter;
12use core::marker::PhantomData;
13
14pub use config::*;
15use embassy_hal_internal::Peri;
16use embassy_sync::waitqueue::AtomicWaker;
17#[cfg(feature = "time")]
18use embassy_time::{Duration, Instant};
19use mode::MasterMode;
20pub use mode::{Master, MultiMaster};
21
22use crate::dma::ChannelAndRequest;
23use crate::gpio::{AnyPin, SealedPin as _};
24use crate::interrupt::typelevel::Interrupt;
25use crate::mode::{Async, Blocking, Mode};
26use crate::rcc::{RccInfo, SealedRccPeripheral};
27use crate::time::Hertz;
28use crate::{interrupt, peripherals};
29
30/// I2C error.
31#[derive(Debug, PartialEq, Eq, Copy, Clone)]
32#[cfg_attr(feature = "defmt", derive(defmt::Format))]
33pub enum Error {
34    /// Bus error
35    Bus,
36    /// Arbitration lost
37    Arbitration,
38    /// ACK not received (either to the address or to a data byte)
39    Nack,
40    /// Timeout
41    Timeout,
42    /// CRC error
43    Crc,
44    /// Overrun error
45    Overrun,
46    /// Zero-length transfers are not allowed.
47    ZeroLengthTransfer,
48}
49
50impl core::fmt::Display for Error {
51    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
52        let message = match self {
53            Self::Bus => "Bus Error",
54            Self::Arbitration => "Arbitration Lost",
55            Self::Nack => "ACK Not Received",
56            Self::Timeout => "Request Timed Out",
57            Self::Crc => "CRC Mismatch",
58            Self::Overrun => "Buffer Overrun",
59            Self::ZeroLengthTransfer => "Zero-Length Transfers are not allowed",
60        };
61
62        write!(f, "{}", message)
63    }
64}
65
66impl core::error::Error for Error {}
67
68/// I2C modes
69pub mod mode {
70    trait SealedMode {}
71
72    /// Trait for I2C master operations.
73    #[allow(private_bounds)]
74    pub trait MasterMode: SealedMode {}
75
76    /// Mode allowing for I2C master operations.
77    pub struct Master;
78    /// Mode allowing for I2C master and slave operations.
79    pub struct MultiMaster;
80
81    impl SealedMode for Master {}
82    impl MasterMode for Master {}
83
84    impl SealedMode for MultiMaster {}
85    impl MasterMode for MultiMaster {}
86}
87
88#[derive(Debug, Clone, PartialEq, Eq)]
89#[cfg_attr(feature = "defmt", derive(defmt::Format))]
90/// The command kind to the slave from the master
91pub enum SlaveCommandKind {
92    /// Write to the slave
93    Write,
94    /// Read from the slave
95    Read,
96}
97
98#[derive(Debug, Clone, PartialEq, Eq)]
99#[cfg_attr(feature = "defmt", derive(defmt::Format))]
100/// The command kind to the slave from the master and the address that the slave matched
101pub struct SlaveCommand {
102    /// The kind of command
103    pub kind: SlaveCommandKind,
104    /// The address that the slave matched
105    pub address: Address,
106}
107
108#[derive(Debug, Clone, PartialEq, Eq)]
109#[cfg_attr(feature = "defmt", derive(defmt::Format))]
110/// The status of the slave send operation
111pub enum SendStatus {
112    /// The slave send operation is done, all bytes have been sent and the master is not requesting more
113    Done,
114    /// The slave send operation is done, but there are leftover bytes that the master did not read
115    LeftoverBytes(usize),
116}
117
118struct I2CDropGuard<'d> {
119    info: &'static Info,
120    scl: Option<Peri<'d, AnyPin>>,
121    sda: Option<Peri<'d, AnyPin>>,
122}
123impl<'d> Drop for I2CDropGuard<'d> {
124    fn drop(&mut self) {
125        if let Some(x) = self.scl.as_ref() {
126            x.set_as_disconnected()
127        }
128        if let Some(x) = self.sda.as_ref() {
129            x.set_as_disconnected()
130        }
131
132        self.info.rcc.disable();
133    }
134}
135
136/// I2C driver.
137pub struct I2c<'d, M: Mode, IM: MasterMode> {
138    info: &'static Info,
139    state: &'static State,
140    kernel_clock: Hertz,
141    tx_dma: Option<ChannelAndRequest<'d>>,
142    rx_dma: Option<ChannelAndRequest<'d>>,
143    #[cfg(feature = "time")]
144    timeout: Duration,
145    _phantom: PhantomData<M>,
146    _phantom2: PhantomData<IM>,
147    _drop_guard: I2CDropGuard<'d>,
148}
149
150impl<'d> I2c<'d, Async, Master> {
151    /// Create a new I2C driver.
152    pub fn new<T: Instance>(
153        peri: Peri<'d, T>,
154        scl: Peri<'d, impl SclPin<T>>,
155        sda: Peri<'d, impl SdaPin<T>>,
156        _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>>
157            + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>>
158            + 'd,
159        tx_dma: Peri<'d, impl TxDma<T>>,
160        rx_dma: Peri<'d, impl RxDma<T>>,
161        config: Config,
162    ) -> Self {
163        Self::new_inner(
164            peri,
165            new_pin!(scl, config.scl_af()),
166            new_pin!(sda, config.sda_af()),
167            new_dma!(tx_dma),
168            new_dma!(rx_dma),
169            config,
170        )
171    }
172}
173
174impl<'d> I2c<'d, Blocking, Master> {
175    /// Create a new blocking I2C driver.
176    pub fn new_blocking<T: Instance>(
177        peri: Peri<'d, T>,
178        scl: Peri<'d, impl SclPin<T>>,
179        sda: Peri<'d, impl SdaPin<T>>,
180        config: Config,
181    ) -> Self {
182        Self::new_inner(
183            peri,
184            new_pin!(scl, config.scl_af()),
185            new_pin!(sda, config.sda_af()),
186            None,
187            None,
188            config,
189        )
190    }
191}
192
193impl<'d, M: Mode> I2c<'d, M, Master> {
194    /// Create a new I2C driver.
195    fn new_inner<T: Instance>(
196        _peri: Peri<'d, T>,
197        scl: Option<Peri<'d, AnyPin>>,
198        sda: Option<Peri<'d, AnyPin>>,
199        tx_dma: Option<ChannelAndRequest<'d>>,
200        rx_dma: Option<ChannelAndRequest<'d>>,
201        config: Config,
202    ) -> Self {
203        unsafe { T::EventInterrupt::enable() };
204        unsafe { T::ErrorInterrupt::enable() };
205
206        let mut this = Self {
207            info: T::info(),
208            state: T::state(),
209            kernel_clock: T::frequency(),
210            tx_dma,
211            rx_dma,
212            #[cfg(feature = "time")]
213            timeout: config.timeout,
214            _phantom: PhantomData,
215            _phantom2: PhantomData,
216            _drop_guard: I2CDropGuard {
217                info: T::info(),
218                scl,
219                sda,
220            },
221        };
222        this.enable_and_init(config);
223
224        this
225    }
226
227    fn enable_and_init(&mut self, config: Config) {
228        self.info.rcc.enable_and_reset();
229        self.init(config);
230    }
231}
232
233impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
234    fn timeout(&self) -> Timeout {
235        Timeout {
236            #[cfg(feature = "time")]
237            deadline: Instant::now() + self.timeout,
238        }
239    }
240}
241
242#[derive(Copy, Clone)]
243struct Timeout {
244    #[cfg(feature = "time")]
245    deadline: Instant,
246}
247
248#[allow(dead_code)]
249impl Timeout {
250    #[inline]
251    fn check(self) -> Result<(), Error> {
252        #[cfg(feature = "time")]
253        if Instant::now() > self.deadline {
254            return Err(Error::Timeout);
255        }
256
257        Ok(())
258    }
259
260    #[inline]
261    fn with<R>(self, fut: impl Future<Output = Result<R, Error>>) -> impl Future<Output = Result<R, Error>> {
262        #[cfg(feature = "time")]
263        {
264            use futures_util::FutureExt;
265
266            embassy_futures::select::select(embassy_time::Timer::at(self.deadline), fut).map(|r| match r {
267                embassy_futures::select::Either::First(_) => Err(Error::Timeout),
268                embassy_futures::select::Either::Second(r) => r,
269            })
270        }
271
272        #[cfg(not(feature = "time"))]
273        fut
274    }
275}
276
277struct State {
278    #[allow(unused)]
279    waker: AtomicWaker,
280}
281
282impl State {
283    const fn new() -> Self {
284        Self {
285            waker: AtomicWaker::new(),
286        }
287    }
288}
289
290struct Info {
291    regs: crate::pac::i2c::I2c,
292    rcc: RccInfo,
293}
294
295peri_trait!(
296    irqs: [EventInterrupt, ErrorInterrupt],
297);
298
299pin_trait!(SclPin, Instance);
300pin_trait!(SdaPin, Instance);
301dma_trait!(RxDma, Instance);
302dma_trait!(TxDma, Instance);
303
304/// Event interrupt handler.
305pub struct EventInterruptHandler<T: Instance> {
306    _phantom: PhantomData<T>,
307}
308
309impl<T: Instance> interrupt::typelevel::Handler<T::EventInterrupt> for EventInterruptHandler<T> {
310    unsafe fn on_interrupt() {
311        _version::on_interrupt::<T>()
312    }
313}
314
315/// Error interrupt handler.
316pub struct ErrorInterruptHandler<T: Instance> {
317    _phantom: PhantomData<T>,
318}
319
320impl<T: Instance> interrupt::typelevel::Handler<T::ErrorInterrupt> for ErrorInterruptHandler<T> {
321    unsafe fn on_interrupt() {
322        _version::on_interrupt::<T>()
323    }
324}
325
326foreach_peripheral!(
327    (i2c, $inst:ident) => {
328        #[allow(private_interfaces)]
329        impl SealedInstance for peripherals::$inst {
330            fn info() -> &'static Info {
331                static INFO: Info = Info{
332                    regs: crate::pac::$inst,
333                    rcc: crate::peripherals::$inst::RCC_INFO,
334                };
335                &INFO
336            }
337            fn state() -> &'static State {
338                static STATE: State = State::new();
339                &STATE
340            }
341        }
342
343        impl Instance for peripherals::$inst {
344            type EventInterrupt = crate::_generated::peripheral_interrupts::$inst::EV;
345            type ErrorInterrupt = crate::_generated::peripheral_interrupts::$inst::ER;
346        }
347    };
348);
349
350impl<'d, M: Mode, IM: MasterMode> embedded_hal_02::blocking::i2c::Read for I2c<'d, M, IM> {
351    type Error = Error;
352
353    fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
354        self.blocking_read(address, buffer)
355    }
356}
357
358impl<'d, M: Mode, IM: MasterMode> embedded_hal_02::blocking::i2c::Write for I2c<'d, M, IM> {
359    type Error = Error;
360
361    fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
362        self.blocking_write(address, write)
363    }
364}
365
366impl<'d, M: Mode, IM: MasterMode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M, IM> {
367    type Error = Error;
368
369    fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
370        self.blocking_write_read(address, write, read)
371    }
372}
373
374impl embedded_hal_1::i2c::Error for Error {
375    fn kind(&self) -> embedded_hal_1::i2c::ErrorKind {
376        match *self {
377            Self::Bus => embedded_hal_1::i2c::ErrorKind::Bus,
378            Self::Arbitration => embedded_hal_1::i2c::ErrorKind::ArbitrationLoss,
379            Self::Nack => {
380                embedded_hal_1::i2c::ErrorKind::NoAcknowledge(embedded_hal_1::i2c::NoAcknowledgeSource::Unknown)
381            }
382            Self::Timeout => embedded_hal_1::i2c::ErrorKind::Other,
383            Self::Crc => embedded_hal_1::i2c::ErrorKind::Other,
384            Self::Overrun => embedded_hal_1::i2c::ErrorKind::Overrun,
385            Self::ZeroLengthTransfer => embedded_hal_1::i2c::ErrorKind::Other,
386        }
387    }
388}
389
390impl<'d, M: Mode, IM: MasterMode> embedded_hal_1::i2c::ErrorType for I2c<'d, M, IM> {
391    type Error = Error;
392}
393
394impl<'d, M: Mode, IM: MasterMode> embedded_hal_1::i2c::I2c for I2c<'d, M, IM> {
395    fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
396        self.blocking_read(address, read)
397    }
398
399    fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
400        self.blocking_write(address, write)
401    }
402
403    fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
404        self.blocking_write_read(address, write, read)
405    }
406
407    fn transaction(
408        &mut self,
409        address: u8,
410        operations: &mut [embedded_hal_1::i2c::Operation<'_>],
411    ) -> Result<(), Self::Error> {
412        self.blocking_transaction(address, operations)
413    }
414}
415
416impl<'d, IM: MasterMode> embedded_hal_async::i2c::I2c for I2c<'d, Async, IM> {
417    async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
418        self.read(address, read).await
419    }
420
421    async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
422        self.write(address, write).await
423    }
424
425    async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
426        self.write_read(address, write, read).await
427    }
428
429    async fn transaction(
430        &mut self,
431        address: u8,
432        operations: &mut [embedded_hal_1::i2c::Operation<'_>],
433    ) -> Result<(), Self::Error> {
434        self.transaction(address, operations).await
435    }
436}
437
438/// Frame type in I2C transaction.
439///
440/// This tells each method what kind of framing to use, to generate a (repeated) start condition (ST
441/// or SR), and/or a stop condition (SP). For read operations, this also controls whether to send an
442/// ACK or NACK after the last byte received.
443///
444/// For write operations, the following options are identical because they differ only in the (N)ACK
445/// treatment relevant for read operations:
446///
447/// - `FirstFrame` and `FirstAndNextFrame`
448/// - `NextFrame` and `LastFrameNoStop`
449///
450/// Abbreviations used below:
451///
452/// - `ST` = start condition
453/// - `SR` = repeated start condition
454/// - `SP` = stop condition
455/// - `ACK`/`NACK` = last byte in read operation
456#[derive(Copy, Clone)]
457#[allow(dead_code)]
458enum FrameOptions {
459    /// `[ST/SR]+[NACK]+[SP]` First frame (of this type) in transaction and also last frame overall.
460    FirstAndLastFrame,
461    /// `[ST/SR]+[NACK]` First frame of this type in transaction, last frame in a read operation but
462    /// not the last frame overall.
463    FirstFrame,
464    /// `[ST/SR]+[ACK]` First frame of this type in transaction, neither last frame overall nor last
465    /// frame in a read operation.
466    FirstAndNextFrame,
467    /// `[ACK]` Middle frame in a read operation (neither first nor last).
468    NextFrame,
469    /// `[NACK]+[SP]` Last frame overall in this transaction but not the first frame.
470    LastFrame,
471    /// `[NACK]` Last frame in a read operation but not last frame overall in this transaction.
472    LastFrameNoStop,
473}
474
475#[allow(dead_code)]
476impl FrameOptions {
477    /// Sends start or repeated start condition before transfer.
478    fn send_start(self) -> bool {
479        match self {
480            Self::FirstAndLastFrame | Self::FirstFrame | Self::FirstAndNextFrame => true,
481            Self::NextFrame | Self::LastFrame | Self::LastFrameNoStop => false,
482        }
483    }
484
485    /// Sends stop condition after transfer.
486    fn send_stop(self) -> bool {
487        match self {
488            Self::FirstAndLastFrame | Self::LastFrame => true,
489            Self::FirstFrame | Self::FirstAndNextFrame | Self::NextFrame | Self::LastFrameNoStop => false,
490        }
491    }
492
493    /// Sends NACK after last byte received, indicating end of read operation.
494    fn send_nack(self) -> bool {
495        match self {
496            Self::FirstAndLastFrame | Self::FirstFrame | Self::LastFrame | Self::LastFrameNoStop => true,
497            Self::FirstAndNextFrame | Self::NextFrame => false,
498        }
499    }
500}
501
502/// Iterates over operations in transaction.
503///
504/// Returns necessary frame options for each operation to uphold the [transaction contract] and have
505/// the right start/stop/(N)ACK conditions on the wire.
506///
507/// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
508#[allow(dead_code)]
509fn operation_frames<'a, 'b: 'a>(
510    operations: &'a mut [embedded_hal_1::i2c::Operation<'b>],
511) -> Result<impl IntoIterator<Item = (&'a mut embedded_hal_1::i2c::Operation<'b>, FrameOptions)>, Error> {
512    use embedded_hal_1::i2c::Operation::{Read, Write};
513
514    // Check empty read buffer before starting transaction. Otherwise, we would risk halting with an
515    // error in the middle of the transaction.
516    //
517    // In principle, we could allow empty read frames within consecutive read operations, as long as
518    // at least one byte remains in the final (merged) read operation, but that makes the logic more
519    // complicated and error-prone.
520    if operations.iter().any(|op| match op {
521        Read(read) => read.is_empty(),
522        Write(_) => false,
523    }) {
524        return Err(Error::Overrun);
525    }
526
527    let mut operations = operations.iter_mut().peekable();
528
529    let mut next_first_frame = true;
530
531    Ok(iter::from_fn(move || {
532        let op = operations.next()?;
533
534        // Is `op` first frame of its type?
535        let first_frame = next_first_frame;
536        let next_op = operations.peek();
537
538        // Get appropriate frame options as combination of the following properties:
539        //
540        // - For each first operation of its type, generate a (repeated) start condition.
541        // - For the last operation overall in the entire transaction, generate a stop condition.
542        // - For read operations, check the next operation: if it is also a read operation, we merge
543        //   these and send ACK for all bytes in the current operation; send NACK only for the final
544        //   read operation's last byte (before write or end of entire transaction) to indicate last
545        //   byte read and release the bus for transmission of the bus master's next byte (or stop).
546        //
547        // We check the third property unconditionally, i.e. even for write opeartions. This is okay
548        // because the resulting frame options are identical for write operations.
549        let frame = match (first_frame, next_op) {
550            (true, None) => FrameOptions::FirstAndLastFrame,
551            (true, Some(Read(_))) => FrameOptions::FirstAndNextFrame,
552            (true, Some(Write(_))) => FrameOptions::FirstFrame,
553            //
554            (false, None) => FrameOptions::LastFrame,
555            (false, Some(Read(_))) => FrameOptions::NextFrame,
556            (false, Some(Write(_))) => FrameOptions::LastFrameNoStop,
557        };
558
559        // Pre-calculate if `next_op` is the first operation of its type. We do this here and not at
560        // the beginning of the loop because we hand out `op` as iterator value and cannot access it
561        // anymore in the next iteration.
562        next_first_frame = match (&op, next_op) {
563            (_, None) => false,
564            (Read(_), Some(Write(_))) | (Write(_), Some(Read(_))) => true,
565            (Read(_), Some(Read(_))) | (Write(_), Some(Write(_))) => false,
566        };
567
568        Some((op, frame))
569    }))
570}