1
#![cfg_attr(docsrs, procmacros::doc_replace)]
2
//! # Inter-Integrated Circuit (I2C) - Master mode
3
//!
4
//! ## Overview
5
//!
6
//! This driver implements the I2C Master mode. In this mode, the MCU initiates
7
//! and controls the I2C communication with one or more slave devices. Slave
8
//! devices are identified by their unique I2C addresses.
9
//!
10
//! ## Configuration
11
//!
12
//! The driver can be configured using the [`Config`] struct. To create a
13
//! configuration, you can use the [`Config::default()`] method, and then modify
14
//! the individual settings as needed, by calling `with_*` methods on the
15
//! [`Config`] struct.
16
//!
17
//! ```rust, no_run
18
//! # {before_snippet}
19
//! use esp_hal::{i2c::master::Config, time::Rate};
20
//!
21
//! let config = Config::default().with_frequency(Rate::from_khz(100));
22
//! # {after_snippet}
23
//! ```
24
//!
25
//! You will then need to pass the configuration to [`I2c::new`], and you can
26
//! also change the configuration later by calling [`I2c::apply_config`].
27
//!
28
//! You will also need to specify the SDA and SCL pins when you create the
29
//! driver instance.
30
//! ```rust, no_run
31
//! # {before_snippet}
32
//! use esp_hal::i2c::master::I2c;
33
//! # use esp_hal::{i2c::master::Config, time::Rate};
34
//! #
35
//! # let config = Config::default();
36
//! #
37
//! // You need to configure the driver during initialization:
38
//! let mut i2c = I2c::new(peripherals.I2C0, config)?
39
//!     .with_sda(peripherals.GPIO2)
40
//!     .with_scl(peripherals.GPIO3);
41
//!
42
//! // You can change the configuration later:
43
//! let new_config = config.with_frequency(Rate::from_khz(400));
44
//! i2c.apply_config(&new_config)?;
45
//! # {after_snippet}
46
//! ```
47
//!
48
//! ## Usage
49
//!
50
//! The master communicates with slave devices using I2C transactions. A
51
//! transaction can be a write, a read, or a combination of both. The
52
//! [`I2c`] driver provides methods for performing these transactions:
53
//! ```rust, no_run
54
//! # {before_snippet}
55
//! # use esp_hal::i2c::master::{I2c, Config, Operation};
56
//! # let config = Config::default();
57
//! # let mut i2c = I2c::new(peripherals.I2C0, config)?;
58
//! #
59
//! // `u8` is automatically converted to `I2cAddress::SevenBit`. The device
60
//! // address does not contain the `R/W` bit!
61
//! const DEVICE_ADDR: u8 = 0x77;
62
//! let write_buffer = [0xAA];
63
//! let mut read_buffer = [0u8; 22];
64
//!
65
//! i2c.write(DEVICE_ADDR, &write_buffer)?;
66
//! i2c.write_read(DEVICE_ADDR, &write_buffer, &mut read_buffer)?;
67
//! i2c.read(DEVICE_ADDR, &mut read_buffer)?;
68
//! i2c.transaction(
69
//!     DEVICE_ADDR,
70
//!     &mut [
71
//!         Operation::Write(&write_buffer),
72
//!         Operation::Read(&mut read_buffer),
73
//!     ],
74
//! )?;
75
//! # {after_snippet}
76
//! ```
77
//! If you configure the driver to `async` mode, the driver also provides
78
//! asynchronous versions of these methods:
79
//! ```rust, no_run
80
//! # {before_snippet}
81
//! # use esp_hal::i2c::master::{I2c, Config, Operation};
82
//! # let config = Config::default();
83
//! # let mut i2c = I2c::new(peripherals.I2C0, config)?;
84
//! #
85
//! # const DEVICE_ADDR: u8 = 0x77;
86
//! # let write_buffer = [0xAA];
87
//! # let mut read_buffer = [0u8; 22];
88
//! #
89
//! // Reconfigure the driver to use async mode.
90
//! let mut i2c = i2c.into_async();
91
//!
92
//! i2c.write_async(DEVICE_ADDR, &write_buffer).await?;
93
//! i2c.write_read_async(DEVICE_ADDR, &write_buffer, &mut read_buffer)
94
//!     .await?;
95
//! i2c.read_async(DEVICE_ADDR, &mut read_buffer).await?;
96
//! i2c.transaction_async(
97
//!     DEVICE_ADDR,
98
//!     &mut [
99
//!         Operation::Write(&write_buffer),
100
//!         Operation::Read(&mut read_buffer),
101
//!     ],
102
//! )
103
//! .await?;
104
//!
105
//! // You should still be able to use the blocking methods, if you need to:
106
//! i2c.write(DEVICE_ADDR, &write_buffer)?;
107
//!
108
//! # {after_snippet}
109
//! ```
110
//!
111
//! The I2C driver also implements [embedded-hal] and [embedded-hal-async]
112
//! traits, so you can use it with any crate that supports these traits.
113
//!
114
//! [embedded-hal]: embedded_hal::i2c
115
//! [embedded-hal-async]: embedded_hal_async::i2c
116

            
117
use core::{
118
    marker::PhantomData,
119
    pin::Pin,
120
    task::{Context, Poll},
121
};
122

            
123
use enumset::{EnumSet, EnumSetType};
124

            
125
use crate::{
126
    Async,
127
    Blocking,
128
    DriverMode,
129
    asynch::AtomicWaker,
130
    clock::ll::{ClockTree, I2cFunctionClockConfig},
131
    gpio::{
132
        DriveMode,
133
        InputSignal,
134
        Level,
135
        OutputConfig,
136
        OutputSignal,
137
        PinGuard,
138
        Pull,
139
        interconnect::{self, PeripheralInput, PeripheralOutput},
140
    },
141
    handler,
142
    interrupt::InterruptHandler,
143
    pac::i2c0::{COMD, RegisterBlock},
144
    private,
145
    ram,
146
    system::PeripheralGuard,
147
    time::{Duration, Instant, Rate},
148
};
149

            
150
mod eh;
151
mod low_level;
152

            
153
pub use low_level::{AnyI2c, Instance};
154
use low_level::{Driver, I2cClockGuard};
155

            
156
const I2C_FIFO_SIZE: usize = property!("i2c_master.fifo_size");
157
// Chunk writes/reads by this size
158
const I2C_CHUNK_SIZE: usize = I2C_FIFO_SIZE - 1;
159
const CLEAR_BUS_TIMEOUT_MS: Duration = Duration::from_millis(50);
160

            
161
/// Representation of I2C address.
162
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
163
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
164
#[non_exhaustive]
165
pub enum I2cAddress {
166
    /// 7-bit address mode type.
167
    ///
168
    /// 7-bit addresses are specified in **right-aligned** form, e.g. in the range
169
    /// `0x00..=0x7F`
170
    ///
171
    /// For example, a device that has the seven bit address of `0b011_0010`,
172
    /// and therefore is addressed on the wire using:
173
    ///
174
    /// * `0b0110010_0` or `0x64` for *writes*
175
    /// * `0b0110010_1` or `0x65` for *reads*
176
    ///
177
    /// The above address is specified as 0b0011_0010 or 0x32, NOT 0x64 or 0x65.
178
    SevenBit(u8),
179
}
180

            
181
impl I2cAddress {
182
    fn validate(&self) -> Result<(), Error> {
183
        match self {
184
            I2cAddress::SevenBit(addr) => {
185
3
                if *addr > 0x7F {
186
                    return Err(Error::AddressInvalid(*self));
187
                }
188
            }
189
        }
190

            
191
        Ok(())
192
    }
193

            
194
    fn bytes(self) -> usize {
195
        match self {
196
            I2cAddress::SevenBit(_) => 1,
197
        }
198
    }
199
}
200

            
201
impl From<u8> for I2cAddress {
202
    fn from(value: u8) -> Self {
203
        I2cAddress::SevenBit(value)
204
    }
205
}
206

            
207
/// I2C SCL timeout period.
208
///
209
/// When the level of SCL remains unchanged for more than `timeout` bus
210
/// clock cycles, the bus goes to idle state.
211
///
212
/// Default value is `BusCycles(10)`.
213
#[doc = ""]
214
#[cfg_attr(
215
    i2c_master_bus_timeout_is_exponential,
