esp_hal/i2c/master/
mod.rs

1//! # Inter-Integrated Circuit (I2C) - Master mode
2//!
3//! ## Overview
4//!
5//! In this mode, the I2C acts as master and initiates the I2C communication by
6//! generating a START condition. Note that only one master is allowed to occupy
7//! the bus to access one slave at the same time.
8//!
9//! ## Configuration
10//!
11//! Each I2C Master controller is individually configurable, and the usual
12//! setting such as frequency, timeout, and SDA/SCL pins can easily be
13//! configured.
14//!
15//! ## Usage
16//!
17//! The I2C driver implements a number of third-party traits, with the
18//! intention of making the HAL inter-compatible with various device drivers
19//! from the community, including the [embedded-hal].
20//!
21//! [embedded-hal]: embedded_hal
22
23use core::{
24    marker::PhantomData,
25    pin::Pin,
26    task::{Context, Poll},
27};
28
29use embedded_hal::i2c::Operation as EhalOperation;
30use enumset::{EnumSet, EnumSetType};
31
32use crate::{
33    Async,
34    Blocking,
35    DriverMode,
36    asynch::AtomicWaker,
37    clock::Clocks,
38    gpio::{
39        DriveMode,
40        InputSignal,
41        OutputConfig,
42        OutputSignal,
43        PinGuard,
44        Pull,
45        interconnect::{self, PeripheralOutput},
46    },
47    i2c::{AnyI2c, AnyI2cInner},
48    interrupt::InterruptHandler,
49    pac::i2c0::{COMD, RegisterBlock},
50    peripherals::Interrupt,
51    private,
52    system::PeripheralGuard,
53    time::{Duration, Instant, Rate},
54};
55
56const I2C_LL_INTR_MASK: u32 = if cfg!(esp32s2) { 0x1ffff } else { 0x3ffff };
57const I2C_FIFO_SIZE: usize = if cfg!(esp32c2) { 16 } else { 32 };
58
59// Chunk writes/reads by this size
60const I2C_CHUNK_SIZE: usize = I2C_FIFO_SIZE - 1;
61const CLEAR_BUS_TIMEOUT_MS: Duration = Duration::from_millis(50);
62
63/// Representation of I2C address.
64#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
65#[cfg_attr(feature = "defmt", derive(defmt::Format))]
66#[non_exhaustive]
67pub enum I2cAddress {
68    /// 7-bit address mode type.
69    ///
70    /// Note that 7-bit addresses are specified in **right-aligned** form, e.g.
71    /// in the range `0x00..=0x7F`.
72    ///
73    /// For example, a device that has the seven bit address of `0b011_0010`,
74    /// and therefore is addressed on the wire using:
75    ///
76    /// * `0b0110010_0` or `0x64` for *writes*
77    /// * `0b0110010_1` or `0x65` for *reads*
78    ///
79    /// The above address is specified as 0b0011_0010 or 0x32, NOT 0x64 or 0x65.
80    SevenBit(u8),
81}
82
83impl I2cAddress {
84    fn validate(&self) -> Result<(), Error> {
85        match self {
86            I2cAddress::SevenBit(addr) => {
87                if *addr > 0x7F {
88                    return Err(Error::AddressInvalid(*self));
89                }
90            }
91        }
92
93        Ok(())
94    }
95}
96
97impl From<u8> for I2cAddress {
98    fn from(value: u8) -> Self {
99        I2cAddress::SevenBit(value)
100    }
101}
102
103/// I2C SCL timeout period.
104///
105/// When the level of SCL remains unchanged for more than `timeout` bus
106/// clock cycles, the bus goes to idle state.
107///
108/// Default value is `BusCycles(10)`.
109#[doc = ""]
110#[cfg_attr(
111    not(esp32),
112    doc = "Note that the effective timeout may be longer than the value configured here."
113)]
114#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, strum::Display)]
115#[cfg_attr(feature = "defmt", derive(defmt::Format))]
116#[non_exhaustive]
117// TODO: when supporting interrupts, document that SCL = high also triggers an
118// interrupt.
119pub enum BusTimeout {
120    /// Use the maximum timeout value.
121    Maximum,
122
123    /// Disable timeout control.
124    #[cfg(not(any(esp32, esp32s2)))]
125    Disabled,
126
127    /// Timeout in bus clock cycles.
128    BusCycles(u32),
129}
130
131impl BusTimeout {
132    fn cycles(&self) -> u32 {
133        match self {
134            BusTimeout::Maximum => {
135                if cfg!(esp32) {
136                    0xF_FFFF
137                } else if cfg!(esp32s2) {
138                    0xFF_FFFF
139                } else {
140                    0x1F
141                }
142            }
143
144            #[cfg(not(any(esp32, esp32s2)))]
145            BusTimeout::Disabled => 1,
146
147            BusTimeout::BusCycles(cycles) => *cycles,
148        }
149    }
150
151    #[cfg(not(esp32))]
152    fn is_set(&self) -> bool {
153        matches!(self, BusTimeout::BusCycles(_) | BusTimeout::Maximum)
154    }
155}
156
157/// Software timeout for I2C operations.
158///
159/// This timeout is used to limit the duration of I2C operations in software.
160/// Note that using this in conjunction with `async` operations will cause the
161/// task to be woken up continuously until the operation completes or the
162/// timeout is reached. You should prefer using an asynchronous
163/// timeout mechanism (like [`embassy_time::with_timeout`]) for better
164/// efficiency.
165///
166/// [`embassy_time::with_timeout`]: https://docs.rs/embassy-time/0.4.0/embassy_time/fn.with_timeout.html
167#[instability::unstable]
168#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
169#[cfg_attr(feature = "defmt", derive(defmt::Format))]
170pub enum SoftwareTimeout {
171    /// No software timeout is set.
172    None,
173
174    /// Define a fixed timeout for I2C operations.
175    Transaction(Duration),
176
177    /// Define a data length dependent timeout for I2C operations.
178    ///
179    /// The applied timeout is calculated as `data_length * duration_per_byte`.
180    /// In [`I2c::transaction`] and [`I2c::transaction_async`], the timeout is
181    /// applied separately for each operation.
182    PerByte(Duration),
183}
184
185/// When the FSM remains unchanged for more than the 2^ the given amount of bus
186/// clock cycles a timeout will be triggered.
187///
188/// The default value is 0x10
189#[instability::unstable]
190#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
191#[cfg_attr(feature = "defmt", derive(defmt::Format))]
192#[cfg(not(any(esp32, esp32s2)))]
193pub struct FsmTimeout {
194    value: u8,
195}
196
197#[cfg(not(any(esp32, esp32s2)))]
198impl FsmTimeout {
199    const FSM_TIMEOUT_MAX: u8 = 23;
200
201    const FSM_TIMEOUT_DEFAULT: u8 = 0x10;
202
203    /// Creates a new timeout.
204    ///
205    /// The meaning of the value and the allowed range of values is different
206    /// for different chips.
207    #[instability::unstable]
208    pub const fn new_const<const VALUE: u8>() -> Self {
209        const {
210            core::assert!(VALUE <= Self::FSM_TIMEOUT_MAX, "Invalid timeout value");
211        }
212        Self { value: VALUE }
213    }
214
215    /// Creates a new timeout.
216    ///
217    /// The meaning of the value and the allowed range of values is different
218    /// for different chips.
219    #[instability::unstable]
220    pub fn new(value: u8) -> Result<Self, ConfigError> {
221        if value > Self::FSM_TIMEOUT_MAX {
222            return Err(ConfigError::TimeoutInvalid);
223        }
224
225        Ok(Self { value })
226    }
227
228    fn value(&self) -> u8 {
229        self.value
230    }
231}
232
233#[cfg(not(any(esp32, esp32s2)))]
234impl Default for FsmTimeout {
235    fn default() -> Self {
236        Self::new_const::<{ Self::FSM_TIMEOUT_DEFAULT }>()
237    }
238}
239
240/// I2C-specific transmission errors
241#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
242#[cfg_attr(feature = "defmt", derive(defmt::Format))]
243#[non_exhaustive]
244pub enum Error {
245    /// The transmission exceeded the FIFO size.
246    FifoExceeded,
247    /// The acknowledgment check failed.
248    AcknowledgeCheckFailed(AcknowledgeCheckFailedReason),
249    /// A timeout occurred during transmission.
250    Timeout,
251    /// The arbitration for the bus was lost.
252    ArbitrationLost,
253    /// The execution of the I2C command was incomplete.
254    ExecutionIncomplete,
255    /// The number of commands issued exceeded the limit.
256    CommandNumberExceeded,
257    /// Zero length read or write operation.
258    ZeroLengthInvalid,
259    /// The given address is invalid.
260    AddressInvalid(I2cAddress),
261}
262
263/// I2C no acknowledge error reason.
264///
265/// Consider this as a hint and make sure to always handle all cases.
266#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
267#[cfg_attr(feature = "defmt", derive(defmt::Format))]
268#[non_exhaustive]
269pub enum AcknowledgeCheckFailedReason {
270    /// The device did not acknowledge its address. The device may be missing.
271    Address,
272
273    /// The device did not acknowledge the data. It may not be ready to process
274    /// requests at the moment.
275    Data,
276
277    /// Either the device did not acknowledge its address or the data, but it is
278    /// unknown which.
279    Unknown,
280}
281
282impl core::fmt::Display for AcknowledgeCheckFailedReason {
283    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
284        match self {
285            AcknowledgeCheckFailedReason::Address => write!(f, "Address"),
286            AcknowledgeCheckFailedReason::Data => write!(f, "Data"),
287            AcknowledgeCheckFailedReason::Unknown => write!(f, "Unknown"),
288        }
289    }
290}
291
292impl From<&AcknowledgeCheckFailedReason> for embedded_hal::i2c::NoAcknowledgeSource {
293    fn from(value: &AcknowledgeCheckFailedReason) -> Self {
294        match value {
295            AcknowledgeCheckFailedReason::Address => {
296                embedded_hal::i2c::NoAcknowledgeSource::Address
297            }
298            AcknowledgeCheckFailedReason::Data => embedded_hal::i2c::NoAcknowledgeSource::Data,
299            AcknowledgeCheckFailedReason::Unknown => {
300                embedded_hal::i2c::NoAcknowledgeSource::Unknown
301            }
302        }
303    }
304}
305
306impl core::error::Error for Error {}
307
308impl core::fmt::Display for Error {
309    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
310        match self {
311            Error::FifoExceeded => write!(f, "The transmission exceeded the FIFO size"),
312            Error::AcknowledgeCheckFailed(reason) => {
313                write!(f, "The acknowledgment check failed. Reason: {reason}")
314            }
315            Error::Timeout => write!(f, "A timeout occurred during transmission"),
316            Error::ArbitrationLost => write!(f, "The arbitration for the bus was lost"),
317            Error::ExecutionIncomplete => {
318                write!(f, "The execution of the I2C command was incomplete")
319            }
320            Error::CommandNumberExceeded => {
321                write!(f, "The number of commands issued exceeded the limit")
322            }
323            Error::ZeroLengthInvalid => write!(f, "Zero length read or write operation"),
324            Error::AddressInvalid(address) => {
325                write!(f, "The given address ({address:?}) is invalid")
326            }
327        }
328    }
329}
330
331/// I2C-specific configuration errors
332#[derive(Debug, Clone, Copy, PartialEq)]
333#[cfg_attr(feature = "defmt", derive(defmt::Format))]
334#[non_exhaustive]
335pub enum ConfigError {
336    /// Provided bus frequency is invalid for the current configuration.
337    FrequencyInvalid,
338    /// Provided timeout is invalid for the current configuration.
339    TimeoutInvalid,
340}
341
342impl core::error::Error for ConfigError {}
343
344impl core::fmt::Display for ConfigError {
345    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
346        match self {
347            ConfigError::FrequencyInvalid => write!(
348                f,
349                "Provided bus frequency is invalid for the current configuration"
350            ),
351            ConfigError::TimeoutInvalid => write!(
352                f,
353                "Provided timeout is invalid for the current configuration"
354            ),
355        }
356    }
357}
358
359// This enum is used to keep track of the last/next operation that was/will be
360// performed in an embedded-hal(-async) I2c::transaction. It is used to
361// determine whether a START condition should be issued at the start of the
362// current operation and whether a read needs an ack or a nack for the final
363// byte.
364#[derive(PartialEq)]
365enum OpKind {
366    Write,
367    Read,
368}
369
370/// I2C operation.
371///
372/// Several operations can be combined as part of a transaction.
373#[derive(Debug, PartialEq, Eq, Hash, strum::Display)]
374#[cfg_attr(feature = "defmt", derive(defmt::Format))]
375pub enum Operation<'a> {
376    /// Write data from the provided buffer.
377    Write(&'a [u8]),
378
379    /// Read data into the provided buffer.
380    Read(&'a mut [u8]),
381}
382
383impl<'a, 'b> From<&'a mut embedded_hal::i2c::Operation<'b>> for Operation<'a> {
384    fn from(value: &'a mut embedded_hal::i2c::Operation<'b>) -> Self {
385        match value {
386            embedded_hal::i2c::Operation::Write(buffer) => Operation::Write(buffer),
387            embedded_hal::i2c::Operation::Read(buffer) => Operation::Read(buffer),
388        }
389    }
390}
391
392impl<'a, 'b> From<&'a mut Operation<'b>> for Operation<'a> {
393    fn from(value: &'a mut Operation<'b>) -> Self {
394        match value {
395            Operation::Write(buffer) => Operation::Write(buffer),
396            Operation::Read(buffer) => Operation::Read(buffer),
397        }
398    }
399}
400
401impl Operation<'_> {
402    fn is_write(&self) -> bool {
403        matches!(self, Operation::Write(_))
404    }
405
406    fn kind(&self) -> OpKind {
407        match self {
408            Operation::Write(_) => OpKind::Write,
409            Operation::Read(_) => OpKind::Read,
410        }
411    }
412
413    fn is_empty(&self) -> bool {
414        match self {
415            Operation::Write(buffer) => buffer.is_empty(),
416            Operation::Read(buffer) => buffer.is_empty(),
417        }
418    }
419}
420
421impl embedded_hal::i2c::Error for Error {
422    fn kind(&self) -> embedded_hal::i2c::ErrorKind {
423        use embedded_hal::i2c::ErrorKind;
424
425        match self {
426            Self::FifoExceeded => ErrorKind::Overrun,
427            Self::ArbitrationLost => ErrorKind::ArbitrationLoss,
428            Self::AcknowledgeCheckFailed(reason) => ErrorKind::NoAcknowledge(reason.into()),
429            _ => ErrorKind::Other,
430        }
431    }
432}
433
434/// A generic I2C Command
435#[derive(Debug)]
436enum Command {
437    Start,
438    Stop,
439    End,
440    Write {
441        /// This bit is to set an expected ACK value for the transmitter.
442        ack_exp: Ack,
443        /// Enables checking the ACK value received against the ack_exp value.
444        ack_check_en: bool,
445        /// Length of data (in bytes) to be written. The maximum length is
446        #[cfg_attr(esp32c2, doc = "16")]
447        #[cfg_attr(not(esp32c2), doc = "32")]
448        /// , while the minimum is 1.
449        length: u8,
450    },
451    Read {
452        /// Indicates whether the receiver will send an ACK after this byte has
453        /// been received.
454        ack_value: Ack,
455        /// Length of data (in bytes) to be written. The maximum length is
456        #[cfg_attr(esp32c2, doc = "16")]
457        #[cfg_attr(not(esp32c2), doc = "32")]
458        /// , while the minimum is 1.
459        length: u8,
460    },
461}
462
463enum OperationType {
464    Write = 0,
465    Read  = 1,
466}
467
468#[derive(Eq, PartialEq, Copy, Clone, Debug)]
469enum Ack {
470    Ack  = 0,
471    Nack = 1,
472}
473
474impl From<u32> for Ack {
475    fn from(ack: u32) -> Self {
476        match ack {
477            0 => Ack::Ack,
478            1 => Ack::Nack,
479            _ => unreachable!(),
480        }
481    }
482}
483
484impl From<Ack> for u32 {
485    fn from(ack: Ack) -> u32 {
486        ack as u32
487    }
488}
489
490/// I2C driver configuration
491#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, procmacros::BuilderLite)]
492#[cfg_attr(feature = "defmt", derive(defmt::Format))]
493#[non_exhaustive]
494pub struct Config {
495    /// The I2C clock frequency.
496    frequency: Rate,
497
498    /// I2C SCL timeout period.
499    timeout: BusTimeout,
500
501    /// Software timeout.
502    #[builder_lite(unstable)]
503    software_timeout: SoftwareTimeout,
504
505    /// Sets the threshold value for the unchanged period of the SCL_FSM.
506    #[cfg(not(any(esp32, esp32s2)))]
507    #[builder_lite(unstable)]
508    scl_st_timeout: FsmTimeout,
509
510    /// Sets the threshold for the unchanged duration of the SCL_MAIN_FSM.
511    #[cfg(not(any(esp32, esp32s2)))]
512    #[builder_lite(unstable)]
513    scl_main_st_timeout: FsmTimeout,
514}
515
516impl Default for Config {
517    fn default() -> Self {
518        Config {
519            frequency: Rate::from_khz(100),
520            timeout: BusTimeout::BusCycles(10),
521            software_timeout: SoftwareTimeout::PerByte(Duration::from_millis(1)),
522            #[cfg(not(any(esp32, esp32s2)))]
523            scl_st_timeout: Default::default(),
524            #[cfg(not(any(esp32, esp32s2)))]
525            scl_main_st_timeout: Default::default(),
526        }
527    }
528}
529
530/// I2C driver
531///
532/// ### I2C initialization and communication with the device
533/// ```rust, no_run
534#[doc = crate::before_snippet!()]
535/// # use esp_hal::i2c::master::{Config, I2c};
536/// # const DEVICE_ADDR: u8 = 0x77;
537/// let mut i2c = I2c::new(
538///     peripherals.I2C0,
539///     Config::default(),
540/// )?
541/// .with_sda(peripherals.GPIO1)
542/// .with_scl(peripherals.GPIO2);
543///
544/// let mut data = [0u8; 22];
545/// i2c.write_read(DEVICE_ADDR, &[0xaa], &mut data)?;
546/// # Ok(())
547/// # }
548/// ```
549#[derive(Debug)]
550#[cfg_attr(feature = "defmt", derive(defmt::Format))]
551pub struct I2c<'d, Dm: DriverMode> {
552    i2c: AnyI2c<'d>,
553    phantom: PhantomData<Dm>,
554    guard: PeripheralGuard,
555    config: DriverConfig,
556}
557
558#[derive(Debug)]
559#[cfg_attr(feature = "defmt", derive(defmt::Format))]
560struct DriverConfig {
561    config: Config,
562    sda_pin: PinGuard,
563    scl_pin: PinGuard,
564}
565
566#[instability::unstable]
567impl<Dm: DriverMode> embassy_embedded_hal::SetConfig for I2c<'_, Dm> {
568    type Config = Config;
569    type ConfigError = ConfigError;
570
571    fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
572        self.apply_config(config)
573    }
574}
575
576impl<Dm: DriverMode> embedded_hal::i2c::ErrorType for I2c<'_, Dm> {
577    type Error = Error;
578}
579
580impl<Dm: DriverMode> embedded_hal::i2c::I2c for I2c<'_, Dm> {
581    fn transaction(
582        &mut self,
583        address: u8,
584        operations: &mut [embedded_hal::i2c::Operation<'_>],
585    ) -> Result<(), Self::Error> {
586        self.driver()
587            .transaction_impl(
588                I2cAddress::SevenBit(address),
589                operations.iter_mut().map(Operation::from),
590            )
591            .inspect_err(|_| self.internal_recover())
592    }
593}
594
595impl<'d> I2c<'d, Blocking> {
596    /// Create a new I2C instance.
597    ///
598    /// # Errors
599    ///
600    /// A [`ConfigError`] variant will be returned if bus frequency or timeout
601    /// passed in config is invalid.
602    pub fn new(i2c: impl Instance + 'd, config: Config) -> Result<Self, ConfigError> {
603        let guard = PeripheralGuard::new(i2c.info().peripheral);
604
605        let sda_pin = PinGuard::new_unconnected(i2c.info().sda_output);
606        let scl_pin = PinGuard::new_unconnected(i2c.info().scl_output);
607
608        let mut i2c = I2c {
609            i2c: i2c.degrade(),
610            phantom: PhantomData,
611            guard,
612            config: DriverConfig {
613                config,
614                sda_pin,
615                scl_pin,
616            },
617        };
618
619        i2c.apply_config(&config)?;
620
621        Ok(i2c)
622    }
623
624    /// Configures the I2C peripheral to operate in asynchronous mode.
625    pub fn into_async(mut self) -> I2c<'d, Async> {
626        self.set_interrupt_handler(self.driver().info.async_handler);
627
628        I2c {
629            i2c: self.i2c,
630            phantom: PhantomData,
631            guard: self.guard,
632            config: self.config,
633        }
634    }
635
636    #[cfg_attr(
637        not(multi_core),
638        doc = "Registers an interrupt handler for the peripheral."
639    )]
640    #[cfg_attr(
641        multi_core,
642        doc = "Registers an interrupt handler for the peripheral on the current core."
643    )]
644    #[doc = ""]
645    /// Note that this will replace any previously registered interrupt
646    /// handlers.
647    ///
648    /// You can restore the default/unhandled interrupt handler by using
649    /// [crate::DEFAULT_INTERRUPT_HANDLER]
650    ///
651    /// # Panics
652    ///
653    /// Panics if passed interrupt handler is invalid (e.g. has priority
654    /// `None`)
655    #[instability::unstable]
656    pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
657        self.i2c.info().set_interrupt_handler(handler);
658    }
659
660    /// Listen for the given interrupts
661    #[instability::unstable]
662    pub fn listen(&mut self, interrupts: impl Into<EnumSet<Event>>) {
663        self.i2c.info().enable_listen(interrupts.into(), true)
664    }
665
666    /// Unlisten the given interrupts
667    #[instability::unstable]
668    pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<Event>>) {
669        self.i2c.info().enable_listen(interrupts.into(), false)
670    }
671
672    /// Gets asserted interrupts
673    #[instability::unstable]
674    pub fn interrupts(&mut self) -> EnumSet<Event> {
675        self.i2c.info().interrupts()
676    }
677
678    /// Resets asserted interrupts
679    #[instability::unstable]
680    pub fn clear_interrupts(&mut self, interrupts: EnumSet<Event>) {
681        self.i2c.info().clear_interrupts(interrupts)
682    }
683}
684
685impl private::Sealed for I2c<'_, Blocking> {}
686
687#[instability::unstable]
688impl crate::interrupt::InterruptConfigurable for I2c<'_, Blocking> {
689    fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
690        self.i2c.info().set_interrupt_handler(handler);
691    }
692}
693
694#[cfg_attr(esp32, allow(dead_code))]
695#[derive(Debug, EnumSetType)]
696#[cfg_attr(feature = "defmt", derive(defmt::Format))]
697#[non_exhaustive]
698#[instability::unstable]
699pub enum Event {
700    /// Triggered when op_code of the master indicates an END command and an END
701    /// condition is detected.
702    EndDetect,
703
704    /// Triggered when the I2C controller detects a STOP bit.
705    TxComplete,
706
707    /// Triggered when the TX FIFO watermark check is enabled and the TX fifo
708    /// falls below the configured watermark.
709    #[cfg(not(any(esp32, esp32s2)))]
710    TxFifoWatermark,
711}
712
713#[must_use = "futures do nothing unless you `.await` or poll them"]
714struct I2cFuture<'a> {
715    events: EnumSet<Event>,
716    driver: Driver<'a>,
717    deadline: Option<Instant>,
718    finished: bool,
719}
720
721impl<'a> I2cFuture<'a> {
722    pub fn new(events: EnumSet<Event>, driver: Driver<'a>, deadline: Option<Instant>) -> Self {
723        driver.regs().int_ena().modify(|_, w| {
724            for event in events {
725                match event {
726                    Event::EndDetect => w.end_detect().set_bit(),
727                    Event::TxComplete => w.trans_complete().set_bit(),
728                    #[cfg(not(any(esp32, esp32s2)))]
729                    Event::TxFifoWatermark => w.txfifo_wm().set_bit(),
730                };
731            }
732
733            w.arbitration_lost().set_bit();
734            w.time_out().set_bit();
735            w.nack().set_bit();
736            #[cfg(not(any(esp32, esp32s2)))]
737            {
738                w.scl_main_st_to().set_bit();
739                w.scl_st_to().set_bit();
740            }
741
742            w
743        });
744
745        Self::new_blocking(events, driver, deadline)
746    }
747
748    pub fn new_blocking(
749        events: EnumSet<Event>,
750        driver: Driver<'a>,
751        deadline: Option<Instant>,
752    ) -> Self {
753        Self {
754            events,
755            driver,
756            deadline,
757            finished: false,
758        }
759    }
760
761    fn is_done(&self) -> bool {
762        !self.driver.info.interrupts().is_disjoint(self.events)
763    }
764
765    fn poll_completion(&mut self) -> Poll<Result<(), Error>> {
766        let error = self.driver.check_errors();
767
768        let now = if self.deadline.is_some() {
769            Instant::now()
770        } else {
771            Instant::EPOCH
772        };
773
774        if self.is_done() {
775            self.finished = true;
776            // Even though we are done, we have to check for NACK and arbitration loss.
777            let result = if error == Err(Error::Timeout) {
778                Ok(())
779            } else {
780                error
781            };
782            Poll::Ready(result)
783        } else if error.is_err() {
784            self.finished = true;
785            Poll::Ready(error)
786        } else {
787            if let Some(deadline) = self.deadline {
788                if now > deadline {
789                    // If the deadline is reached, we return an error.
790                    return Poll::Ready(Err(Error::Timeout));
791                }
792            }
793
794            Poll::Pending
795        }
796    }
797}
798
799impl core::future::Future for I2cFuture<'_> {
800    type Output = Result<(), Error>;
801
802    fn poll(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
803        self.driver.state.waker.register(ctx.waker());
804
805        let result = self.poll_completion();
806
807        if result.is_pending() && self.deadline.is_some() {
808            ctx.waker().wake_by_ref();
809        }
810
811        result
812    }
813}
814
815impl Drop for I2cFuture<'_> {
816    fn drop(&mut self) {
817        if !self.finished {
818            self.driver.reset_fsm();
819            self.driver.clear_bus_blocking();
820        }
821    }
822}
823
824impl<'d> I2c<'d, Async> {
825    /// Configure the I2C peripheral to operate in blocking mode.
826    pub fn into_blocking(self) -> I2c<'d, Blocking> {
827        self.i2c.info().disable_interrupts();
828
829        I2c {
830            i2c: self.i2c,
831            phantom: PhantomData,
832            guard: self.guard,
833            config: self.config,
834        }
835    }
836
837    /// Writes bytes to slave with given `address`
838    pub async fn write_async<A: Into<I2cAddress>>(
839        &mut self,
840        address: A,
841        buffer: &[u8],
842    ) -> Result<(), Error> {
843        self.transaction_async(address, &mut [Operation::Write(buffer)])
844            .await
845    }
846
847    /// Reads enough bytes from slave with `address` to fill `buffer`
848    ///
849    /// # Errors
850    ///
851    /// The corresponding error variant from [`Error`] will be returned if the
852    /// passed buffer has zero length.
853    pub async fn read_async<A: Into<I2cAddress>>(
854        &mut self,
855        address: A,
856        buffer: &mut [u8],
857    ) -> Result<(), Error> {
858        self.transaction_async(address, &mut [Operation::Read(buffer)])
859            .await
860    }
861
862    /// Writes bytes to slave with given `address` and then reads enough
863    /// bytes to fill `buffer` *in a single transaction*
864    ///
865    /// # Errors
866    ///
867    /// The corresponding error variant from [`Error`] will be returned if the
868    /// passed buffer has zero length.
869    pub async fn write_read_async<A: Into<I2cAddress>>(
870        &mut self,
871        address: A,
872        write_buffer: &[u8],
873        read_buffer: &mut [u8],
874    ) -> Result<(), Error> {
875        self.transaction_async(
876            address,
877            &mut [Operation::Write(write_buffer), Operation::Read(read_buffer)],
878        )
879        .await
880    }
881
882    /// Execute the provided operations on the I2C bus as a single
883    /// transaction.
884    ///
885    /// Transaction contract:
886    /// - Before executing the first operation an ST is sent automatically. This
887    ///   is followed by SAD+R/W as appropriate.
888    /// - Data from adjacent operations of the same type are sent after each
889    ///   other without an SP or SR.
890    /// - Between adjacent operations of a different type an SR and SAD+R/W is
891    ///   sent.
892    /// - After executing the last operation an SP is sent automatically.
893    /// - If the last operation is a `Read` the master does not send an
894    ///   acknowledge for the last byte.
895    ///
896    /// - `ST` = start condition
897    /// - `SAD+R/W` = slave address followed by bit 1 to indicate reading or 0
898    ///   to indicate writing
899    /// - `SR` = repeated start condition
900    /// - `SP` = stop condition
901    #[cfg_attr(
902        any(esp32, esp32s2),
903        doc = "\n\nOn ESP32 and ESP32-S2 there might be issues combining large read/write operations with small (<3 bytes) read/write operations.\n\n"
904    )]
905    /// # Errors
906    ///
907    /// The corresponding error variant from [`Error`] will be returned if the
908    /// buffer passed to an [`Operation`] has zero length.
909    pub async fn transaction_async<'a, A: Into<I2cAddress>>(
910        &mut self,
911        address: A,
912        operations: impl IntoIterator<Item = &'a mut Operation<'a>>,
913    ) -> Result<(), Error> {
914        self.driver()
915            .transaction_impl_async(address.into(), operations.into_iter().map(Operation::from))
916            .await
917            .inspect_err(|_| self.internal_recover())
918    }
919}
920
921impl<'d, Dm> I2c<'d, Dm>
922where
923    Dm: DriverMode,
924{
925    fn driver(&self) -> Driver<'_> {
926        Driver {
927            info: self.i2c.info(),
928            state: self.i2c.state(),
929            config: &self.config,
930        }
931    }
932
933    fn internal_recover(&self) {
934        if self.driver().regs().sr().read().bus_busy().bit_is_set() {
935            // Send clock pulses to make sure the slave releases the bus.
936            self.driver().clear_bus_blocking();
937        }
938
939        self.driver().reset_fsm();
940    }
941
942    /// Connect a pin to the I2C SDA signal.
943    ///
944    /// This will replace previous pin assignments for this signal.
945    pub fn with_sda(mut self, sda: impl PeripheralOutput<'d>) -> Self {
946        let info = self.driver().info;
947        let input = info.sda_input;
948        let output = info.sda_output;
949        Driver::connect_pin(sda.into(), input, output, &mut self.config.sda_pin);
950
951        self
952    }
953
954    /// Connect a pin to the I2C SCL signal.
955    ///
956    /// This will replace previous pin assignments for this signal.
957    pub fn with_scl(mut self, scl: impl PeripheralOutput<'d>) -> Self {
958        let info = self.driver().info;
959        let input = info.scl_input;
960        let output = info.scl_output;
961        Driver::connect_pin(scl.into(), input, output, &mut self.config.scl_pin);
962
963        self
964    }
965
966    /// Writes bytes to slave with given `address`
967    /// ```rust, no_run
968    #[doc = crate::before_snippet!()]
969    /// # use esp_hal::i2c::master::{Config, I2c};
970    /// # let mut i2c = I2c::new(
971    /// #   peripherals.I2C0,
972    /// #   Config::default(),
973    /// # )?;
974    /// # const DEVICE_ADDR: u8 = 0x77;
975    /// i2c.write(DEVICE_ADDR, &[0xaa])?;
976    /// # Ok(())
977    /// # }
978    /// ```
979    pub fn write<A: Into<I2cAddress>>(&mut self, address: A, buffer: &[u8]) -> Result<(), Error> {
980        self.transaction(address, &mut [Operation::Write(buffer)])
981    }
982
983    /// Reads enough bytes from slave with `address` to fill `buffer`
984    /// ```rust, no_run
985    #[doc = crate::before_snippet!()]
986    /// # use esp_hal::i2c::master::{Config, I2c};
987    /// # let mut i2c = I2c::new(
988    /// #   peripherals.I2C0,
989    /// #   Config::default(),
990    /// # )?;
991    /// # const DEVICE_ADDR: u8 = 0x77;
992    /// let mut data = [0u8; 22];
993    /// i2c.read(DEVICE_ADDR, &mut data)?;
994    /// # Ok(())
995    /// # }
996    /// ```
997    /// 
998    /// # Errors
999    ///
1000    /// The corresponding error variant from [`Error`] will be returned if the passed buffer has zero length.
1001    pub fn read<A: Into<I2cAddress>>(
1002        &mut self,
1003        address: A,
1004        buffer: &mut [u8],
1005    ) -> Result<(), Error> {
1006        self.transaction(address, &mut [Operation::Read(buffer)])
1007    }
1008
1009    /// Writes bytes to slave with given `address` and then reads enough bytes
1010    /// to fill `buffer` *in a single transaction*
1011    /// ```rust, no_run
1012    #[doc = crate::before_snippet!()]
1013    /// # use esp_hal::i2c::master::{Config, I2c};
1014    /// # let mut i2c = I2c::new(
1015    /// #   peripherals.I2C0,
1016    /// #   Config::default(),
1017    /// # )?;
1018    /// # const DEVICE_ADDR: u8 = 0x77;
1019    /// let mut data = [0u8; 22];
1020    /// i2c.write_read(DEVICE_ADDR, &[0xaa], &mut data)?;
1021    /// # Ok(())
1022    /// # }
1023    /// ```
1024    /// 
1025    /// # Errors
1026    ///
1027    /// The corresponding error variant from [`Error`] will be returned if the passed buffer has zero length.
1028    pub fn write_read<A: Into<I2cAddress>>(
1029        &mut self,
1030        address: A,
1031        write_buffer: &[u8],
1032        read_buffer: &mut [u8],
1033    ) -> Result<(), Error> {
1034        self.transaction(
1035            address,
1036            &mut [Operation::Write(write_buffer), Operation::Read(read_buffer)],
1037        )
1038    }
1039
1040    /// Execute the provided operations on the I2C bus.
1041    ///
1042    /// Transaction contract:
1043    /// - Before executing the first operation an ST is sent automatically. This
1044    ///   is followed by SAD+R/W as appropriate.
1045    /// - Data from adjacent operations of the same type are sent after each
1046    ///   other without an SP or SR.
1047    /// - Between adjacent operations of a different type an SR and SAD+R/W is
1048    ///   sent.
1049    /// - After executing the last operation an SP is sent automatically.
1050    /// - If the last operation is a `Read` the master does not send an
1051    ///   acknowledge for the last byte.
1052    ///
1053    /// - `ST` = start condition
1054    /// - `SAD+R/W` = slave address followed by bit 1 to indicate reading or 0
1055    ///   to indicate writing
1056    /// - `SR` = repeated start condition
1057    /// - `SP` = stop condition
1058    ///
1059    /// ```rust, no_run
1060    #[doc = crate::before_snippet!()]
1061    /// # use esp_hal::i2c::master::{Config, I2c, Operation};
1062    /// # let mut i2c = I2c::new(
1063    /// #   peripherals.I2C0,
1064    /// #   Config::default(),
1065    /// # )?;
1066    /// # const DEVICE_ADDR: u8 = 0x77;
1067    /// let mut data = [0u8; 22];
1068    /// i2c.transaction(
1069    ///     DEVICE_ADDR,
1070    ///     &mut [Operation::Write(&[0xaa]), Operation::Read(&mut data)]
1071    /// )?;
1072    /// # Ok(())
1073    /// # }
1074    /// ```
1075    ///
1076    #[cfg_attr(
1077        any(esp32, esp32s2),
1078        doc = "\n\nOn ESP32 and ESP32-S2 it is advisable to not combine large read/write operations with small (<3 bytes) read/write operations.\n\n"
1079    )]
1080    /// # Errors
1081    ///
1082    /// The corresponding error variant from [`Error`] will be returned if the
1083    /// buffer passed to an [`Operation`] has zero length.
1084    pub fn transaction<'a, A: Into<I2cAddress>>(
1085        &mut self,
1086        address: A,
1087        operations: impl IntoIterator<Item = &'a mut Operation<'a>>,
1088    ) -> Result<(), Error> {
1089        self.driver()
1090            .transaction_impl(address.into(), operations.into_iter().map(Operation::from))
1091            .inspect_err(|_| self.internal_recover())
1092    }
1093
1094    /// Applies a new configuration.
1095    ///
1096    /// # Errors
1097    ///
1098    /// A [`ConfigError`] variant will be returned if bus frequency or timeout
1099    /// passed in config is invalid.
1100    pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
1101        self.config.config = *config;
1102        self.driver().setup(config)?;
1103        self.driver().reset_fsm();
1104        Ok(())
1105    }
1106}
1107
1108impl embedded_hal_async::i2c::I2c for I2c<'_, Async> {
1109    async fn transaction(
1110        &mut self,
1111        address: u8,
1112        operations: &mut [EhalOperation<'_>],
1113    ) -> Result<(), Self::Error> {
1114        self.driver()
1115            .transaction_impl_async(address.into(), operations.iter_mut().map(Operation::from))
1116            .await
1117            .inspect_err(|_| self.internal_recover())
1118    }
1119}
1120
1121fn async_handler(info: &Info, state: &State) {
1122    // Disable all interrupts. The I2C Future will check events based on the
1123    // interrupt status bits.
1124    info.regs().int_ena().write(|w| unsafe { w.bits(0) });
1125
1126    state.waker.wake();
1127}
1128
1129/// Sets the filter with a supplied threshold in clock cycles for which a
1130/// pulse must be present to pass the filter
1131fn set_filter(
1132    register_block: &RegisterBlock,
1133    sda_threshold: Option<u8>,
1134    scl_threshold: Option<u8>,
1135) {
1136    cfg_if::cfg_if! {
1137        if #[cfg(any(esp32, esp32s2))] {
1138            register_block.sda_filter_cfg().modify(|_, w| {
1139                if let Some(threshold) = sda_threshold {
1140                    unsafe { w.sda_filter_thres().bits(threshold) };
1141                }
1142                w.sda_filter_en().bit(sda_threshold.is_some())
1143            });
1144            register_block.scl_filter_cfg().modify(|_, w| {
1145                if let Some(threshold) = scl_threshold {
1146                    unsafe { w.scl_filter_thres().bits(threshold) };
1147                }
1148                w.scl_filter_en().bit(scl_threshold.is_some())
1149            });
1150        } else {
1151            register_block.filter_cfg().modify(|_, w| {
1152                if let Some(threshold) = sda_threshold {
1153                    unsafe { w.sda_filter_thres().bits(threshold) };
1154                }
1155                if let Some(threshold) = scl_threshold {
1156                    unsafe { w.scl_filter_thres().bits(threshold) };
1157                }
1158                w.sda_filter_en().bit(sda_threshold.is_some());
1159                w.scl_filter_en().bit(scl_threshold.is_some())
1160            });
1161        }
1162    }
1163}
1164
1165#[allow(clippy::too_many_arguments, unused)]
1166/// Configures the clock and timing parameters for the I2C peripheral.
1167fn configure_clock(
1168    register_block: &RegisterBlock,
1169    sclk_div: u32,
1170    scl_low_period: u32,
1171    scl_high_period: u32,
1172    scl_wait_high_period: u32,
1173    sda_hold_time: u32,
1174    sda_sample_time: u32,
1175    scl_rstart_setup_time: u32,
1176    scl_stop_setup_time: u32,
1177    scl_start_hold_time: u32,
1178    scl_stop_hold_time: u32,
1179    timeout: BusTimeout,
1180) -> Result<(), ConfigError> {
1181    unsafe {
1182        // divider
1183        #[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
1184        register_block.clk_conf().modify(|_, w| {
1185            w.sclk_sel().clear_bit();
1186            w.sclk_div_num().bits((sclk_div - 1) as u8)
1187        });
1188
1189        // scl period
1190        register_block
1191            .scl_low_period()
1192            .write(|w| w.scl_low_period().bits(scl_low_period as u16));
1193
1194        #[cfg(not(esp32))]
1195        let scl_wait_high_period = scl_wait_high_period
1196            .try_into()
1197            .map_err(|_| ConfigError::FrequencyInvalid)?;
1198
1199        register_block.scl_high_period().write(|w| {
1200            #[cfg(not(esp32))] // ESP32 does not have a wait_high field
1201            w.scl_wait_high_period().bits(scl_wait_high_period);
1202            w.scl_high_period().bits(scl_high_period as u16)
1203        });
1204
1205        // sda sample
1206        register_block
1207            .sda_hold()
1208            .write(|w| w.time().bits(sda_hold_time as u16));
1209        register_block
1210            .sda_sample()
1211            .write(|w| w.time().bits(sda_sample_time as u16));
1212
1213        // setup
1214        register_block
1215            .scl_rstart_setup()
1216            .write(|w| w.time().bits(scl_rstart_setup_time as u16));
1217        register_block
1218            .scl_stop_setup()
1219            .write(|w| w.time().bits(scl_stop_setup_time as u16));
1220
1221        // hold
1222        register_block
1223            .scl_start_hold()
1224            .write(|w| w.time().bits(scl_start_hold_time as u16));
1225        register_block
1226            .scl_stop_hold()
1227            .write(|w| w.time().bits(scl_stop_hold_time as u16));
1228
1229        // The ESP32 variant does not have an enable flag for the
1230        // timeout mechanism
1231        cfg_if::cfg_if! {
1232            if #[cfg(esp32)] {
1233                register_block
1234                    .to()
1235                    .write(|w| w.time_out().bits(timeout.cycles()));
1236            } else {
1237                register_block
1238                    .to()
1239                    .write(|w| w.time_out_en().bit(timeout.is_set())
1240                    .time_out_value()
1241                    .bits(timeout.cycles() as _)
1242                );
1243            }
1244        }
1245    }
1246    Ok(())
1247}
1248
1249/// Peripheral data describing a particular I2C instance.
1250#[doc(hidden)]
1251#[derive(Debug)]
1252#[non_exhaustive]
1253pub struct Info {
1254    /// Pointer to the register block for this I2C instance.
1255    ///
1256    /// Use [Self::register_block] to access the register block.
1257    pub register_block: *const RegisterBlock,
1258
1259    /// System peripheral marker.
1260    pub peripheral: crate::system::Peripheral,
1261
1262    /// Interrupt handler for the asynchronous operations of this I2C instance.
1263    pub async_handler: InterruptHandler,
1264
1265    /// Interrupt for this I2C instance.
1266    pub interrupt: Interrupt,
1267
1268    /// SCL output signal.
1269    pub scl_output: OutputSignal,
1270
1271    /// SCL input signal.
1272    pub scl_input: InputSignal,
1273
1274    /// SDA output signal.
1275    pub sda_output: OutputSignal,
1276
1277    /// SDA input signal.
1278    pub sda_input: InputSignal,
1279}
1280
1281impl Info {
1282    /// Returns the register block for this I2C instance.
1283    pub fn regs(&self) -> &RegisterBlock {
1284        unsafe { &*self.register_block }
1285    }
1286
1287    /// Listen for the given interrupts
1288    fn enable_listen(&self, interrupts: EnumSet<Event>, enable: bool) {
1289        let reg_block = self.regs();
1290
1291        reg_block.int_ena().modify(|_, w| {
1292            for interrupt in interrupts {
1293                match interrupt {
1294                    Event::EndDetect => w.end_detect().bit(enable),
1295                    Event::TxComplete => w.trans_complete().bit(enable),
1296                    #[cfg(not(any(esp32, esp32s2)))]
1297                    Event::TxFifoWatermark => w.txfifo_wm().bit(enable),
1298                };
1299            }
1300            w
1301        });
1302    }
1303
1304    fn interrupts(&self) -> EnumSet<Event> {
1305        let mut res = EnumSet::new();
1306        let reg_block = self.regs();
1307
1308        let ints = reg_block.int_raw().read();
1309
1310        if ints.end_detect().bit_is_set() {
1311            res.insert(Event::EndDetect);
1312        }
1313        if ints.trans_complete().bit_is_set() {
1314            res.insert(Event::TxComplete);
1315        }
1316        #[cfg(not(any(esp32, esp32s2)))]
1317        if ints.txfifo_wm().bit_is_set() {
1318            res.insert(Event::TxFifoWatermark);
1319        }
1320
1321        res
1322    }
1323
1324    fn clear_interrupts(&self, interrupts: EnumSet<Event>) {
1325        let reg_block = self.regs();
1326
1327        reg_block.int_clr().write(|w| {
1328            for interrupt in interrupts {
1329                match interrupt {
1330                    Event::EndDetect => w.end_detect().clear_bit_by_one(),
1331                    Event::TxComplete => w.trans_complete().clear_bit_by_one(),
1332                    #[cfg(not(any(esp32, esp32s2)))]
1333                    Event::TxFifoWatermark => w.txfifo_wm().clear_bit_by_one(),
1334                };
1335            }
1336            w
1337        });
1338    }
1339
1340    fn set_interrupt_handler(&self, handler: InterruptHandler) {
1341        for core in crate::system::Cpu::other() {
1342            crate::interrupt::disable(core, self.interrupt);
1343        }
1344        self.enable_listen(EnumSet::all(), false);
1345        self.clear_interrupts(EnumSet::all());
1346        unsafe { crate::interrupt::bind_interrupt(self.interrupt, handler.handler()) };
1347        unwrap!(crate::interrupt::enable(self.interrupt, handler.priority()));
1348    }
1349
1350    fn disable_interrupts(&self) {
1351        crate::interrupt::disable(crate::system::Cpu::current(), self.interrupt);
1352    }
1353}
1354
1355impl PartialEq for Info {
1356    fn eq(&self, other: &Self) -> bool {
1357        core::ptr::eq(self.register_block, other.register_block)
1358    }
1359}
1360
1361unsafe impl Sync for Info {}
1362
1363#[derive(Clone, Copy)]
1364enum Deadline {
1365    None,
1366    Fixed(Instant),
1367    PerByte(Duration),
1368}
1369
1370impl Deadline {
1371    fn start(self, data_len: usize) -> Option<Instant> {
1372        match self {
1373            Deadline::None => None,
1374            Deadline::Fixed(deadline) => Some(deadline),
1375            Deadline::PerByte(duration) => Some(Instant::now() + duration * data_len as u32),
1376        }
1377    }
1378}
1379
1380#[allow(dead_code)] // Some versions don't need `state`
1381#[derive(Clone, Copy)]
1382struct Driver<'a> {
1383    info: &'a Info,
1384    state: &'a State,
1385    config: &'a DriverConfig,
1386}
1387
1388impl Driver<'_> {
1389    fn regs(&self) -> &RegisterBlock {
1390        self.info.regs()
1391    }
1392
1393    fn connect_pin(
1394        pin: crate::gpio::interconnect::OutputSignal<'_>,
1395        input: InputSignal,
1396        output: OutputSignal,
1397        guard: &mut PinGuard,
1398    ) {
1399        // avoid the pin going low during configuration
1400        pin.set_output_high(true);
1401
1402        pin.apply_output_config(
1403            &OutputConfig::default()
1404                .with_drive_mode(DriveMode::OpenDrain)
1405                .with_pull(Pull::Up),
1406        );
1407        pin.set_output_enable(true);
1408        pin.set_input_enable(true);
1409
1410        input.connect_to(&pin);
1411
1412        *guard = interconnect::OutputSignal::connect_with_guard(pin, output);
1413    }
1414
1415    fn init_master(&self) {
1416        self.regs().ctr().write(|w| {
1417            // Set I2C controller to master mode
1418            w.ms_mode().set_bit();
1419            // Use open drain output for SDA and SCL
1420            w.sda_force_out().set_bit();
1421            w.scl_force_out().set_bit();
1422            // Use Most Significant Bit first for sending and receiving data
1423            w.tx_lsb_first().clear_bit();
1424            w.rx_lsb_first().clear_bit();
1425
1426            #[cfg(not(esp32))]
1427            w.arbitration_en().clear_bit();
1428
1429            #[cfg(esp32s2)]
1430            w.ref_always_on().set_bit();
1431
1432            // Ensure that clock is enabled
1433            w.clk_en().set_bit()
1434        });
1435    }
1436
1437    /// Configures the I2C peripheral with the specified frequency, clocks, and
1438    /// optional timeout.
1439    fn setup(&self, config: &Config) -> Result<(), ConfigError> {
1440        self.init_master();
1441
1442        // Configure filter
1443        // FIXME if we ever change this we need to adapt `set_frequency` for ESP32
1444        set_filter(self.regs(), Some(7), Some(7));
1445
1446        // Configure frequency
1447        self.set_frequency(config)?;
1448
1449        // Configure additional timeouts
1450        #[cfg(not(any(esp32, esp32s2)))]
1451        {
1452            self.regs()
1453                .scl_st_time_out()
1454                .write(|w| unsafe { w.scl_st_to().bits(config.scl_st_timeout.value()) });
1455            self.regs()
1456                .scl_main_st_time_out()
1457                .write(|w| unsafe { w.scl_main_st_to().bits(config.scl_main_st_timeout.value()) });
1458        }
1459
1460        self.update_registers();
1461
1462        Ok(())
1463    }
1464
1465    /// Resets the I2C controller (FIFO + FSM + command list)
1466    // This function implements esp-idf's `s_i2c_hw_fsm_reset`, without the
1467    // clear_bus=true parts.
1468    // https://github.com/espressif/esp-idf/blob/27d68f57e6bdd3842cd263585c2c352698a9eda2/components/esp_driver_i2c/i2c_master.c#L115
1469    //
1470    // Make sure you don't call this function in the middle of a transaction. If the
1471    // first command in the command list is not a START, the hardware will hang
1472    // with no timeouts.
1473    fn reset_fsm(&self) {
1474        cfg_if::cfg_if! {
1475            if #[cfg(any(esp32c6, esp32h2))] {
1476                // Device has a working FSM reset mechanism
1477                self.regs().ctr().modify(|_, w| w.fsm_rst().set_bit());
1478            } else {
1479                // Even though C2 and C3 have a FSM reset bit, esp-idf does not
1480                // define SOC_I2C_SUPPORT_HW_FSM_RST for them, so include them in the fallback impl.
1481
1482                // Do the reset
1483                crate::system::PeripheralClockControl::disable(self.info.peripheral);
1484                crate::system::PeripheralClockControl::enable(self.info.peripheral);
1485
1486                // Restore configuration. This operation has succeeded once, so we can
1487                // assume that the config is valid and we can ignore the result.
1488                self.setup(&self.config.config).ok();
1489            }
1490        }
1491    }
1492
1493    fn ensure_idle_blocking(&self) {
1494        if self.regs().sr().read().bus_busy().bit_is_set() {
1495            // If the bus is busy, we need to clear it.
1496            self.clear_bus_blocking();
1497        }
1498    }
1499
1500    async fn ensure_idle(&self) {
1501        if self.regs().sr().read().bus_busy().bit_is_set() {
1502            // If the bus is busy, we need to clear it.
1503            self.clear_bus().await;
1504        }
1505    }
1506
1507    fn reset_before_transmission(&self) {
1508        // Clear all I2C interrupts
1509        self.clear_all_interrupts();
1510
1511        // Reset fifo
1512        self.reset_fifo();
1513
1514        // Reset the command list
1515        self.reset_command_list();
1516    }
1517
1518    /// Implements s_i2c_master_clear_bus
1519    ///
1520    /// If a transaction ended incorrectly for some reason, the slave may drive
1521    /// SDA indefinitely. This function forces the slave to release the
1522    /// bus by sending 9 clock pulses.
1523    fn clear_bus_blocking(&self) {
1524        let mut future = ClearBusFuture::new(*self);
1525        let start = Instant::now();
1526        while future.poll_completion().is_pending() {
1527            if start.elapsed() > CLEAR_BUS_TIMEOUT_MS {
1528                break;
1529            }
1530        }
1531    }
1532
1533    async fn clear_bus(&self) {
1534        let clear_bus = ClearBusFuture::new(*self);
1535        let start = Instant::now();
1536
1537        embassy_futures::select::select(clear_bus, async {
1538            while start.elapsed() < CLEAR_BUS_TIMEOUT_MS {
1539                embassy_futures::yield_now().await;
1540            }
1541        })
1542        .await;
1543    }
1544
1545    /// Resets the I2C peripheral's command registers.
1546    fn reset_command_list(&self) {
1547        for cmd in self.regs().comd_iter() {
1548            cmd.reset();
1549        }
1550    }
1551
1552    #[cfg(esp32)]
1553    /// Sets the frequency of the I2C interface by calculating and applying the
1554    /// associated timings - corresponds to i2c_ll_cal_bus_clk and
1555    /// i2c_ll_set_bus_timing in ESP-IDF
1556    fn set_frequency(&self, clock_config: &Config) -> Result<(), ConfigError> {
1557        let timeout = clock_config.timeout;
1558
1559        let clocks = Clocks::get();
1560        let source_clk = clocks.i2c_clock.as_hz();
1561        let bus_freq = clock_config.frequency.as_hz();
1562
1563        let half_cycle: u32 = source_clk / bus_freq / 2;
1564        let scl_low = half_cycle;
1565        let scl_high = half_cycle;
1566        let sda_hold = half_cycle / 2;
1567        let sda_sample = scl_high / 2;
1568        let setup = half_cycle;
1569        let hold = half_cycle;
1570        let timeout = BusTimeout::BusCycles(match timeout {
1571            BusTimeout::Maximum => 0xF_FFFF,
1572            BusTimeout::BusCycles(cycles) => check_timeout(cycles * 2 * half_cycle, 0xF_FFFF)?,
1573        });
1574
1575        // SCL period. According to the TRM, we should always subtract 1 to SCL low
1576        // period
1577        let scl_low = scl_low - 1;
1578        // Still according to the TRM, if filter is not enbled, we have to subtract 7,
1579        // if SCL filter is enabled, we have to subtract:
1580        //   8 if SCL filter is between 0 and 2 (included)
1581        //   6 + SCL threshold if SCL filter is between 3 and 7 (included)
1582        // to SCL high period
1583        let mut scl_high = scl_high;
1584        // In the "worst" case, we will subtract 13, make sure the result will still be
1585        // correct
1586
1587        // FIXME since we always set the filter threshold to 7 we don't need conditional
1588        // code here once that changes we need the conditional code here
1589        scl_high -= 7 + 6;
1590
1591        // if (filter_cfg_en) {
1592        //     if (thres <= 2) {
1593        //         scl_high -= 8;
1594        //     } else {
1595        //         assert(hw->scl_filter_cfg.thres <= 7);
1596        //         scl_high -= thres + 6;
1597        //     }
1598        // } else {
1599        //    scl_high -= 7;
1600        //}
1601
1602        let scl_high_period = scl_high;
1603        let scl_low_period = scl_low;
1604        // sda sample
1605        let sda_hold_time = sda_hold;
1606        let sda_sample_time = sda_sample;
1607        // setup
1608        let scl_rstart_setup_time = setup;
1609        let scl_stop_setup_time = setup;
1610        // hold
1611        let scl_start_hold_time = hold;
1612        let scl_stop_hold_time = hold;
1613
1614        configure_clock(
1615            self.regs(),
1616            0,
1617            scl_low_period,
1618            scl_high_period,
1619            0,
1620            sda_hold_time,
1621            sda_sample_time,
1622            scl_rstart_setup_time,
1623            scl_stop_setup_time,
1624            scl_start_hold_time,
1625            scl_stop_hold_time,
1626            timeout,
1627        )?;
1628
1629        Ok(())
1630    }
1631
1632    #[cfg(esp32s2)]
1633    /// Sets the frequency of the I2C interface by calculating and applying the
1634    /// associated timings - corresponds to i2c_ll_cal_bus_clk and
1635    /// i2c_ll_set_bus_timing in ESP-IDF
1636    fn set_frequency(&self, clock_config: &Config) -> Result<(), ConfigError> {
1637        let timeout = clock_config.timeout;
1638
1639        let clocks = Clocks::get();
1640        let source_clk = clocks.apb_clock.as_hz();
1641        let bus_freq = clock_config.frequency.as_hz();
1642
1643        let half_cycle: u32 = source_clk / bus_freq / 2;
1644        // SCL
1645        let scl_low = half_cycle;
1646        // default, scl_wait_high < scl_high
1647        let scl_high = half_cycle / 2 + 2;
1648        let scl_wait_high = half_cycle - scl_high;
1649        let sda_hold = half_cycle / 2;
1650        // scl_wait_high < sda_sample <= scl_high
1651        let sda_sample = half_cycle / 2 - 1;
1652        let setup = half_cycle;
1653        let hold = half_cycle;
1654
1655        // scl period
1656        let scl_low_period = scl_low - 1;
1657        let scl_high_period = scl_high;
1658        let scl_wait_high_period = scl_wait_high;
1659        // sda sample
1660        let sda_hold_time = sda_hold;
1661        let sda_sample_time = sda_sample;
1662        // setup
1663        let scl_rstart_setup_time = setup;
1664        let scl_stop_setup_time = setup;
1665        // hold
1666        let scl_start_hold_time = hold - 1;
1667        let scl_stop_hold_time = hold;
1668
1669        let timeout = BusTimeout::BusCycles(match timeout {
1670            BusTimeout::Maximum => 0xFF_FFFF,
1671            BusTimeout::BusCycles(cycles) => check_timeout(cycles * 2 * half_cycle, 0xFF_FFFF)?,
1672        });
1673
1674        configure_clock(
1675            self.regs(),
1676            0,
1677            scl_low_period,
1678            scl_high_period,
1679            scl_wait_high_period,
1680            sda_hold_time,
1681            sda_sample_time,
1682            scl_rstart_setup_time,
1683            scl_stop_setup_time,
1684            scl_start_hold_time,
1685            scl_stop_hold_time,
1686            timeout,
1687        )?;
1688
1689        Ok(())
1690    }
1691
1692    #[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
1693    /// Sets the frequency of the I2C interface by calculating and applying the
1694    /// associated timings - corresponds to i2c_ll_cal_bus_clk and
1695    /// i2c_ll_set_bus_timing in ESP-IDF
1696    fn set_frequency(&self, clock_config: &Config) -> Result<(), ConfigError> {
1697        let timeout = clock_config.timeout;
1698
1699        let clocks = Clocks::get();
1700        let source_clk = clocks.xtal_clock.as_hz();
1701        let bus_freq = clock_config.frequency.as_hz();
1702
1703        let clkm_div: u32 = source_clk / (bus_freq * 1024) + 1;
1704        let sclk_freq: u32 = source_clk / clkm_div;
1705        let half_cycle: u32 = sclk_freq / bus_freq / 2;
1706        // SCL
1707        let scl_low = half_cycle;
1708        // default, scl_wait_high < scl_high
1709        // Make 80KHz as a boundary here, because when working at lower frequency, too
1710        // much scl_wait_high will faster the frequency according to some
1711        // hardware behaviors.
1712        let scl_wait_high = if bus_freq >= 80 * 1000 {
1713            half_cycle / 2 - 2
1714        } else {
1715            half_cycle / 4
1716        };
1717        let scl_high = half_cycle - scl_wait_high;
1718        let sda_hold = half_cycle / 4;
1719        let sda_sample = half_cycle / 2 + scl_wait_high;
1720        let setup = half_cycle;
1721        let hold = half_cycle;
1722
1723        // According to the Technical Reference Manual, the following timings must be
1724        // subtracted by 1. However, according to the practical measurement and
1725        // some hardware behaviour, if wait_high_period and scl_high minus one.
1726        // The SCL frequency would be a little higher than expected. Therefore, the
1727        // solution here is not to minus scl_high as well as scl_wait high, and
1728        // the frequency will be absolutely accurate to all frequency
1729        // to some extent.
1730        let scl_low_period = scl_low - 1;
1731        let scl_high_period = scl_high;
1732        let scl_wait_high_period = scl_wait_high;
1733        // sda sample
1734        let sda_hold_time = sda_hold - 1;
1735        let sda_sample_time = sda_sample - 1;
1736        // setup
1737        let scl_rstart_setup_time = setup - 1;
1738        let scl_stop_setup_time = setup - 1;
1739        // hold
1740        let scl_start_hold_time = hold - 1;
1741        let scl_stop_hold_time = hold - 1;
1742
1743        let timeout = match timeout {
1744            BusTimeout::Maximum => BusTimeout::BusCycles(0x1F),
1745            BusTimeout::Disabled => BusTimeout::Disabled,
1746            BusTimeout::BusCycles(cycles) => {
1747                let to_peri = (cycles * 2 * half_cycle).max(1);
1748                let log2 = to_peri.ilog2();
1749                // Round up so that we don't shorten timeouts.
1750                let raw = if to_peri != 1 << log2 { log2 + 1 } else { log2 };
1751                BusTimeout::BusCycles(check_timeout(raw, 0x1F)?)
1752            }
1753        };
1754
1755        configure_clock(
1756            self.regs(),
1757            clkm_div,
1758            scl_low_period,
1759            scl_high_period,
1760            scl_wait_high_period,
1761            sda_hold_time,
1762            sda_sample_time,
1763            scl_rstart_setup_time,
1764            scl_stop_setup_time,
1765            scl_start_hold_time,
1766            scl_stop_hold_time,
1767            timeout,
1768        )?;
1769
1770        Ok(())
1771    }
1772
1773    /// Configures the I2C peripheral for a write operation.
1774    /// - `addr` is the address of the slave device.
1775    /// - `bytes` is the data two be sent.
1776    /// - `start` indicates whether the operation should start by a START
1777    ///   condition and sending the address.
1778    /// - `cmd_iterator` is an iterator over the command registers.
1779    fn setup_write<'a, I>(
1780        &self,
1781        addr: I2cAddress,
1782        bytes: &[u8],
1783        start: bool,
1784        cmd_iterator: &mut I,
1785    ) -> Result<(), Error>
1786    where
1787        I: Iterator<Item = &'a COMD>,
1788    {
1789        // If start is true we need to send the address, too, which takes up a data
1790        // byte.
1791        let max_len = if start {
1792            I2C_CHUNK_SIZE
1793        } else {
1794            I2C_CHUNK_SIZE + 1
1795        };
1796        if bytes.len() > max_len {
1797            return Err(Error::FifoExceeded);
1798        }
1799
1800        if start {
1801            add_cmd(cmd_iterator, Command::Start)?;
1802        }
1803
1804        let write_len = if start { bytes.len() + 1 } else { bytes.len() };
1805        // don't issue write if there is no data to write
1806        if write_len > 0 {
1807            if cfg!(any(esp32, esp32s2)) {
1808                // try to place END at the same index
1809                if write_len < 2 {
1810                    add_cmd(
1811                        cmd_iterator,
1812                        Command::Write {
1813                            ack_exp: Ack::Ack,
1814                            ack_check_en: true,
1815                            length: write_len as u8,
1816                        },
1817                    )?;
1818                } else if start {
1819                    add_cmd(
1820                        cmd_iterator,
1821                        Command::Write {
1822                            ack_exp: Ack::Ack,
1823                            ack_check_en: true,
1824                            length: (write_len as u8) - 1,
1825                        },
1826                    )?;
1827                    add_cmd(
1828                        cmd_iterator,
1829                        Command::Write {
1830                            ack_exp: Ack::Ack,
1831                            ack_check_en: true,
1832                            length: 1,
1833                        },
1834                    )?;
1835                } else {
1836                    add_cmd(
1837                        cmd_iterator,
1838                        Command::Write {
1839                            ack_exp: Ack::Ack,
1840                            ack_check_en: true,
1841                            length: (write_len as u8) - 2,
1842                        },
1843                    )?;
1844                    add_cmd(
1845                        cmd_iterator,
1846                        Command::Write {
1847                            ack_exp: Ack::Ack,
1848                            ack_check_en: true,
1849                            length: 1,
1850                        },
1851                    )?;
1852                    add_cmd(
1853                        cmd_iterator,
1854                        Command::Write {
1855                            ack_exp: Ack::Ack,
1856                            ack_check_en: true,
1857                            length: 1,
1858                        },
1859                    )?;
1860                }
1861            } else {
1862                add_cmd(
1863                    cmd_iterator,
1864                    Command::Write {
1865                        ack_exp: Ack::Ack,
1866                        ack_check_en: true,
1867                        length: write_len as u8,
1868                    },
1869                )?;
1870            }
1871        }
1872
1873        if start {
1874            // Load address and R/W bit into FIFO
1875            match addr {
1876                I2cAddress::SevenBit(addr) => {
1877                    write_fifo(self.regs(), (addr << 1) | OperationType::Write as u8);
1878                }
1879            }
1880        }
1881        for b in bytes {
1882            write_fifo(self.regs(), *b);
1883        }
1884
1885        Ok(())
1886    }
1887
1888    /// Configures the I2C peripheral for a read operation.
1889    /// - `addr` is the address of the slave device.
1890    /// - `buffer` is the buffer to store the read data.
1891    /// - `start` indicates whether the operation should start by a START
1892    ///   condition and sending the address.
1893    /// - `will_continue` indicates whether there is another read operation
1894    ///   following this one and we should not nack the last byte.
1895    /// - `cmd_iterator` is an iterator over the command registers.
1896    fn setup_read<'a, I>(
1897        &self,
1898        addr: I2cAddress,
1899        buffer: &mut [u8],
1900        start: bool,
1901        will_continue: bool,
1902        cmd_iterator: &mut I,
1903    ) -> Result<(), Error>
1904    where
1905        I: Iterator<Item = &'a COMD>,
1906    {
1907        if buffer.is_empty() {
1908            return Err(Error::ZeroLengthInvalid);
1909        }
1910        let (max_len, initial_len) = if will_continue {
1911            (I2C_CHUNK_SIZE + 1, buffer.len())
1912        } else {
1913            (I2C_CHUNK_SIZE, buffer.len() - 1)
1914        };
1915        if buffer.len() > max_len {
1916            return Err(Error::FifoExceeded);
1917        }
1918
1919        if start {
1920            add_cmd(cmd_iterator, Command::Start)?;
1921            // WRITE command
1922            add_cmd(
1923                cmd_iterator,
1924                Command::Write {
1925                    ack_exp: Ack::Ack,
1926                    ack_check_en: true,
1927                    length: 1,
1928                },
1929            )?;
1930        }
1931
1932        if initial_len > 0 {
1933            if cfg!(any(esp32, esp32s2)) {
1934                // try to place END at the same index
1935                if initial_len < 2 || start {
1936                    add_cmd(
1937                        cmd_iterator,
1938                        Command::Read {
1939                            ack_value: Ack::Ack,
1940                            length: initial_len as u8,
1941                        },
1942                    )?;
1943                } else if !will_continue {
1944                    add_cmd(
1945                        cmd_iterator,
1946                        Command::Read {
1947                            ack_value: Ack::Ack,
1948                            length: (initial_len as u8) - 1,
1949                        },
1950                    )?;
1951                    add_cmd(
1952                        cmd_iterator,
1953                        Command::Read {
1954                            ack_value: Ack::Ack,
1955                            length: 1,
1956                        },
1957                    )?;
1958                } else {
1959                    add_cmd(
1960                        cmd_iterator,
1961                        Command::Read {
1962                            ack_value: Ack::Ack,
1963                            length: (initial_len as u8) - 2,
1964                        },
1965                    )?;
1966                    add_cmd(
1967                        cmd_iterator,
1968                        Command::Read {
1969                            ack_value: Ack::Ack,
1970                            length: 1,
1971                        },
1972                    )?;
1973                    add_cmd(
1974                        cmd_iterator,
1975                        Command::Read {
1976                            ack_value: Ack::Ack,
1977                            length: 1,
1978                        },
1979                    )?;
1980                }
1981            } else {
1982                add_cmd(
1983                    cmd_iterator,
1984                    Command::Read {
1985                        ack_value: Ack::Ack,
1986                        length: initial_len as u8,
1987                    },
1988                )?;
1989            }
1990        }
1991
1992        if !will_continue {
1993            // this is the last read so we need to nack the last byte
1994            // READ w/o ACK
1995            add_cmd(
1996                cmd_iterator,
1997                Command::Read {
1998                    ack_value: Ack::Nack,
1999                    length: 1,
2000                },
2001            )?;
2002        }
2003
2004        self.update_registers();
2005
2006        if start {
2007            // Load address and R/W bit into FIFO
2008            match addr {
2009                I2cAddress::SevenBit(addr) => {
2010                    write_fifo(self.regs(), (addr << 1) | OperationType::Read as u8);
2011                }
2012            }
2013        }
2014        Ok(())
2015    }
2016
2017    /// Reads from RX FIFO into the given buffer.
2018    fn read_all_from_fifo(&self, buffer: &mut [u8]) -> Result<(), Error> {
2019        // we don't support single I2C reads larger than the FIFO
2020        if buffer.len() > I2C_FIFO_SIZE {
2021            return Err(Error::FifoExceeded);
2022        }
2023
2024        if self.regs().sr().read().rxfifo_cnt().bits() < buffer.len() as u8 {
2025            return Err(Error::ExecutionIncomplete);
2026        }
2027
2028        // Read bytes from FIFO
2029        for byte in buffer.iter_mut() {
2030            *byte = read_fifo(self.regs());
2031        }
2032
2033        Ok(())
2034    }
2035
2036    /// Clears all pending interrupts for the I2C peripheral.
2037    fn clear_all_interrupts(&self) {
2038        self.regs()
2039            .int_clr()
2040            .write(|w| unsafe { w.bits(I2C_LL_INTR_MASK) });
2041    }
2042
2043    async fn wait_for_completion(&self, deadline: Option<Instant>) -> Result<(), Error> {
2044        I2cFuture::new(Event::TxComplete | Event::EndDetect, *self, deadline).await?;
2045        self.check_all_commands_done(deadline).await
2046    }
2047
2048    /// Waits for the completion of an I2C transaction.
2049    fn wait_for_completion_blocking(&self, deadline: Option<Instant>) -> Result<(), Error> {
2050        let mut future =
2051            I2cFuture::new_blocking(Event::TxComplete | Event::EndDetect, *self, deadline);
2052        loop {
2053            if let Poll::Ready(result) = future.poll_completion() {
2054                result?;
2055                return self.check_all_commands_done_blocking(deadline);
2056            }
2057        }
2058    }
2059
2060    fn all_commands_done(&self, deadline: Option<Instant>) -> Result<bool, Error> {
2061        // NOTE: on esp32 executing the end command generates the end_detect interrupt
2062        //       but does not seem to clear the done bit! So we don't check the done
2063        //       status of an end command
2064        let now = if deadline.is_some() {
2065            Instant::now()
2066        } else {
2067            Instant::EPOCH
2068        };
2069
2070        for cmd_reg in self.regs().comd_iter() {
2071            let cmd = cmd_reg.read();
2072
2073            // if there is a valid command which is not END, check if it's marked as done
2074            if cmd.bits() != 0x0 && !cmd.opcode().is_end() && !cmd.command_done().bit_is_set() {
2075                // Let's retry
2076                if let Some(deadline) = deadline {
2077                    if now > deadline {
2078                        return Err(Error::ExecutionIncomplete);
2079                    }
2080                }
2081                return Ok(false);
2082            }
2083
2084            // once we hit END or STOP we can break the loop
2085            if cmd.opcode().is_end() {
2086                break;
2087            }
2088            if cmd.opcode().is_stop() {
2089                #[cfg(esp32)]
2090                // wait for STOP - apparently on ESP32 we otherwise miss the ACK error for an
2091                // empty write
2092                if self.regs().sr().read().scl_state_last() == 6 {
2093                    self.check_errors()?;
2094                } else {
2095                    continue;
2096                }
2097                break;
2098            }
2099        }
2100        Ok(true)
2101    }
2102
2103    /// Checks whether all I2C commands have completed execution.
2104    fn check_all_commands_done_blocking(&self, deadline: Option<Instant>) -> Result<(), Error> {
2105        // loop until commands are actually done
2106        while !self.all_commands_done(deadline)? {}
2107
2108        Ok(())
2109    }
2110
2111    /// Checks whether all I2C commands have completed execution.
2112    async fn check_all_commands_done(&self, deadline: Option<Instant>) -> Result<(), Error> {
2113        // loop until commands are actually done
2114        while !self.all_commands_done(deadline)? {
2115            embassy_futures::yield_now().await;
2116        }
2117
2118        Ok(())
2119    }
2120
2121    /// Checks for I2C transmission errors and handles them.
2122    ///
2123    /// This function inspects specific I2C-related interrupts to detect errors
2124    /// during communication, such as timeouts, failed acknowledgments, or
2125    /// arbitration loss. If an error is detected, the function handles it
2126    /// by resetting the I2C peripheral to clear the error condition and then
2127    /// returns an appropriate error.
2128    fn check_errors(&self) -> Result<(), Error> {
2129        let r = self.regs().int_raw().read();
2130
2131        // The ESP32 variant has a slightly different interrupt naming
2132        // scheme!
2133
2134        // Handle error cases
2135        if r.time_out().bit_is_set() {
2136            return Err(Error::Timeout);
2137        }
2138        if r.nack().bit_is_set() {
2139            return Err(Error::AcknowledgeCheckFailed(estimate_ack_failed_reason(
2140                self.regs(),
2141            )));
2142        }
2143        if r.arbitration_lost().bit_is_set() {
2144            return Err(Error::ArbitrationLost);
2145        }
2146
2147        #[cfg(not(any(esp32, esp32s2)))]
2148        {
2149            if r.scl_st_to().bit_is_set() {
2150                return Err(Error::Timeout);
2151            }
2152            if r.scl_main_st_to().bit_is_set() {
2153                return Err(Error::Timeout);
2154            }
2155        }
2156
2157        #[cfg(not(esp32))]
2158        if r.trans_complete().bit_is_set() && self.regs().sr().read().resp_rec().bit_is_clear() {
2159            return Err(Error::AcknowledgeCheckFailed(
2160                AcknowledgeCheckFailedReason::Data,
2161            ));
2162        }
2163
2164        Ok(())
2165    }
2166
2167    /// Updates the configuration of the I2C peripheral.
2168    ///
2169    /// This function ensures that the configuration values, such as clock
2170    /// settings, SDA/SCL filtering, timeouts, and other operational
2171    /// parameters, which are configured in other functions, are properly
2172    /// propagated to the I2C hardware. This step is necessary to synchronize
2173    /// the software-configured settings with the peripheral's internal
2174    /// registers, ensuring that the hardware behaves according to the
2175    /// current configuration.
2176    fn update_registers(&self) {
2177        // Ensure that the configuration of the peripheral is correctly propagated
2178        // (only necessary for C2, C3, C6, H2 and S3 variant)
2179        #[cfg(not(any(esp32, esp32s2)))]
2180        self.regs().ctr().modify(|_, w| w.conf_upgate().set_bit());
2181    }
2182
2183    /// Starts an I2C transmission.
2184    fn start_transmission(&self) {
2185        // Start transmission
2186        self.regs().ctr().modify(|_, w| w.trans_start().set_bit());
2187    }
2188
2189    /// Resets the transmit and receive FIFO buffers
2190    #[cfg(not(esp32))]
2191    fn reset_fifo(&self) {
2192        // First, reset the fifo buffers
2193        self.regs().fifo_conf().modify(|_, w| unsafe {
2194            w.tx_fifo_rst().set_bit();
2195            w.rx_fifo_rst().set_bit();
2196            w.nonfifo_en().clear_bit();
2197            w.fifo_prt_en().set_bit();
2198            w.rxfifo_wm_thrhd().bits(1);
2199            w.txfifo_wm_thrhd().bits(8)
2200        });
2201
2202        self.regs().fifo_conf().modify(|_, w| {
2203            w.tx_fifo_rst().clear_bit();
2204            w.rx_fifo_rst().clear_bit()
2205        });
2206
2207        self.regs().int_clr().write(|w| {
2208            w.rxfifo_wm().clear_bit_by_one();
2209            w.txfifo_wm().clear_bit_by_one()
2210        });
2211
2212        self.update_registers();
2213    }
2214
2215    /// Resets the transmit and receive FIFO buffers
2216    #[cfg(esp32)]
2217    fn reset_fifo(&self) {
2218        // First, reset the fifo buffers
2219        self.regs().fifo_conf().modify(|_, w| unsafe {
2220            w.tx_fifo_rst().set_bit();
2221            w.rx_fifo_rst().set_bit();
2222            w.nonfifo_en().clear_bit();
2223            w.nonfifo_rx_thres().bits(1);
2224            w.nonfifo_tx_thres().bits(32)
2225        });
2226
2227        self.regs().fifo_conf().modify(|_, w| {
2228            w.tx_fifo_rst().clear_bit();
2229            w.rx_fifo_rst().clear_bit()
2230        });
2231
2232        self.regs()
2233            .int_clr()
2234            .write(|w| w.rxfifo_full().clear_bit_by_one());
2235    }
2236
2237    fn start_write_operation(
2238        &self,
2239        address: I2cAddress,
2240        bytes: &[u8],
2241        start: bool,
2242        stop: bool,
2243        deadline: Deadline,
2244    ) -> Result<Option<Instant>, Error> {
2245        let cmd_iterator = &mut self.regs().comd_iter();
2246
2247        self.setup_write(address, bytes, start, cmd_iterator)?;
2248
2249        if stop {
2250            add_cmd(cmd_iterator, Command::Stop)?;
2251        } else {
2252            add_cmd(cmd_iterator, Command::End)?;
2253        }
2254        self.start_transmission();
2255        let deadline = deadline.start(bytes.len() + start as usize);
2256
2257        Ok(deadline)
2258    }
2259
2260    /// Executes an I2C read operation.
2261    /// - `addr` is the address of the slave device.
2262    /// - `buffer` is the buffer to store the read data.
2263    /// - `start` indicates whether the operation should start by a START
2264    ///   condition and sending the address.
2265    /// - `stop` indicates whether the operation should end with a STOP
2266    ///   condition.
2267    /// - `will_continue` indicates whether there is another read operation
2268    ///   following this one and we should not nack the last byte.
2269    /// - `cmd_iterator` is an iterator over the command registers.
2270    fn start_read_operation(
2271        &self,
2272        address: I2cAddress,
2273        buffer: &mut [u8],
2274        start: bool,
2275        will_continue: bool,
2276        stop: bool,
2277        deadline: Deadline,
2278    ) -> Result<Option<Instant>, Error> {
2279        let cmd_iterator = &mut self.regs().comd_iter();
2280
2281        self.setup_read(address, buffer, start, will_continue, cmd_iterator)?;
2282
2283        if stop {
2284            add_cmd(cmd_iterator, Command::Stop)?;
2285        } else {
2286            add_cmd(cmd_iterator, Command::End)?;
2287        }
2288        self.start_transmission();
2289        let deadline = deadline.start(buffer.len() + start as usize);
2290
2291        Ok(deadline)
2292    }
2293
2294    /// Executes an I2C write operation.
2295    /// - `addr` is the address of the slave device.
2296    /// - `bytes` is the data two be sent.
2297    /// - `start` indicates whether the operation should start by a START
2298    ///   condition and sending the address.
2299    /// - `stop` indicates whether the operation should end with a STOP
2300    ///   condition.
2301    /// - `cmd_iterator` is an iterator over the command registers.
2302    fn write_operation_blocking(
2303        &self,
2304        address: I2cAddress,
2305        bytes: &[u8],
2306        start: bool,
2307        stop: bool,
2308        deadline: Deadline,
2309    ) -> Result<(), Error> {
2310        address.validate()?;
2311        self.reset_before_transmission();
2312
2313        // Short circuit for zero length writes without start or end as that would be an
2314        // invalid operation write lengths in the TRM (at least for ESP32-S3) are 1-255
2315        if bytes.is_empty() && !start && !stop {
2316            return Ok(());
2317        }
2318
2319        let deadline = self.start_write_operation(address, bytes, start, stop, deadline)?;
2320        self.wait_for_completion_blocking(deadline)?;
2321
2322        Ok(())
2323    }
2324
2325    /// Executes an I2C read operation.
2326    /// - `addr` is the address of the slave device.
2327    /// - `buffer` is the buffer to store the read data.
2328    /// - `start` indicates whether the operation should start by a START
2329    ///   condition and sending the address.
2330    /// - `stop` indicates whether the operation should end with a STOP
2331    ///   condition.
2332    /// - `will_continue` indicates whether there is another read operation
2333    ///   following this one and we should not nack the last byte.
2334    /// - `cmd_iterator` is an iterator over the command registers.
2335    fn read_operation_blocking(
2336        &self,
2337        address: I2cAddress,
2338        buffer: &mut [u8],
2339        start: bool,
2340        stop: bool,
2341        will_continue: bool,
2342        deadline: Deadline,
2343    ) -> Result<(), Error> {
2344        address.validate()?;
2345        self.reset_before_transmission();
2346
2347        // Short circuit for zero length reads as that would be an invalid operation
2348        // read lengths in the TRM (at least for ESP32-S3) are 1-255
2349        if buffer.is_empty() {
2350            return Ok(());
2351        }
2352
2353        let deadline =
2354            self.start_read_operation(address, buffer, start, will_continue, stop, deadline)?;
2355        self.wait_for_completion_blocking(deadline)?;
2356        self.read_all_from_fifo(buffer)?;
2357
2358        Ok(())
2359    }
2360
2361    /// Executes an async I2C write operation.
2362    /// - `addr` is the address of the slave device.
2363    /// - `bytes` is the data two be sent.
2364    /// - `start` indicates whether the operation should start by a START
2365    ///   condition and sending the address.
2366    /// - `stop` indicates whether the operation should end with a STOP
2367    ///   condition.
2368    /// - `cmd_iterator` is an iterator over the command registers.
2369    async fn write_operation(
2370        &self,
2371        address: I2cAddress,
2372        bytes: &[u8],
2373        start: bool,
2374        stop: bool,
2375        deadline: Deadline,
2376    ) -> Result<(), Error> {
2377        address.validate()?;
2378        self.reset_before_transmission();
2379
2380        // Short circuit for zero length writes without start or end as that would be an
2381        // invalid operation write lengths in the TRM (at least for ESP32-S3) are 1-255
2382        if bytes.is_empty() && !start && !stop {
2383            return Ok(());
2384        }
2385
2386        let deadline = self.start_write_operation(address, bytes, start, stop, deadline)?;
2387        self.wait_for_completion(deadline).await?;
2388
2389        Ok(())
2390    }
2391
2392    /// Executes an async I2C read operation.
2393    /// - `addr` is the address of the slave device.
2394    /// - `buffer` is the buffer to store the read data.
2395    /// - `start` indicates whether the operation should start by a START
2396    ///   condition and sending the address.
2397    /// - `stop` indicates whether the operation should end with a STOP
2398    ///   condition.
2399    /// - `will_continue` indicates whether there is another read operation
2400    ///   following this one and we should not nack the last byte.
2401    /// - `cmd_iterator` is an iterator over the command registers.
2402    async fn read_operation(
2403        &self,
2404        address: I2cAddress,
2405        buffer: &mut [u8],
2406        start: bool,
2407        stop: bool,
2408        will_continue: bool,
2409        deadline: Deadline,
2410    ) -> Result<(), Error> {
2411        address.validate()?;
2412        self.reset_before_transmission();
2413
2414        // Short circuit for zero length reads as that would be an invalid operation
2415        // read lengths in the TRM (at least for ESP32-S3) are 1-255
2416        if buffer.is_empty() {
2417            return Ok(());
2418        }
2419
2420        let deadline =
2421            self.start_read_operation(address, buffer, start, will_continue, stop, deadline)?;
2422        self.wait_for_completion(deadline).await?;
2423        self.read_all_from_fifo(buffer)?;
2424
2425        Ok(())
2426    }
2427
2428    fn read_blocking(
2429        &self,
2430        address: I2cAddress,
2431        buffer: &mut [u8],
2432        start: bool,
2433        stop: bool,
2434        will_continue: bool,
2435        deadline: Deadline,
2436    ) -> Result<(), Error> {
2437        let chunk_count = VariableChunkIterMut::new(buffer).count();
2438        for (idx, chunk) in VariableChunkIterMut::new(buffer).enumerate() {
2439            self.read_operation_blocking(
2440                address,
2441                chunk,
2442                start && idx == 0,
2443                stop && idx == chunk_count - 1,
2444                will_continue || idx < chunk_count - 1,
2445                deadline,
2446            )?;
2447        }
2448
2449        Ok(())
2450    }
2451
2452    fn write_blocking(
2453        &self,
2454        address: I2cAddress,
2455        buffer: &[u8],
2456        start: bool,
2457        stop: bool,
2458        deadline: Deadline,
2459    ) -> Result<(), Error> {
2460        if buffer.is_empty() {
2461            return self.write_operation_blocking(address, &[], start, stop, deadline);
2462        }
2463
2464        let chunk_count = VariableChunkIter::new(buffer).count();
2465        for (idx, chunk) in VariableChunkIter::new(buffer).enumerate() {
2466            self.write_operation_blocking(
2467                address,
2468                chunk,
2469                start && idx == 0,
2470                stop && idx == chunk_count - 1,
2471                deadline,
2472            )?;
2473        }
2474
2475        Ok(())
2476    }
2477
2478    async fn read(
2479        &self,
2480        address: I2cAddress,
2481        buffer: &mut [u8],
2482        start: bool,
2483        stop: bool,
2484        will_continue: bool,
2485        deadline: Deadline,
2486    ) -> Result<(), Error> {
2487        let chunk_count = VariableChunkIterMut::new(buffer).count();
2488        for (idx, chunk) in VariableChunkIterMut::new(buffer).enumerate() {
2489            self.read_operation(
2490                address,
2491                chunk,
2492                start && idx == 0,
2493                stop && idx == chunk_count - 1,
2494                will_continue || idx < chunk_count - 1,
2495                deadline,
2496            )
2497            .await?;
2498        }
2499
2500        Ok(())
2501    }
2502
2503    async fn write(
2504        &self,
2505        address: I2cAddress,
2506        buffer: &[u8],
2507        start: bool,
2508        stop: bool,
2509        deadline: Deadline,
2510    ) -> Result<(), Error> {
2511        if buffer.is_empty() {
2512            return self
2513                .write_operation(address, &[], start, stop, deadline)
2514                .await;
2515        }
2516
2517        let chunk_count = VariableChunkIter::new(buffer).count();
2518        for (idx, chunk) in VariableChunkIter::new(buffer).enumerate() {
2519            self.write_operation(
2520                address,
2521                chunk,
2522                start && idx == 0,
2523                stop && idx == chunk_count - 1,
2524                deadline,
2525            )
2526            .await?;
2527        }
2528
2529        Ok(())
2530    }
2531
2532    fn transaction_impl<'a>(
2533        &self,
2534        address: I2cAddress,
2535        operations: impl Iterator<Item = Operation<'a>>,
2536    ) -> Result<(), Error> {
2537        address.validate()?;
2538        self.ensure_idle_blocking();
2539
2540        let mut deadline = Deadline::None;
2541
2542        if let SoftwareTimeout::Transaction(timeout) = self.config.config.software_timeout {
2543            deadline = Deadline::Fixed(Instant::now() + timeout);
2544        }
2545
2546        let mut last_op: Option<OpKind> = None;
2547        // filter out 0 length read operations
2548        let mut op_iter = operations
2549            .filter(|op| op.is_write() || !op.is_empty())
2550            .peekable();
2551
2552        while let Some(op) = op_iter.next() {
2553            let next_op = op_iter.peek().map(|v| v.kind());
2554            let kind = op.kind();
2555            match op {
2556                Operation::Write(buffer) => {
2557                    // execute a write operation:
2558                    // - issue START/RSTART if op is different from previous
2559                    // - issue STOP if op is the last one
2560                    if let SoftwareTimeout::PerByte(timeout) = self.config.config.software_timeout {
2561                        deadline = Deadline::PerByte(timeout);
2562                    }
2563                    self.write_blocking(
2564                        address,
2565                        buffer,
2566                        !matches!(last_op, Some(OpKind::Write)),
2567                        next_op.is_none(),
2568                        deadline,
2569                    )?;
2570                }
2571                Operation::Read(buffer) => {
2572                    if let SoftwareTimeout::PerByte(timeout) = self.config.config.software_timeout {
2573                        deadline = Deadline::PerByte(timeout);
2574                    }
2575                    // execute a read operation:
2576                    // - issue START/RSTART if op is different from previous
2577                    // - issue STOP if op is the last one
2578                    // - will_continue is true if there is another read operation next
2579                    self.read_blocking(
2580                        address,
2581                        buffer,
2582                        !matches!(last_op, Some(OpKind::Read)),
2583                        next_op.is_none(),
2584                        matches!(next_op, Some(OpKind::Read)),
2585                        deadline,
2586                    )?;
2587                }
2588            }
2589
2590            last_op = Some(kind);
2591        }
2592
2593        Ok(())
2594    }
2595
2596    async fn transaction_impl_async<'a>(
2597        &self,
2598        address: I2cAddress,
2599        operations: impl Iterator<Item = Operation<'a>>,
2600    ) -> Result<(), Error> {
2601        address.validate()?;
2602        self.ensure_idle().await;
2603
2604        let mut deadline = Deadline::None;
2605
2606        if let SoftwareTimeout::Transaction(timeout) = self.config.config.software_timeout {
2607            deadline = Deadline::Fixed(Instant::now() + timeout);
2608        }
2609
2610        let mut last_op: Option<OpKind> = None;
2611        // filter out 0 length read operations
2612        let mut op_iter = operations
2613            .filter(|op| op.is_write() || !op.is_empty())
2614            .peekable();
2615
2616        while let Some(op) = op_iter.next() {
2617            let next_op = op_iter.peek().map(|v| v.kind());
2618            let kind = op.kind();
2619            match op {
2620                Operation::Write(buffer) => {
2621                    if let SoftwareTimeout::PerByte(timeout) = self.config.config.software_timeout {
2622                        deadline = Deadline::PerByte(timeout);
2623                    }
2624                    // execute a write operation:
2625                    // - issue START/RSTART if op is different from previous
2626                    // - issue STOP if op is the last one
2627                    self.write(
2628                        address,
2629                        buffer,
2630                        !matches!(last_op, Some(OpKind::Write)),
2631                        next_op.is_none(),
2632                        deadline,
2633                    )
2634                    .await?;
2635                }
2636                Operation::Read(buffer) => {
2637                    if let SoftwareTimeout::PerByte(timeout) = self.config.config.software_timeout {
2638                        deadline = Deadline::PerByte(timeout);
2639                    }
2640                    // execute a read operation:
2641                    // - issue START/RSTART if op is different from previous
2642                    // - issue STOP if op is the last one
2643                    // - will_continue is true if there is another read operation next
2644                    self.read(
2645                        address,
2646                        buffer,
2647                        !matches!(last_op, Some(OpKind::Read)),
2648                        next_op.is_none(),
2649                        matches!(next_op, Some(OpKind::Read)),
2650                        deadline,
2651                    )
2652                    .await?;
2653                }
2654            }
2655
2656            last_op = Some(kind);
2657        }
2658
2659        Ok(())
2660    }
2661}
2662
2663fn check_timeout(v: u32, max: u32) -> Result<u32, ConfigError> {
2664    if v <= max {
2665        Ok(v)
2666    } else {
2667        Err(ConfigError::TimeoutInvalid)
2668    }
2669}
2670
2671/// Chunks a slice by I2C_CHUNK_SIZE in a way to avoid the last chunk being
2672/// sized smaller than 2
2673struct VariableChunkIterMut<'a, T> {
2674    buffer: &'a mut [T],
2675}
2676
2677impl<'a, T> VariableChunkIterMut<'a, T> {
2678    fn new(buffer: &'a mut [T]) -> Self {
2679        Self { buffer }
2680    }
2681}
2682
2683impl<'a, T> Iterator for VariableChunkIterMut<'a, T> {
2684    type Item = &'a mut [T];
2685
2686    fn next(&mut self) -> Option<Self::Item> {
2687        if self.buffer.is_empty() {
2688            return None;
2689        }
2690
2691        let s = calculate_chunk_size(self.buffer.len());
2692        let (chunk, remaining) = core::mem::take(&mut self.buffer).split_at_mut(s);
2693        self.buffer = remaining;
2694        Some(chunk)
2695    }
2696}
2697
2698/// Chunks a slice by I2C_CHUNK_SIZE in a way to avoid the last chunk being
2699/// sized smaller than 2
2700struct VariableChunkIter<'a, T> {
2701    buffer: &'a [T],
2702}
2703
2704impl<'a, T> VariableChunkIter<'a, T> {
2705    fn new(buffer: &'a [T]) -> Self {
2706        Self { buffer }
2707    }
2708}
2709
2710impl<'a, T> Iterator for VariableChunkIter<'a, T> {
2711    type Item = &'a [T];
2712
2713    fn next(&mut self) -> Option<Self::Item> {
2714        if self.buffer.is_empty() {
2715            return None;
2716        }
2717
2718        let s = calculate_chunk_size(self.buffer.len());
2719        let (chunk, remaining) = core::mem::take(&mut self.buffer).split_at(s);
2720        self.buffer = remaining;
2721        Some(chunk)
2722    }
2723}
2724
2725fn calculate_chunk_size(remaining: usize) -> usize {
2726    if remaining <= I2C_CHUNK_SIZE {
2727        remaining
2728    } else if remaining > I2C_CHUNK_SIZE + 2 {
2729        I2C_CHUNK_SIZE
2730    } else {
2731        I2C_CHUNK_SIZE - 2
2732    }
2733}
2734
2735#[cfg(not(any(esp32, esp32s2)))]
2736mod bus_clear {
2737    use super::*;
2738
2739    pub struct ClearBusFuture<'a> {
2740        driver: Driver<'a>,
2741    }
2742
2743    impl<'a> ClearBusFuture<'a> {
2744        // Number of SCL pulses to clear the bus
2745        const BUS_CLEAR_BITS: u8 = 9;
2746
2747        pub fn new(driver: Driver<'a>) -> Self {
2748            let mut this = Self { driver };
2749            this.configure(Self::BUS_CLEAR_BITS);
2750            this
2751        }
2752
2753        fn configure(&mut self, bits: u8) {
2754            self.driver.regs().scl_sp_conf().modify(|_, w| {
2755                unsafe { w.scl_rst_slv_num().bits(bits) };
2756                w.scl_rst_slv_en().bit(bits > 0)
2757            });
2758            self.driver.update_registers();
2759        }
2760
2761        pub fn poll_completion(&mut self) -> Poll<()> {
2762            if self
2763                .driver
2764                .regs()
2765                .scl_sp_conf()
2766                .read()
2767                .scl_rst_slv_en()
2768                .bit_is_set()
2769            {
2770                Poll::Pending
2771            } else {
2772                Poll::Ready(())
2773            }
2774        }
2775    }
2776
2777    impl Drop for ClearBusFuture<'_> {
2778        fn drop(&mut self) {
2779            self.configure(0);
2780            // We don't care about errors during bus clearing
2781            self.driver.clear_all_interrupts();
2782        }
2783    }
2784}
2785
2786#[cfg(any(esp32, esp32s2))]
2787mod bus_clear {
2788    use super::*;
2789    use crate::gpio::AnyPin;
2790
2791    /// State of the bus clearing operation.
2792    ///
2793    /// Pins are changed on the start of the state, and a wait is scheduled
2794    /// for the end of the state. At the end of the wait, the state is
2795    /// updated to the next state.
2796    enum State {
2797        Idle,
2798        SendStop,
2799
2800        // Number of SCL pulses left to send, and the last SCL level.
2801        //
2802        // Our job is to send 9 high->low SCL transitions, followed by a STOP condition.
2803        SendClock(u8, bool),
2804    }
2805
2806    pub struct ClearBusFuture<'a> {
2807        driver: Driver<'a>,
2808        wait: Instant,
2809        state: State,
2810        sda: Option<AnyPin<'static>>,
2811        scl: Option<AnyPin<'static>>,
2812    }
2813
2814    impl<'a> ClearBusFuture<'a> {
2815        // Number of SCL pulses to clear the bus
2816        const BUS_CLEAR_BITS: u8 = 9;
2817        // use standard 100kHz data rate
2818        const SCL_DELAY: Duration = Duration::from_micros(5);
2819
2820        pub fn new(driver: Driver<'a>) -> Self {
2821            // ESP32: The chip is lacking hardware support for bus clearing.
2822            // ESP32-S2: The hardware bus clearing doesn't seem to work
2823            // -> so we implement it in software.
2824            let sda = driver
2825                .config
2826                .sda_pin
2827                .pin_number()
2828                .map(|n| unsafe { AnyPin::steal(n) });
2829            let scl = driver
2830                .config
2831                .scl_pin
2832                .pin_number()
2833                .map(|n| unsafe { AnyPin::steal(n) });
2834
2835            let (Some(sda), Some(scl)) = (sda, scl) else {
2836                // If we don't have the pins, we can't clear the bus.
2837                return Self {
2838                    driver,
2839                    wait: Instant::now(),
2840                    state: State::Idle,
2841                    sda: None,
2842                    scl: None,
2843                };
2844            };
2845
2846            driver.info.scl_output.disconnect_from(&scl);
2847            driver.info.sda_output.disconnect_from(&sda);
2848
2849            sda.set_output_high(true);
2850            scl.set_output_high(false);
2851
2852            // Starting from (9, false), becase:
2853            // - we start with SCL low
2854            // - a complete SCL cycle consists of a high period and a low period
2855            // - we decrement the remaining counter at the beginning of a cycle, which gives
2856            //   us 9 complete SCL cycles.
2857            let state = State::SendClock(Self::BUS_CLEAR_BITS, false);
2858
2859            Self {
2860                driver,
2861                wait: Instant::now() + Self::SCL_DELAY,
2862                state,
2863                sda: Some(sda),
2864                scl: Some(scl),
2865            }
2866        }
2867    }
2868
2869    impl ClearBusFuture<'_> {
2870        pub fn poll_completion(&mut self) -> Poll<()> {
2871            let now = Instant::now();
2872
2873            match self.state {
2874                State::Idle => return Poll::Ready(()),
2875                _ if now < self.wait => {
2876                    // Still waiting for the end of the SCL pulse
2877                    return Poll::Pending;
2878                }
2879                State::SendStop => {
2880                    if let Some(sda) = self.sda.as_ref() {
2881                        sda.set_output_high(true); // STOP, SDA low -> high while SCL is HIGH
2882                    }
2883                    self.state = State::Idle;
2884                    return Poll::Ready(());
2885                }
2886                State::SendClock(0, false) => {
2887                    if let (Some(scl), Some(sda)) = (self.scl.as_ref(), self.sda.as_ref()) {
2888                        // Set up for STOP condition
2889                        sda.set_output_high(false);
2890                        scl.set_output_high(true);
2891                    }
2892                    self.state = State::SendStop;
2893                }
2894                State::SendClock(n, false) => {
2895                    if let Some(scl) = self.scl.as_ref() {
2896                        scl.set_output_high(true);
2897                    }
2898                    self.state = State::SendClock(n - 1, true);
2899                }
2900                State::SendClock(n, true) => {
2901                    if let Some(scl) = self.scl.as_ref() {
2902                        scl.set_output_high(false);
2903                    }
2904                    self.state = State::SendClock(n, false);
2905                }
2906            }
2907            self.wait = Instant::now() + Self::SCL_DELAY;
2908
2909            Poll::Pending
2910        }
2911    }
2912
2913    impl Drop for ClearBusFuture<'_> {
2914        fn drop(&mut self) {
2915            if let (Some(sda), Some(scl)) = (self.sda.take(), self.scl.take()) {
2916                // Make sure _we_ release the bus.
2917                scl.set_output_high(true);
2918                sda.set_output_high(true);
2919
2920                self.driver.info.sda_output.connect_to(&sda);
2921                self.driver.info.scl_output.connect_to(&scl);
2922
2923                // We don't care about errors during bus clearing. There shouldn't be any,
2924                // anyway.
2925                self.driver.clear_all_interrupts();
2926            }
2927        }
2928    }
2929}
2930
2931use bus_clear::ClearBusFuture;
2932
2933impl Future for ClearBusFuture<'_> {
2934    type Output = ();
2935
2936    fn poll(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
2937        let pending = self.poll_completion();
2938        if pending.is_pending() {
2939            ctx.waker().wake_by_ref();
2940        }
2941        pending
2942    }
2943}
2944
2945/// Peripheral state for an I2C instance.
2946#[doc(hidden)]
2947#[non_exhaustive]
2948pub struct State {
2949    /// Waker for the asynchronous operations.
2950    pub waker: AtomicWaker,
2951}
2952
2953/// A peripheral singleton compatible with the I2C master driver.
2954pub trait Instance: crate::private::Sealed + super::IntoAnyI2c {
2955    #[doc(hidden)]
2956    /// Returns the peripheral data and state describing this instance.
2957    fn parts(&self) -> (&Info, &State);
2958
2959    /// Returns the peripheral data describing this instance.
2960    #[doc(hidden)]
2961    #[inline(always)]
2962    fn info(&self) -> &Info {
2963        self.parts().0
2964    }
2965
2966    /// Returns the peripheral state for this instance.
2967    #[doc(hidden)]
2968    #[inline(always)]
2969    fn state(&self) -> &State {
2970        self.parts().1
2971    }
2972}
2973
2974/// Adds a command to the I2C command sequence.
2975///
2976/// Make sure the first command after a FSM reset is a START, otherwise
2977/// the hardware will hang with no timeouts.
2978fn add_cmd<'a, I>(cmd_iterator: &mut I, command: Command) -> Result<(), Error>
2979where
2980    I: Iterator<Item = &'a COMD>,
2981{
2982    let cmd = cmd_iterator.next().ok_or(Error::CommandNumberExceeded)?;
2983
2984    cmd.write(|w| match command {
2985        Command::Start => w.opcode().rstart(),
2986        Command::Stop => w.opcode().stop(),
2987        Command::End => w.opcode().end(),
2988        Command::Write {
2989            ack_exp,
2990            ack_check_en,
2991            length,
2992        } => unsafe {
2993            w.opcode().write();
2994            w.ack_exp().bit(ack_exp == Ack::Nack);
2995            w.ack_check_en().bit(ack_check_en);
2996            w.byte_num().bits(length);
2997            w
2998        },
2999        Command::Read { ack_value, length } => unsafe {
3000            w.opcode().read();
3001            w.ack_value().bit(ack_value == Ack::Nack);
3002            w.byte_num().bits(length);
3003            w
3004        },
3005    });
3006
3007    Ok(())
3008}
3009
3010#[cfg(not(esp32s2))]
3011fn read_fifo(register_block: &RegisterBlock) -> u8 {
3012    register_block.data().read().fifo_rdata().bits()
3013}
3014
3015#[cfg(not(esp32))]
3016fn write_fifo(register_block: &RegisterBlock, data: u8) {
3017    register_block
3018        .data()
3019        .write(|w| unsafe { w.fifo_rdata().bits(data) });
3020}
3021
3022#[cfg(esp32s2)]
3023fn read_fifo(register_block: &RegisterBlock) -> u8 {
3024    let base_addr = register_block.scl_low_period().as_ptr();
3025    let fifo_ptr = (if base_addr as u32 == 0x3f413000 {
3026        0x6001301c
3027    } else {
3028        0x6002701c
3029    }) as *mut u32;
3030    unsafe { (fifo_ptr.read_volatile() & 0xff) as u8 }
3031}
3032
3033#[cfg(esp32)]
3034fn write_fifo(register_block: &RegisterBlock, data: u8) {
3035    let base_addr = register_block.scl_low_period().as_ptr();
3036    let fifo_ptr = (if base_addr as u32 == 0x3FF53000 {
3037        0x6001301c
3038    } else {
3039        0x6002701c
3040    }) as *mut u32;
3041    unsafe {
3042        fifo_ptr.write_volatile(data as u32);
3043    }
3044}
3045
3046// Estimate the reason for an acknowledge check failure on a best effort basis.
3047// When in doubt it's better to return `Unknown` than to return a wrong reason.
3048fn estimate_ack_failed_reason(_register_block: &RegisterBlock) -> AcknowledgeCheckFailedReason {
3049    cfg_if::cfg_if! {
3050        if #[cfg(any(esp32, esp32s2, esp32c2, esp32c3))] {
3051            AcknowledgeCheckFailedReason::Unknown
3052        } else {
3053            // this is based on observations rather than documented behavior
3054            if _register_block.fifo_st().read().txfifo_raddr().bits() <= 1 {
3055                AcknowledgeCheckFailedReason::Address
3056            } else {
3057                AcknowledgeCheckFailedReason::Data
3058            }
3059        }
3060    }
3061}
3062
3063macro_rules! instance {
3064    ($inst:ident, $peri:ident, $scl:ident, $sda:ident, $interrupt:ident) => {
3065        impl Instance for crate::peripherals::$inst<'_> {
3066            fn parts(&self) -> (&Info, &State) {
3067                #[crate::handler]
3068                pub(super) fn irq_handler() {
3069                    async_handler(&PERIPHERAL, &STATE);
3070                }
3071
3072                static STATE: State = State {
3073                    waker: AtomicWaker::new(),
3074                };
3075
3076                static PERIPHERAL: Info = Info {
3077                    register_block: crate::peripherals::$inst::ptr(),
3078                    peripheral: crate::system::Peripheral::$peri,
3079                    async_handler: irq_handler,
3080                    interrupt: Interrupt::$interrupt,
3081                    scl_output: OutputSignal::$scl,
3082                    scl_input: InputSignal::$scl,
3083                    sda_output: OutputSignal::$sda,
3084                    sda_input: InputSignal::$sda,
3085                };
3086                (&PERIPHERAL, &STATE)
3087            }
3088        }
3089    };
3090}
3091
3092#[cfg(i2c0)]
3093instance!(I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA, I2C_EXT0);
3094#[cfg(i2c1)]
3095instance!(I2C1, I2cExt1, I2CEXT1_SCL, I2CEXT1_SDA, I2C_EXT1);
3096
3097impl Instance for AnyI2c<'_> {
3098    delegate::delegate! {
3099        to match &self.0 {
3100            AnyI2cInner::I2c0(i2c) => i2c,
3101            #[cfg(i2c1)]
3102            AnyI2cInner::I2c1(i2c) => i2c,
3103        } {
3104            fn parts(&self) -> (&Info, &State);
3105        }
3106    }
3107}