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