216
    doc = "The effective timeout may be longer than the value configured here."
217
)]
218
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, strum::Display)]
219
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
220
#[non_exhaustive]
221
#[instability::unstable]
222
pub enum BusTimeout {
223
    /// Use the maximum timeout value.
224
    Maximum,
225

            
226
    /// Disables timeout control.
227
    #[cfg(i2c_master_has_bus_timeout_enable)]
228
    Disabled,
229

            
230
    /// Timeout in bus clock cycles.
231
    BusCycles(u32),
232
}
233

            
234
impl BusTimeout {
235
    /// Returns the timeout in APB cycles, or `None` if the timeout is disabled.
236
    ///
237
    /// Newer devices only support power-of-two timeouts, so the value must be rounded to a
238
    /// power of two using the logarithm of the timeout value. This may cause considerably longer
239
    /// (at most approximately double) timeouts than configured. An `ApbCycles` variant may be
240
    /// provided in the future to allow specifying the timeout in APB cycles directly.
241
    fn apb_cycles(self, half_bus_cycle: u32) -> Result<Option<u32>, ConfigError> {
242
57
        match self {
243
            BusTimeout::Maximum => Ok(Some(property!("i2c_master.max_bus_timeout"))),
244

            
245
            #[cfg(i2c_master_has_bus_timeout_enable)]
246
57
            BusTimeout::Disabled => Ok(None),
247

            
248
            BusTimeout::BusCycles(cycles) => {
249
                let raw = if cfg!(i2c_master_bus_timeout_is_exponential) {
250
                    let to_peri = (cycles * 2 * half_bus_cycle).max(1);
251
                    let log2 = to_peri.ilog2();
252
                    // If not a power of 2, round up so that we don't shorten timeouts.
253
                    if to_peri != 1 << log2 { log2 + 1 } else { log2 }
254
                } else {
255
                    cycles * 2 * half_bus_cycle
256
                };
257

            
258
                if raw <= property!("i2c_master.max_bus_timeout") {
259
                    Ok(Some(raw))
260
                } else {
261
                    Err(ConfigError::TimeoutTooLong)
262
                }
263
            }
264
        }
265
    }
266
}
267

            
268
/// Software timeout for I2C operations.
269
///
270
/// This timeout is used to limit the duration of I2C operations in software.
271
/// Using this in conjunction with `async` operations causes the task to be woken
272
/// up continuously until the operation completes or the timeout is reached. Prefer
273
/// an asynchronous timeout mechanism (like [`embassy_time::with_timeout`]) for
274
/// better efficiency.
275
///
276
/// [`embassy_time::with_timeout`]: https://docs.rs/embassy-time/0.4.0/embassy_time/fn.with_timeout.html
277
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
278
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
279
pub enum SoftwareTimeout {
280
    /// No software timeout is set.
281
    None,
282

            
283
    /// Defines a fixed timeout for I2C operations.
284
    Transaction(Duration),
285

            
286
    /// Defines a data length dependent timeout for I2C operations.
287
    ///
288
    /// The applied timeout is calculated as `data_length * duration_per_byte`.
289
    /// In [`I2c::transaction`] and [`I2c::transaction_async`], the timeout is
290
    /// applied separately for each operation.
291
    PerByte(Duration),
292
}
293

            
294
/// When the FSM remains unchanged for more than the 2^ the given amount of bus
295
/// clock cycles a timeout will be triggered.
296
///
297
/// The default value is 23 (2^23 clock cycles).
298
#[instability::unstable]
299
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
300
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
301
#[cfg(i2c_master_has_fsm_timeouts)]
302
pub struct FsmTimeout {
303
    value: u8,
304
}
305

            
306
#[cfg(i2c_master_has_fsm_timeouts)]
307
impl FsmTimeout {
308
    const FSM_TIMEOUT_MAX: u8 = 23;
309

            
310
    /// Creates a new timeout.
311
    ///
312
    /// The meaning of the value and the allowed range of values is different
313
    /// for different chips.
314
    #[instability::unstable]
315
    pub const fn new_const<const VALUE: u8>() -> Self {
316
        const {
317
            core::assert!(VALUE <= Self::FSM_TIMEOUT_MAX, "Invalid timeout value");
318
        }
319
        Self { value: VALUE }
320
    }
321

            
322
    /// Creates a new timeout.
323
    ///
324
    /// The meaning of the value and the allowed range of values is different
325
    /// for different chips.
326
    #[instability::unstable]
327
    pub fn new(value: u8) -> Result<Self, ConfigError> {
328
        if value > Self::FSM_TIMEOUT_MAX {
329
            return Err(ConfigError::TimeoutTooLong);
330
        }
331

            
332
        Ok(Self { value })
333
    }
334

            
335
    fn value(&self) -> u8 {
336
        self.value
337
    }
338
}
339

            
340
#[cfg(i2c_master_has_fsm_timeouts)]
341
impl Default for FsmTimeout {
342
    fn default() -> Self {
343
        Self::new_const::<{ Self::FSM_TIMEOUT_MAX }>()
344
    }
345
}
346

            
347
/// I2C-specific transmission errors
348
2
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
349
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
350
#[non_exhaustive]
351
pub enum Error {
352
    /// The transmission exceeded the FIFO size.
353
    FifoExceeded,
354
    /// The acknowledgment check failed.
355
    AcknowledgeCheckFailed(AcknowledgeCheckFailedReason),
356
    /// A timeout occurred during transmission.
357
    Timeout,
358
    /// The arbitration for the bus was lost.
359
    ArbitrationLost,
360
    /// The execution of the I2C command was incomplete.
361
    ExecutionIncomplete,
362
    /// The number of commands issued exceeded the limit.
363
    CommandNumberExceeded,
364
    /// Zero length read or write operation.
365
    ZeroLengthInvalid,
366
    /// The given address is invalid.
367
    AddressInvalid(I2cAddress),
368
}
369

            
370
/// I2C no acknowledge error reason.
371
///
372
/// Consider this as a hint and make sure to always handle all cases.
373
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
374
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
375
#[non_exhaustive]
376
pub enum AcknowledgeCheckFailedReason {
377
    /// The device did not acknowledge its address. The device may be missing.
378
    Address,
379

            
380
    /// The device did not acknowledge the data. It may not be ready to process
381
    /// requests at the moment.
382
    Data,
383

            
384
    /// Either the device did not acknowledge its address or the data, but it is
385
    /// unknown which.
386
    Unknown,
387
}
388

            
389
impl core::fmt::Display for AcknowledgeCheckFailedReason {
390
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
391
        match self {
392
            AcknowledgeCheckFailedReason::Address => write!(f, "Address"),
393
            AcknowledgeCheckFailedReason::Data => write!(f, "Data"),
394
            AcknowledgeCheckFailedReason::Unknown => write!(f, "Unknown"),
395
        }
396
    }
397
}
398

            
399
impl From<&AcknowledgeCheckFailedReason> for embedded_hal::i2c::NoAcknowledgeSource {
400
    fn from(value: &AcknowledgeCheckFailedReason) -> Self {
401
        match value {
402
            AcknowledgeCheckFailedReason::Address => {
403
                embedded_hal::i2c::NoAcknowledgeSource::Address
404
            }
405
            AcknowledgeCheckFailedReason::Data => embedded_hal::i2c::NoAcknowledgeSource::Data,
406
            AcknowledgeCheckFailedReason::Unknown => {
407
                embedded_hal::i2c::NoAcknowledgeSource::Unknown
408
            }
409
        }
410
    }
411
}
412

            
413
impl core::error::Error for Error {}
414

            
415
impl core::fmt::Display for Error {
416
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
417
        match self {
418
            Error::FifoExceeded => write!(f, "The transmission exceeded the FIFO size"),
419
            Error::AcknowledgeCheckFailed(reason) => {
420
                write!(f, "The acknowledgment check failed. Reason: {reason}")
421
            }
422
            Error::Timeout => write!(f, "A timeout occurred during transmission"),
423
            Error::ArbitrationLost => write!(f, "The arbitration for the bus was lost"),
424
            Error::ExecutionIncomplete => {
425
                write!(f, "The execution of the I2C command was incomplete")
426
            }
427
            Error::CommandNumberExceeded => {
428
                write!(f, "The number of commands issued exceeded the limit")
429
            }
430
            Error::ZeroLengthInvalid => write!(f, "Zero length read or write operation"),
431
            Error::AddressInvalid(address) => {
432
                write!(f, "The given address ({address:?}) is invalid")
433
            }
434
        }
435
    }
436
}
437

            
438
/// I2C-specific configuration errors
439
#[derive(Debug, Clone, Copy, PartialEq)]
440
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
441
#[non_exhaustive]
442
pub enum ConfigError {
443
    /// Provided bus frequency is not valid for the current configuration.
444
    FrequencyOutOfRange,
445
    /// Provided timeout is not valid for the current configuration.
446
    TimeoutTooLong,
447
}
448

            
449
impl core::error::Error for ConfigError {}
450

            
451
impl core::fmt::Display for ConfigError {
452
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
453
        match self {
454
            ConfigError::FrequencyOutOfRange => write!(
455
                f,
456
                "Provided bus frequency is invalid for the current configuration"
457
            ),
458
            ConfigError::TimeoutTooLong => write!(
459
                f,
460
                "Provided timeout is invalid for the current configuration"
461
            ),
462
        }
463
    }
464
}
465

            
466
// This enum is used to keep track of the last/next operation that was/will be
467
// performed in an embedded-hal(-async) I2c::transaction. It is used to
468
// determine whether a START condition should be issued at the start of the
469
// current operation and whether a read needs an ack or a nack for the final
470
// byte.
471
#[derive(PartialEq)]
472
enum OpKind {
473
    Write,
474
    Read,
475
}
476

            
477
/// I2C operation.
478
///
479
/// Several operations can be combined as part of a transaction.
480
#[derive(Debug, PartialEq, Eq, Hash, strum::Display)]
481
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
482
pub enum Operation<'a> {
483
    /// Writes data from the provided buffer.
484
    Write(&'a [u8]),
485

            
486
    /// Reads data into the provided buffer.
487
    Read(&'a mut [u8]),
488
}
489

            
490
impl<'a, 'b> From<&'a mut embedded_hal::i2c::Operation<'b>> for Operation<'a> {
491
    fn from(value: &'a mut embedded_hal::i2c::Operation<'b>) -> Self {
492
        match value {
493
            embedded_hal::i2c::Operation::Write(buffer) => Operation::Write(buffer),
494
            embedded_hal::i2c::Operation::Read(buffer) => Operation::Read(buffer),
495
        }
496
    }
497
}
498

            
499
impl<'a, 'b> From<&'a mut Operation<'b>> for Operation<'a> {
500
    fn from(value: &'a mut Operation<'b>) -> Self {
501
115
        match value {
502
            Operation::Write(buffer) => Operation::Write(buffer),
503
            Operation::Read(buffer) => Operation::Read(buffer),
504
        }
505
    }
506
}
507

            
508
impl Operation<'_> {
509
    fn is_write(&self) -> bool {
510
        matches!(self, Operation::Write(_))
511
    }
512

            
513
    fn kind(&self) -> OpKind {
514
        match self {
515
            Operation::Write(_) => OpKind::Write,
516
            Operation::Read(_) => OpKind::Read,
517
        }
518
    }
519

            
520
    fn is_empty(&self) -> bool {
521
        match self {
522
            Operation::Write(buffer) => buffer.is_empty(),
523
            Operation::Read(buffer) => buffer.is_empty(),
524
        }
525
    }
526
}
527

            
528
/// A generic I2C Command.
529
#[derive(Debug)]
530
enum Command {
531
    Start,
532
    Stop,
533
    End,
534
    Write {
535
        /// This bit is to set an expected ACK value for the transmitter.
536
        ack_exp: Ack,
537
        /// Enables checking the ACK value received against the ack_exp value.
538
        ack_check_en: bool,
539
        /// Length of data (in bytes) to be written. The maximum length is.
540
        #[doc = property!("i2c_master.fifo_size", str)]
541
        /// , while the minimum is 1.
542
        length: u8,
543
    },
544
    Read {
545
        /// Indicates whether the receiver will send an ACK after this byte has
546
        /// been received.
547
        ack_value: Ack,
548
        /// Length of data (in bytes) to be read. The maximum length is.
549
        #[doc = property!("i2c_master.fifo_size", str)]
550
        /// , while the minimum is 1.
551
        length: u8,
552
    },
553
}
554

            
555
enum OperationType {
556
    Write = 0,
557
    Read  = 1,
558
}
559

            
560
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
561
enum Ack {
562
    Ack  = 0,
563
    Nack = 1,
564
}
565

            
566
/// Clock source for the I2C peripheral.
567
#[instability::unstable]
568
pub use crate::soc::clocks::I2cFunctionClockSclk as ClockSource;
569

            
570
/// I2C driver configuration
571
1
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, procmacros::BuilderLite)]
572
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
573
#[non_exhaustive]
574
pub struct Config {
575
    /// The I2C clock frequency.
576
    ///
577
    /// Default value: 100 kHz.
578
    frequency: Rate,
579

            
580
    /// I2C SCL timeout period.
581
    ///
582
    /// Default value:
583
    #[cfg_attr(i2c_master_has_bus_timeout_enable, doc = "disabled")]
584
    #[cfg_attr(not(i2c_master_has_bus_timeout_enable), doc = concat!(property!("i2c_master.max_bus_timeout", str), " bus cycles"))]
585
    #[builder_lite(unstable)]
586
    timeout: BusTimeout,
587

            
588
    /// Software timeout.
589
    ///
590
    /// Default value: disabled.
591
    software_timeout: SoftwareTimeout,
592

            
593
    /// Sets the threshold value for the unchanged period of the SCL_FSM.
594
    ///
595
    /// Default value: 16.
596
    #[cfg(i2c_master_has_fsm_timeouts)]
597
    #[builder_lite(unstable)]
598
    scl_st_timeout: FsmTimeout,
599

            
600
    /// Sets the threshold for the unchanged duration of the SCL_MAIN_FSM.
601
    ///
602
    /// Default value: 16.
603
    #[cfg(i2c_master_has_fsm_timeouts)]
604
    #[builder_lite(unstable)]
605
    scl_main_st_timeout: FsmTimeout,
606

            
607
    /// The clock source for the I2C peripheral.
608
    ///
609
    /// Default value: [`ClockSource::default()`].
610
    #[builder_lite(unstable)]
611
    clock_source: ClockSource,
612

            
613
    /// Selects whether the controller samples the SDA line while SCL is high or
614
    /// low.
615
    ///
616
    /// Standard I2C devices change SDA while SCL is low and hold it stable while
617
    /// SCL is high, so the line is sampled while SCL is high by default
618
    /// ([`Level::High`]).
619
    #[builder_lite(unstable)]
620
    scl_sample_level: Level,
621

            
622
    /// Enables I2C bus arbitration detection.
623
    ///
624
    /// Default value: `false`.
625
    #[cfg(i2c_master_has_arbitration_en)]
626
    #[builder_lite(unstable)]
627
    bus_arbitration: bool,
628
}
629

            
630
impl Default for Config {
631
22
    fn default() -> Self {
632
22
        Config {
633
            frequency: Rate::from_khz(100),
634

            
635
            #[cfg(i2c_master_has_bus_timeout_enable)]
636
            timeout: BusTimeout::Disabled,
637
            #[cfg(not(i2c_master_has_bus_timeout_enable))]
638
            timeout: BusTimeout::Maximum,
639

            
640
            software_timeout: SoftwareTimeout::None,
641

            
642
            #[cfg(i2c_master_has_fsm_timeouts)]
643
            scl_st_timeout: Default::default(),
644
            #[cfg(i2c_master_has_fsm_timeouts)]
645
            scl_main_st_timeout: Default::default(),
646

            
647
            clock_source: Default::default(),
648

            
649
            scl_sample_level: Level::High,
650

            
651
            #[cfg(i2c_master_has_arbitration_en)]
652
            bus_arbitration: false,
653
        }
654
22
    }
655
}
656

            
657
#[procmacros::doc_replace]
658
/// I2C driver
659
///
660
/// # Examples
661
///
662
/// ```rust, no_run
663
/// # {before_snippet}
664
/// use esp_hal::i2c::master::{Config, I2c};
665
/// # const DEVICE_ADDR: u8 = 0x77;
666
/// let mut i2c = I2c::new(peripherals.I2C0, Config::default())?
667
///     .with_sda(peripherals.GPIO1)
668
///     .with_scl(peripherals.GPIO2);
669
///
670
/// let mut data = [0u8; 22];
671
/// i2c.write_read(DEVICE_ADDR, &[0xaa], &mut data)?;
672
/// # {after_snippet}
673
/// ```
674
#[derive(Debug)]
675
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
676
pub struct I2c<'d, Dm: DriverMode> {
677
    i2c: AnyI2c<'d>,
678
    phantom: PhantomData<Dm>,
679
    guard: PeripheralGuard,
680
    config: DriverConfig,
681
}
682

            
683
#[derive(Debug)]
684
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
685
struct DriverConfig {
686
    config: Config,
687
    sda_pin: PinGuard,
688
    scl_pin: PinGuard,
689
}
690

            
691
impl<'d> I2c<'d, Blocking> {
692
    #[procmacros::doc_replace]
693
    /// Creates a new I2C instance.
694
    ///
695
    /// # Examples
696
    ///
697
    /// ```rust, no_run
698
    /// # {before_snippet}
699
    /// use esp_hal::i2c::master::{Config, I2c};
700
    /// let i2c = I2c::new(peripherals.I2C0, Config::default())?
701
    ///     .with_sda(peripherals.GPIO1)
702
    ///     .with_scl(peripherals.GPIO2);
703
    /// # {after_snippet}
704
    /// ```
705
    ///
706
    /// # Errors
707
    ///
708
    /// [`ConfigError`] when bus frequency or timeout passed in config is invalid.
709
    pub fn new(i2c: impl Instance + 'd, config: Config) -> Result<Self, ConfigError> {
710
15
        let guard = PeripheralGuard::new(i2c.info().peripheral);
711

            
712
        ClockTree::with(|clocks| {
713
            let clock = i2c.info().clock_instance;
714
15
            let config = I2cFunctionClockConfig::new(
715
                Default::default(),
716
                #[cfg(any(i2c_master_version = "3", i2c_master_version = "4"))]
717
                0,
718
            );
719
15
            clock.configure_function_clock(clocks, config);
720
        });
721

            
722
        let sda_pin = PinGuard::new_unconnected();
723
        let scl_pin = PinGuard::new_unconnected();
724

            
725
        let i2c_any = i2c.degrade();
726

            
727
15
        let i2c = I2c {
728
            i2c: i2c_any,
729
            phantom: PhantomData,
730
            guard,
731
            config: DriverConfig {
732
                config,
733
                sda_pin,
734
                scl_pin,
735
            },
736
        };
737

            
738
        // Make sure inputs are well-defined.
739
        let i2c = i2c.with_scl(crate::gpio::Level::High);
740
        let mut i2c = i2c.with_sda(crate::gpio::Level::High);
741

            
742
        i2c.apply_config(&config)?;
743

            
744
15
        Ok(i2c)
745
    }
746

            
747
    /// Reconfigures the driver to operate in [`Async`] mode.
748
    ///
749
    /// See the [`Async`] documentation for an example on how to use this
750
    /// method.
751
8
    pub fn into_async(mut self) -> I2c<'d, Async> {
752
        self.set_interrupt_handler(self.driver().info.async_handler);
753

            
754
8
        I2c {
755
            i2c: self.i2c,
756
            phantom: PhantomData,
757
8
            guard: self.guard,
758
            config: self.config,
759
        }
760
8
    }
761

            
762
    #[cfg_attr(
763
        not(multi_core),
764
        doc = "Registers an interrupt handler for the peripheral."
765
    )]
766
    #[cfg_attr(
767
        multi_core,
768
        doc = "Registers an interrupt handler for the peripheral on the current core."
769
    )]
770
    #[doc = ""]
771
    /// Replaces any previously registered interrupt handlers.
772
    ///
773
    /// The default/unhandled interrupt handler can be restored by passing
774
    /// [DEFAULT_INTERRUPT_HANDLER][crate::interrupt::DEFAULT_INTERRUPT_HANDLER].
775
    ///
776
    /// # Panics
777
    ///
778
    /// Panics if passed interrupt handler is invalid (e.g. has priority
779
    /// `None`)
780
    #[instability::unstable]
781
    pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
782
        self.i2c.set_interrupt_handler(handler);
783
    }
784

            
785
    /// Listens for the given interrupts.
786
    #[instability::unstable]
787
    pub fn listen(&mut self, interrupts: impl Into<EnumSet<Event>>) {
788
        self.i2c.info().enable_listen(interrupts.into(), true)
789
    }
790

            
791
    /// Unlistens from the given interrupts.
792
    #[instability::unstable]
793
    pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<Event>>) {
794
        self.i2c.info().enable_listen(interrupts.into(), false)
795
    }
796

            
797
    /// Returns the asserted interrupts.
798
    #[instability::unstable]
799
    pub fn interrupts(&mut self) -> EnumSet<Event> {
800
        self.i2c.info().interrupts()
801
    }
802

            
803
    /// Resets asserted interrupts.
804
    #[instability::unstable]
805
    pub fn clear_interrupts(&mut self, interrupts: EnumSet<Event>) {
806
        self.i2c.info().clear_interrupts(interrupts)
807
    }
808
}
809

            
810
impl private::Sealed for I2c<'_, Blocking> {}
811

            
812
#[instability::unstable]
813
impl crate::interrupt::InterruptConfigurable for I2c<'_, Blocking> {
814
    fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
815
        self.i2c.set_interrupt_handler(handler);
816
    }
817
}
818

            
819
#[derive(Debug, EnumSetType)]
820
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
821
#[non_exhaustive]
822
#[instability::unstable]
823
pub enum Event {
824
    /// Triggered when op_code of the master indicates an END command and an END
825
    /// condition is detected.
826
    EndDetect,
827

            
828
    /// Triggered when the I2C controller detects a STOP bit.
829
    TxComplete,
830

            
831
    /// Triggered when the TX FIFO watermark check is enabled and the TX fifo
832
    /// falls below the configured watermark.
833
    #[cfg(i2c_master_has_tx_fifo_watermark)]
834
    TxFifoWatermark,
835
}
836

            
837
impl<'d> I2c<'d, Async> {
838
    /// Reconfigures the driver to operate in [`Blocking`] mode.
839
    ///
840
    /// See the [`Blocking`] documentation for an example on how to use this
841
    /// method.
842
    pub fn into_blocking(self) -> I2c<'d, Blocking> {
843
        self.i2c.disable_peri_interrupt_on_all_cores();
844

            
845
        I2c {
846
            i2c: self.i2c,
847
            phantom: PhantomData,
848
            guard: self.guard,
849
            config: self.config,
850
        }
851
    }
852

            
853
    #[procmacros::doc_replace]
854
    /// Writes bytes to slave with given `address`.
855
    ///
856
    /// Dropping the returned Future aborts the transfer, but blocks while the
857
    /// driver finishes clearing and releasing the bus.
858
    ///
859
    /// # Examples
860
    ///
861
    /// ```rust, no_run
862
    /// # {before_snippet}
863
    /// use esp_hal::i2c::master::{Config, I2c};
864
    /// const DEVICE_ADDR: u8 = 0x77;
865
    /// let mut i2c = I2c::new(peripherals.I2C0, Config::default())?
866
    ///     .with_sda(peripherals.GPIO1)
867
    ///     .with_scl(peripherals.GPIO2)
868
    ///     .into_async();
869
    ///
870
    /// i2c.write_async(DEVICE_ADDR, &[0xaa]).await?;
871
    /// # {after_snippet}
872
    /// ```
873
    pub async fn write_async<A: Into<I2cAddress>>(
874
6
        &mut self,
875
6
        address: A,
876
6
        buffer: &[u8],
877
11
    ) -> Result<(), Error> {
878
6
        self.transaction_async(address, &mut [Operation::Write(buffer)])
879
            .await
880
    }
881

            
882
    #[procmacros::doc_replace]
883
    /// Reads enough bytes from slave with `address` to fill `buffer`.
884
    ///
885
    /// Dropping the returned Future aborts the transfer, but blocks while the
886
    /// driver finishes clearing and releasing the bus.
887
    ///
888
    /// # Examples
889
    ///
890
    /// ```rust, no_run
891
    /// # {before_snippet}
892
    /// use esp_hal::i2c::master::{Config, I2c};
893
    /// const DEVICE_ADDR: u8 = 0x77;
894
    /// let mut i2c = I2c::new(peripherals.I2C0, Config::default())?
895
    ///     .with_sda(peripherals.GPIO1)
896
    ///     .with_scl(peripherals.GPIO2)
897
    ///     .into_async();
898
    ///
899
    /// let mut data = [0u8; 22];
900
    /// i2c.read_async(DEVICE_ADDR, &mut data).await?;
901
    /// # {after_snippet}
902
    /// ```
903
    ///
904
    /// # Errors
905
    ///
906
    /// [`Error`] when the passed buffer has zero length.
907
    pub async fn read_async<A: Into<I2cAddress>>(
908
        &mut self,
909
        address: A,
910
        buffer: &mut [u8],
911
    ) -> Result<(), Error> {
912
        self.transaction_async(address, &mut [Operation::Read(buffer)])
913
            .await
914
    }
915

            
916
    #[procmacros::doc_replace]
917
    /// Writes bytes to slave with given `address` and then reads enough
918
    /// bytes to fill `buffer` *in a single transaction*.
919
    ///
920
    /// Dropping the returned Future aborts the transfer, but blocks while the
921
    /// driver finishes clearing and releasing the bus.
922
    ///
923
    /// # Examples
924
    ///
925
    /// ```rust, no_run
926
    /// # {before_snippet}
927
    /// use esp_hal::i2c::master::{Config, I2c};
928
    /// const DEVICE_ADDR: u8 = 0x77;
929
    /// let mut i2c = I2c::new(peripherals.I2C0, Config::default())?
930
    ///     .with_sda(peripherals.GPIO1)
931
    ///     .with_scl(peripherals.GPIO2)
932
    ///     .into_async();
933
    ///
934
    /// let mut data = [0u8; 22];
935
    /// i2c.write_read_async(DEVICE_ADDR, &[0xaa], &mut data)
936
    ///     .await?;
937
    /// # {after_snippet}
938
    /// ```
939
    ///
940
    /// # Errors
941
    ///
942
    /// [`Error`] when the passed buffer has zero length.
943
    pub async fn write_read_async<A: Into<I2cAddress>>(
944
1
        &mut self,
945
1
        address: A,
946
1
        write_buffer: &[u8],
947
1
        read_buffer: &mut [u8],
948
200
    ) -> Result<(), Error> {
949
100
        self.transaction_async(
950
            address,
951
100
            &mut [Operation::Write(write_buffer), Operation::Read(read_buffer)],
952
        )
953
300
        .await
954
100
    }
955

            
956
    #[procmacros::doc_replace]
957
    /// Executes the provided operations on the I2C bus as a single transaction.
958
    ///
959
    /// Dropping the returned Future aborts the transfer, but blocks while the
960
    /// driver finishes clearing and releasing the bus.
961
    ///
962
    /// Transaction contract:
963
    /// - Before executing the first operation an ST is sent automatically. This is followed by
964
    ///   SAD+R/W as appropriate.
965
    /// - Data from adjacent operations of the same type are sent after each other without an SP or
966
    ///   SR.
967
    /// - Between adjacent operations of a different type an SR and SAD+R/W is sent.
968
    /// - After executing the last operation an SP is sent automatically.
969
    /// - If the last operation is a `Read` the master does not send an acknowledge for the last
970
    ///   byte.
971
    ///
972
    /// - `ST` = start condition
973
    /// - `SAD+R/W` = slave address followed by bit 1 to indicate reading or 0 to indicate writing
974
    /// - `SR` = repeated start condition
975
    /// - `SP` = stop condition
976
    #[cfg_attr(
977
        any(esp32, esp32s2),
978
        doc = "\n\nOn ESP32 and ESP32-S2 there might be issues combining large read/write operations with small (<3 bytes) read/write operations.\n\n"
979
    )]
980
    /// # Examples
981
    ///
982
    /// ```rust, no_run
983
    /// # {before_snippet}
984
    /// use esp_hal::i2c::master::{Config, I2c, Operation};
985
    /// const DEVICE_ADDR: u8 = 0x77;
986
    /// let mut i2c = I2c::new(peripherals.I2C0, Config::default())?
987
    ///     .with_sda(peripherals.GPIO1)
988
    ///     .with_scl(peripherals.GPIO2)
989
    ///     .into_async();
990
    ///
991
    /// let mut data = [0u8; 22];
992
    /// i2c.transaction_async(
993
    ///     DEVICE_ADDR,
994
    ///     &mut [Operation::Write(&[0xaa]), Operation::Read(&mut data)],
995
    /// )
996
    /// .await?;
997
    /// # {after_snippet}
998
    /// ```
999
    ///
    /// # Errors
    ///
    /// [`Error`] when the buffer passed to an [`Operation`] has zero length.
    pub async fn transaction_async<'a, A: Into<I2cAddress>>(
109
        &mut self,
109
        address: A,
109
        operations: impl IntoIterator<Item = &'a mut Operation<'a>>,
383
    ) -> Result<(), Error> {
109
        let _clock_guard = I2cClockGuard::new(self.i2c.reborrow());
109
        self.driver()
            .transaction_impl_async(address.into(), operations.into_iter().map(Operation::from))
383
            .await
2
            .inspect_err(|error| self.internal_recover(error))
    }
}
impl<'d, Dm> I2c<'d, Dm>
where
    Dm: DriverMode,
{
    fn driver(&self) -> Driver<'_> {
109
        Driver {
            info: self.i2c.info(),
            state: self.i2c.state(),
            config: &self.config,
        }
    }
    fn internal_recover(&self, error: &Error) {
        // Timeout errors mean our hardware is (possibly) working when it gets reset. Clear the bus
        // in this case, to prevent leaving the I2C device mid-transfer.
2
        self.driver().reset_fsm(*error == Error::Timeout)
    }
    #[procmacros::doc_replace]
    /// Connects a pin to the I2C SDA signal.
    ///
    /// If called with a pin singleton (e.g. `GPIO2`), the pin is configured to use
    /// the internal pull-up resistor. If that is undesired, call this method with a
    /// fully configured [`Flex`][crate::gpio::Flex] pin driver. With `Flex`, the I2C
    /// driver does not change the pin configuration.
    ///
    /// This will replace previous pin assignments for this signal.
    ///
    /// # Examples
    ///
    /// Basic usage
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::i2c::master::{Config, I2c};
    ///
    /// let i2c = I2c::new(peripherals.I2C0, Config::default())?.with_sda(peripherals.GPIO2);
    /// # {after_snippet}
    /// ```
    ///
    /// Using `Flex` to configure the pin
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::{
    ///     gpio::{DriveMode, Flex, OutputConfig},
    ///     i2c::master::{Config, I2c},
    /// };
    ///
    /// let mut sda = Flex::new(peripherals.GPIO2);
    ///
    /// // The default pullup setting is `Pull::None`.
    /// sda.apply_output_config(&OutputConfig::default().with_drive_mode(DriveMode::OpenDrain));
    /// sda.set_input_enable(true);
    /// sda.set_output_enable(true);
    /// // Initial pin state to avoid the pin to go low during peripheral configuration.
    /// sda.set_high();
    ///
    /// let i2c = I2c::new(peripherals.I2C0, Config::default())?.with_sda(sda);
    /// # {after_snippet}
    /// ```
    pub fn with_sda(mut self, sda: impl PeripheralInput<'d> + PeripheralOutput<'d>) -> Self {
        let info = self.driver().info;
15
        let input = info.sda_input;
15
        let output = info.sda_output;
15
        Driver::connect_pin(sda.into(), input, output, &mut self.config.sda_pin);
15
        self
    }
    #[procmacros::doc_replace]
    /// Connects a pin to the I2C SCL signal.
    ///
    /// If called with a pin singleton (e.g. `GPIO2`), the pin is configured to use
    /// the internal pull-up resistor. If that is undesired, call this method with a
    /// fully configured [`Flex`][crate::gpio::Flex] pin driver. With `Flex`, the I2C
    /// driver does not change the pin configuration.
    ///
    /// This will replace previous pin assignments for this signal.
    ///
    /// # Examples
    ///
    /// Basic usage
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::i2c::master::{Config, I2c};
    ///
    /// let i2c = I2c::new(peripherals.I2C0, Config::default())?.with_scl(peripherals.GPIO2);
    /// # {after_snippet}
    /// ```
    ///
    /// Using `Flex` to configure the pin
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::{
    ///     gpio::{DriveMode, Flex, OutputConfig},
    ///     i2c::master::{Config, I2c},
    /// };
    ///
    /// let mut scl = Flex::new(peripherals.GPIO2);
    ///
    /// // The default pullup setting is `Pull::None`.
    /// scl.apply_output_config(&OutputConfig::default().with_drive_mode(DriveMode::OpenDrain));
    /// scl.set_input_enable(true);
    /// scl.set_output_enable(true);
    /// // Initial pin state to avoid the pin to go low during peripheral configuration.
    /// scl.set_high();
    ///
    /// let i2c = I2c::new(peripherals.I2C0, Config::default())?.with_scl(scl);
    /// # {after_snippet}
    /// ```
    pub fn with_scl(mut self, scl: impl PeripheralInput<'d> + PeripheralOutput<'d>) -> Self {
        let info = self.driver().info;
15
        let input = info.scl_input;
15
        let output = info.scl_output;
15
        Driver::connect_pin(scl.into(), input, output, &mut self.config.scl_pin);
15
        self
    }
    #[procmacros::doc_replace]
    /// Writes bytes to slave with given `address`.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::i2c::master::{Config, I2c};
    /// # let mut i2c = I2c::new(
    /// #   peripherals.I2C0,
    /// #   Config::default(),
    /// # )?;
    /// # const DEVICE_ADDR: u8 = 0x77;
    /// i2c.write(DEVICE_ADDR, &[0xaa])?;
    /// # {after_snippet}
    /// ```
    pub fn write<A: Into<I2cAddress>>(&mut self, address: A, buffer: &[u8]) -> Result<(), Error> {
1
        self.transaction(address, &mut [Operation::Write(buffer)])
    }
    #[procmacros::doc_replace]
    /// Reads enough bytes from slave with `address` to fill `buffer`.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::i2c::master::{Config, I2c};
    /// # let mut i2c = I2c::new(
    /// #   peripherals.I2C0,
    /// #   Config::default(),
    /// # )?;
    /// # const DEVICE_ADDR: u8 = 0x77;
    /// let mut data = [0u8; 22];
    /// i2c.read(DEVICE_ADDR, &mut data)?;
    /// # {after_snippet}
    /// ```
    ///
    /// # Errors
    ///
    /// [`Error`] when the passed buffer has zero length.
    pub fn read<A: Into<I2cAddress>>(
        &mut self,
        address: A,
        buffer: &mut [u8],
    ) -> Result<(), Error> {
        self.transaction(address, &mut [Operation::Read(buffer)])
    }
    #[procmacros::doc_replace]
    /// Writes bytes to slave with given `address` and then reads enough bytes
    /// to fill `buffer` *in a single transaction*.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::i2c::master::{Config, I2c};
    /// # let mut i2c = I2c::new(
    /// #   peripherals.I2C0,
    /// #   Config::default(),
    /// # )?;
    /// # const DEVICE_ADDR: u8 = 0x77;
    /// let mut data = [0u8; 22];
    /// i2c.write_read(DEVICE_ADDR, &[0xaa], &mut data)?;
    /// # {after_snippet}
    /// ```
    ///
    /// # Errors
    ///
    /// [`Error`] when the passed buffer has zero length.
2
    pub fn write_read<A: Into<I2cAddress>>(
        &mut self,
        address: A,
        write_buffer: &[u8],
        read_buffer: &mut [u8],
    ) -> Result<(), Error> {
        self.transaction(
            address,
2
            &mut [Operation::Write(write_buffer), Operation::Read(read_buffer)],
        )
2
    }
    #[procmacros::doc_replace]
    /// Executes the provided operations on the I2C bus.
    ///
    /// Transaction contract:
    /// - Before executing the first operation an ST is sent automatically. This is followed by
    ///   SAD+R/W as appropriate.
    /// - Data from adjacent operations of the same type are sent after each other without an SP or
    ///   SR.
    /// - Between adjacent operations of a different type an SR and SAD+R/W is sent.
    /// - After executing the last operation an SP is sent automatically.
    /// - If the last operation is a `Read` the master does not send an acknowledge for the last
    ///   byte.
    ///
    /// - `ST` = start condition
    /// - `SAD+R/W` = slave address followed by bit 1 to indicate reading or 0 to indicate writing
    /// - `SR` = repeated start condition
    /// - `SP` = stop condition
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::i2c::master::{Config, I2c, Operation};
    /// # let mut i2c = I2c::new(
    /// #   peripherals.I2C0,
    /// #   Config::default(),
    /// # )?;
    /// # const DEVICE_ADDR: u8 = 0x77;
    /// let mut data = [0u8; 22];
    /// i2c.transaction(
    ///     DEVICE_ADDR,
    ///     &mut [Operation::Write(&[0xaa]), Operation::Read(&mut data)],
    /// )?;
    /// # {after_snippet}
    /// ```
    #[cfg_attr(
        any(esp32, esp32s2),
        doc = "\n\nOn ESP32 and ESP32-S2 it is advisable to not combine large read/write operations with small (<3 bytes) read/write operations.\n\n"
    )]
    /// # Errors
    ///
    /// [`Error`] when the buffer passed to an [`Operation`] has zero length.
    pub fn transaction<'a, A: Into<I2cAddress>>(
        &mut self,
        address: A,
        operations: impl IntoIterator<Item = &'a mut Operation<'a>>,
    ) -> Result<(), Error> {
2
        let _clock_guard = I2cClockGuard::new(self.i2c.reborrow());
        self.driver()
2
            .transaction_impl(address.into(), operations.into_iter().map(Operation::from))
            .inspect_err(|error| self.internal_recover(error))
    }
    #[procmacros::doc_replace]
    /// Applies a new configuration.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::i2c::master::{Config, I2c};
    /// let mut i2c = I2c::new(peripherals.I2C0, Config::default())?;
    ///
    /// i2c.apply_config(&Config::default().with_frequency(Rate::from_khz(400)))?;
    /// # {after_snippet}
    /// ```
    ///
    /// # Errors
    ///
    /// [`ConfigError`] when bus frequency or timeout passed in config is invalid.
    pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
15
        self.config.config = *config;
15
        self.driver().setup(config)?;
15
        self.driver().reset_fsm(false);
        Ok(())
    }
    /// Drives SCL low (`true`) or releases it (`false`).
    ///
    /// Forcing a line low interrupts normal peripheral operation — no
    /// transactions should be started while a line is held low.
    #[instability::unstable]
    pub fn force_scl_low(&mut self, low: bool) {
1
        self.driver().force_scl_low(low);
    }
    /// Drives SDA low (`true`) or releases it (`false`).
    ///
    /// Forcing a line low interrupts normal peripheral operation — no
    /// transactions should be started while a line is held low.
    #[instability::unstable]
    pub fn force_sda_low(&mut self, low: bool) {
1
        self.driver().force_sda_low(low);
    }
}