Merge pull request #2304 from embassy-rs/stm32-docs
stm32/i2c: remove _timeout public API, share more code between v1/v2.
This commit is contained in:
		@@ -1,17 +1,23 @@
 | 
				
			|||||||
#![macro_use]
 | 
					#![macro_use]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use core::marker::PhantomData;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use crate::dma::NoDma;
 | 
					 | 
				
			||||||
use crate::interrupt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[cfg_attr(i2c_v1, path = "v1.rs")]
 | 
					#[cfg_attr(i2c_v1, path = "v1.rs")]
 | 
				
			||||||
#[cfg_attr(i2c_v2, path = "v2.rs")]
 | 
					#[cfg_attr(i2c_v2, path = "v2.rs")]
 | 
				
			||||||
mod _version;
 | 
					mod _version;
 | 
				
			||||||
pub use _version::*;
 | 
					 | 
				
			||||||
use embassy_sync::waitqueue::AtomicWaker;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::peripherals;
 | 
					use core::future::Future;
 | 
				
			||||||
 | 
					use core::marker::PhantomData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
 | 
				
			||||||
 | 
					use embassy_sync::waitqueue::AtomicWaker;
 | 
				
			||||||
 | 
					#[cfg(feature = "time")]
 | 
				
			||||||
 | 
					use embassy_time::{Duration, Instant};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::dma::NoDma;
 | 
				
			||||||
 | 
					use crate::gpio::sealed::AFType;
 | 
				
			||||||
 | 
					use crate::gpio::Pull;
 | 
				
			||||||
 | 
					use crate::interrupt::typelevel::Interrupt;
 | 
				
			||||||
 | 
					use crate::time::Hertz;
 | 
				
			||||||
 | 
					use crate::{interrupt, peripherals};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// I2C error.
 | 
					/// I2C error.
 | 
				
			||||||
#[derive(Debug, PartialEq, Eq)]
 | 
					#[derive(Debug, PartialEq, Eq)]
 | 
				
			||||||
@@ -33,6 +39,148 @@ pub enum Error {
 | 
				
			|||||||
    ZeroLengthTransfer,
 | 
					    ZeroLengthTransfer,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// I2C config
 | 
				
			||||||
 | 
					#[non_exhaustive]
 | 
				
			||||||
 | 
					#[derive(Copy, Clone)]
 | 
				
			||||||
 | 
					pub struct Config {
 | 
				
			||||||
 | 
					    /// Enable internal pullup on SDA.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// Using external pullup resistors is recommended for I2C. If you do
 | 
				
			||||||
 | 
					    /// have external pullups you should not enable this.
 | 
				
			||||||
 | 
					    pub sda_pullup: bool,
 | 
				
			||||||
 | 
					    /// Enable internal pullup on SCL.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// Using external pullup resistors is recommended for I2C. If you do
 | 
				
			||||||
 | 
					    /// have external pullups you should not enable this.
 | 
				
			||||||
 | 
					    pub scl_pullup: bool,
 | 
				
			||||||
 | 
					    /// Timeout.
 | 
				
			||||||
 | 
					    #[cfg(feature = "time")]
 | 
				
			||||||
 | 
					    pub timeout: embassy_time::Duration,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Default for Config {
 | 
				
			||||||
 | 
					    fn default() -> Self {
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            sda_pullup: false,
 | 
				
			||||||
 | 
					            scl_pullup: false,
 | 
				
			||||||
 | 
					            #[cfg(feature = "time")]
 | 
				
			||||||
 | 
					            timeout: embassy_time::Duration::from_millis(1000),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// I2C driver.
 | 
				
			||||||
 | 
					pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
 | 
				
			||||||
 | 
					    _peri: PeripheralRef<'d, T>,
 | 
				
			||||||
 | 
					    #[allow(dead_code)]
 | 
				
			||||||
 | 
					    tx_dma: PeripheralRef<'d, TXDMA>,
 | 
				
			||||||
 | 
					    #[allow(dead_code)]
 | 
				
			||||||
 | 
					    rx_dma: PeripheralRef<'d, RXDMA>,
 | 
				
			||||||
 | 
					    #[cfg(feature = "time")]
 | 
				
			||||||
 | 
					    timeout: Duration,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			||||||
 | 
					    /// Create a new I2C driver.
 | 
				
			||||||
 | 
					    pub fn new(
 | 
				
			||||||
 | 
					        peri: impl Peripheral<P = T> + 'd,
 | 
				
			||||||
 | 
					        scl: impl Peripheral<P = impl SclPin<T>> + 'd,
 | 
				
			||||||
 | 
					        sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
 | 
				
			||||||
 | 
					        _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>>
 | 
				
			||||||
 | 
					            + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>>
 | 
				
			||||||
 | 
					            + 'd,
 | 
				
			||||||
 | 
					        tx_dma: impl Peripheral<P = TXDMA> + 'd,
 | 
				
			||||||
 | 
					        rx_dma: impl Peripheral<P = RXDMA> + 'd,
 | 
				
			||||||
 | 
					        freq: Hertz,
 | 
				
			||||||
 | 
					        config: Config,
 | 
				
			||||||
 | 
					    ) -> Self {
 | 
				
			||||||
 | 
					        into_ref!(peri, scl, sda, tx_dma, rx_dma);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        T::enable_and_reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        scl.set_as_af_pull(
 | 
				
			||||||
 | 
					            scl.af_num(),
 | 
				
			||||||
 | 
					            AFType::OutputOpenDrain,
 | 
				
			||||||
 | 
					            match config.scl_pullup {
 | 
				
			||||||
 | 
					                true => Pull::Up,
 | 
				
			||||||
 | 
					                false => Pull::None,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        sda.set_as_af_pull(
 | 
				
			||||||
 | 
					            sda.af_num(),
 | 
				
			||||||
 | 
					            AFType::OutputOpenDrain,
 | 
				
			||||||
 | 
					            match config.sda_pullup {
 | 
				
			||||||
 | 
					                true => Pull::Up,
 | 
				
			||||||
 | 
					                false => Pull::None,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        unsafe { T::EventInterrupt::enable() };
 | 
				
			||||||
 | 
					        unsafe { T::ErrorInterrupt::enable() };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut this = Self {
 | 
				
			||||||
 | 
					            _peri: peri,
 | 
				
			||||||
 | 
					            tx_dma,
 | 
				
			||||||
 | 
					            rx_dma,
 | 
				
			||||||
 | 
					            #[cfg(feature = "time")]
 | 
				
			||||||
 | 
					            timeout: config.timeout,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.init(freq, config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn timeout(&self) -> Timeout {
 | 
				
			||||||
 | 
					        Timeout {
 | 
				
			||||||
 | 
					            #[cfg(feature = "time")]
 | 
				
			||||||
 | 
					            deadline: Instant::now() + self.timeout,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Copy, Clone)]
 | 
				
			||||||
 | 
					struct Timeout {
 | 
				
			||||||
 | 
					    #[cfg(feature = "time")]
 | 
				
			||||||
 | 
					    deadline: Instant,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[allow(dead_code)]
 | 
				
			||||||
 | 
					impl Timeout {
 | 
				
			||||||
 | 
					    #[cfg(not(feature = "time"))]
 | 
				
			||||||
 | 
					    #[inline]
 | 
				
			||||||
 | 
					    fn check(self) -> Result<(), Error> {
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[cfg(feature = "time")]
 | 
				
			||||||
 | 
					    #[inline]
 | 
				
			||||||
 | 
					    fn check(self) -> Result<(), Error> {
 | 
				
			||||||
 | 
					        if Instant::now() > self.deadline {
 | 
				
			||||||
 | 
					            Err(Error::Timeout)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Ok(())
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[cfg(not(feature = "time"))]
 | 
				
			||||||
 | 
					    #[inline]
 | 
				
			||||||
 | 
					    fn with<R>(self, fut: impl Future<Output = Result<R, Error>>) -> impl Future<Output = Result<R, Error>> {
 | 
				
			||||||
 | 
					        fut
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[cfg(feature = "time")]
 | 
				
			||||||
 | 
					    #[inline]
 | 
				
			||||||
 | 
					    fn with<R>(self, fut: impl Future<Output = Result<R, Error>>) -> impl Future<Output = Result<R, Error>> {
 | 
				
			||||||
 | 
					        use futures::FutureExt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        embassy_futures::select::select(embassy_time::Timer::at(self.deadline), fut).map(|r| match r {
 | 
				
			||||||
 | 
					            embassy_futures::select::Either::First(_) => Err(Error::Timeout),
 | 
				
			||||||
 | 
					            embassy_futures::select::Either::Second(r) => r,
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub(crate) mod sealed {
 | 
					pub(crate) mod sealed {
 | 
				
			||||||
    use super::*;
 | 
					    use super::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,20 +1,14 @@
 | 
				
			|||||||
use core::future::poll_fn;
 | 
					use core::future::poll_fn;
 | 
				
			||||||
use core::marker::PhantomData;
 | 
					 | 
				
			||||||
use core::task::Poll;
 | 
					use core::task::Poll;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use embassy_embedded_hal::SetConfig;
 | 
					use embassy_embedded_hal::SetConfig;
 | 
				
			||||||
use embassy_futures::select::{select, Either};
 | 
					use embassy_futures::select::{select, Either};
 | 
				
			||||||
use embassy_hal_internal::drop::OnDrop;
 | 
					use embassy_hal_internal::drop::OnDrop;
 | 
				
			||||||
use embassy_hal_internal::{into_ref, PeripheralRef};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
use super::*;
 | 
					use super::*;
 | 
				
			||||||
use crate::dma::{NoDma, Transfer};
 | 
					use crate::dma::Transfer;
 | 
				
			||||||
use crate::gpio::sealed::AFType;
 | 
					 | 
				
			||||||
use crate::gpio::Pull;
 | 
					 | 
				
			||||||
use crate::interrupt::typelevel::Interrupt;
 | 
					 | 
				
			||||||
use crate::pac::i2c;
 | 
					use crate::pac::i2c;
 | 
				
			||||||
use crate::time::Hertz;
 | 
					use crate::time::Hertz;
 | 
				
			||||||
use crate::{interrupt, Peripheral};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub unsafe fn on_interrupt<T: Instance>() {
 | 
					pub unsafe fn on_interrupt<T: Instance>() {
 | 
				
			||||||
    let regs = T::regs();
 | 
					    let regs = T::regs();
 | 
				
			||||||
@@ -30,55 +24,8 @@ pub unsafe fn on_interrupt<T: Instance>() {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[non_exhaustive]
 | 
					 | 
				
			||||||
#[derive(Copy, Clone, Default)]
 | 
					 | 
				
			||||||
pub struct Config {
 | 
					 | 
				
			||||||
    pub sda_pullup: bool,
 | 
					 | 
				
			||||||
    pub scl_pullup: bool,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
 | 
					 | 
				
			||||||
    phantom: PhantomData<&'d mut T>,
 | 
					 | 
				
			||||||
    #[allow(dead_code)]
 | 
					 | 
				
			||||||
    tx_dma: PeripheralRef<'d, TXDMA>,
 | 
					 | 
				
			||||||
    #[allow(dead_code)]
 | 
					 | 
				
			||||||
    rx_dma: PeripheralRef<'d, RXDMA>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
					impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			||||||
    pub fn new(
 | 
					    pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
 | 
				
			||||||
        _peri: impl Peripheral<P = T> + 'd,
 | 
					 | 
				
			||||||
        scl: impl Peripheral<P = impl SclPin<T>> + 'd,
 | 
					 | 
				
			||||||
        sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
 | 
					 | 
				
			||||||
        _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>>
 | 
					 | 
				
			||||||
            + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>>
 | 
					 | 
				
			||||||
            + 'd,
 | 
					 | 
				
			||||||
        tx_dma: impl Peripheral<P = TXDMA> + 'd,
 | 
					 | 
				
			||||||
        rx_dma: impl Peripheral<P = RXDMA> + 'd,
 | 
					 | 
				
			||||||
        freq: Hertz,
 | 
					 | 
				
			||||||
        config: Config,
 | 
					 | 
				
			||||||
    ) -> Self {
 | 
					 | 
				
			||||||
        into_ref!(scl, sda, tx_dma, rx_dma);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        T::enable_and_reset();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        scl.set_as_af_pull(
 | 
					 | 
				
			||||||
            scl.af_num(),
 | 
					 | 
				
			||||||
            AFType::OutputOpenDrain,
 | 
					 | 
				
			||||||
            match config.scl_pullup {
 | 
					 | 
				
			||||||
                true => Pull::Up,
 | 
					 | 
				
			||||||
                false => Pull::None,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        sda.set_as_af_pull(
 | 
					 | 
				
			||||||
            sda.af_num(),
 | 
					 | 
				
			||||||
            AFType::OutputOpenDrain,
 | 
					 | 
				
			||||||
            match config.sda_pullup {
 | 
					 | 
				
			||||||
                true => Pull::Up,
 | 
					 | 
				
			||||||
                false => Pull::None,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        T::regs().cr1().modify(|reg| {
 | 
					        T::regs().cr1().modify(|reg| {
 | 
				
			||||||
            reg.set_pe(false);
 | 
					            reg.set_pe(false);
 | 
				
			||||||
            //reg.set_anfoff(false);
 | 
					            //reg.set_anfoff(false);
 | 
				
			||||||
@@ -101,15 +48,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
        T::regs().cr1().modify(|reg| {
 | 
					        T::regs().cr1().modify(|reg| {
 | 
				
			||||||
            reg.set_pe(true);
 | 
					            reg.set_pe(true);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					 | 
				
			||||||
        unsafe { T::EventInterrupt::enable() };
 | 
					 | 
				
			||||||
        unsafe { T::ErrorInterrupt::enable() };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Self {
 | 
					 | 
				
			||||||
            phantom: PhantomData,
 | 
					 | 
				
			||||||
            tx_dma,
 | 
					 | 
				
			||||||
            rx_dma,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn check_and_clear_error_flags() -> Result<i2c::regs::Sr1, Error> {
 | 
					    fn check_and_clear_error_flags() -> Result<i2c::regs::Sr1, Error> {
 | 
				
			||||||
@@ -169,12 +107,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
        Ok(sr1)
 | 
					        Ok(sr1)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn write_bytes(
 | 
					    fn write_bytes(&mut self, addr: u8, bytes: &[u8], timeout: Timeout) -> Result<(), Error> {
 | 
				
			||||||
        &mut self,
 | 
					 | 
				
			||||||
        addr: u8,
 | 
					 | 
				
			||||||
        bytes: &[u8],
 | 
					 | 
				
			||||||
        check_timeout: impl Fn() -> Result<(), Error>,
 | 
					 | 
				
			||||||
    ) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        // Send a START condition
 | 
					        // Send a START condition
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        T::regs().cr1().modify(|reg| {
 | 
					        T::regs().cr1().modify(|reg| {
 | 
				
			||||||
@@ -183,7 +116,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Wait until START condition was generated
 | 
					        // Wait until START condition was generated
 | 
				
			||||||
        while !Self::check_and_clear_error_flags()?.start() {
 | 
					        while !Self::check_and_clear_error_flags()?.start() {
 | 
				
			||||||
            check_timeout()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Also wait until signalled we're master and everything is waiting for us
 | 
					        // Also wait until signalled we're master and everything is waiting for us
 | 
				
			||||||
@@ -193,7 +126,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
            let sr2 = T::regs().sr2().read();
 | 
					            let sr2 = T::regs().sr2().read();
 | 
				
			||||||
            !sr2.msl() && !sr2.busy()
 | 
					            !sr2.msl() && !sr2.busy()
 | 
				
			||||||
        } {
 | 
					        } {
 | 
				
			||||||
            check_timeout()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Set up current address, we're trying to talk to
 | 
					        // Set up current address, we're trying to talk to
 | 
				
			||||||
@@ -203,7 +136,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
        // Wait for the address to be acknowledged
 | 
					        // Wait for the address to be acknowledged
 | 
				
			||||||
        // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set.
 | 
					        // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set.
 | 
				
			||||||
        while !Self::check_and_clear_error_flags()?.addr() {
 | 
					        while !Self::check_and_clear_error_flags()?.addr() {
 | 
				
			||||||
            check_timeout()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Clear condition by reading SR2
 | 
					        // Clear condition by reading SR2
 | 
				
			||||||
@@ -211,20 +144,20 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Send bytes
 | 
					        // Send bytes
 | 
				
			||||||
        for c in bytes {
 | 
					        for c in bytes {
 | 
				
			||||||
            self.send_byte(*c, &check_timeout)?;
 | 
					            self.send_byte(*c, timeout)?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Fallthrough is success
 | 
					        // Fallthrough is success
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn send_byte(&self, byte: u8, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
 | 
					    fn send_byte(&self, byte: u8, timeout: Timeout) -> Result<(), Error> {
 | 
				
			||||||
        // Wait until we're ready for sending
 | 
					        // Wait until we're ready for sending
 | 
				
			||||||
        while {
 | 
					        while {
 | 
				
			||||||
            // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set.
 | 
					            // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set.
 | 
				
			||||||
            !Self::check_and_clear_error_flags()?.txe()
 | 
					            !Self::check_and_clear_error_flags()?.txe()
 | 
				
			||||||
        } {
 | 
					        } {
 | 
				
			||||||
            check_timeout()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Push out a byte of data
 | 
					        // Push out a byte of data
 | 
				
			||||||
@@ -235,32 +168,27 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
            // Check for any potential error conditions.
 | 
					            // Check for any potential error conditions.
 | 
				
			||||||
            !Self::check_and_clear_error_flags()?.btf()
 | 
					            !Self::check_and_clear_error_flags()?.btf()
 | 
				
			||||||
        } {
 | 
					        } {
 | 
				
			||||||
            check_timeout()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn recv_byte(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<u8, Error> {
 | 
					    fn recv_byte(&self, timeout: Timeout) -> Result<u8, Error> {
 | 
				
			||||||
        while {
 | 
					        while {
 | 
				
			||||||
            // Check for any potential error conditions.
 | 
					            // Check for any potential error conditions.
 | 
				
			||||||
            Self::check_and_clear_error_flags()?;
 | 
					            Self::check_and_clear_error_flags()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            !T::regs().sr1().read().rxne()
 | 
					            !T::regs().sr1().read().rxne()
 | 
				
			||||||
        } {
 | 
					        } {
 | 
				
			||||||
            check_timeout()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let value = T::regs().dr().read().dr();
 | 
					        let value = T::regs().dr().read().dr();
 | 
				
			||||||
        Ok(value)
 | 
					        Ok(value)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn blocking_read_timeout(
 | 
					    fn blocking_read_timeout(&mut self, addr: u8, buffer: &mut [u8], timeout: Timeout) -> Result<(), Error> {
 | 
				
			||||||
        &mut self,
 | 
					 | 
				
			||||||
        addr: u8,
 | 
					 | 
				
			||||||
        buffer: &mut [u8],
 | 
					 | 
				
			||||||
        check_timeout: impl Fn() -> Result<(), Error>,
 | 
					 | 
				
			||||||
    ) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        if let Some((last, buffer)) = buffer.split_last_mut() {
 | 
					        if let Some((last, buffer)) = buffer.split_last_mut() {
 | 
				
			||||||
            // Send a START condition and set ACK bit
 | 
					            // Send a START condition and set ACK bit
 | 
				
			||||||
            T::regs().cr1().modify(|reg| {
 | 
					            T::regs().cr1().modify(|reg| {
 | 
				
			||||||
@@ -270,7 +198,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            // Wait until START condition was generated
 | 
					            // Wait until START condition was generated
 | 
				
			||||||
            while !Self::check_and_clear_error_flags()?.start() {
 | 
					            while !Self::check_and_clear_error_flags()?.start() {
 | 
				
			||||||
                check_timeout()?;
 | 
					                timeout.check()?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Also wait until signalled we're master and everything is waiting for us
 | 
					            // Also wait until signalled we're master and everything is waiting for us
 | 
				
			||||||
@@ -278,7 +206,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
                let sr2 = T::regs().sr2().read();
 | 
					                let sr2 = T::regs().sr2().read();
 | 
				
			||||||
                !sr2.msl() && !sr2.busy()
 | 
					                !sr2.msl() && !sr2.busy()
 | 
				
			||||||
            } {
 | 
					            } {
 | 
				
			||||||
                check_timeout()?;
 | 
					                timeout.check()?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Set up current address, we're trying to talk to
 | 
					            // Set up current address, we're trying to talk to
 | 
				
			||||||
@@ -287,7 +215,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
            // Wait until address was sent
 | 
					            // Wait until address was sent
 | 
				
			||||||
            // Wait for the address to be acknowledged
 | 
					            // Wait for the address to be acknowledged
 | 
				
			||||||
            while !Self::check_and_clear_error_flags()?.addr() {
 | 
					            while !Self::check_and_clear_error_flags()?.addr() {
 | 
				
			||||||
                check_timeout()?;
 | 
					                timeout.check()?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Clear condition by reading SR2
 | 
					            // Clear condition by reading SR2
 | 
				
			||||||
@@ -295,7 +223,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            // Receive bytes into buffer
 | 
					            // Receive bytes into buffer
 | 
				
			||||||
            for c in buffer {
 | 
					            for c in buffer {
 | 
				
			||||||
                *c = self.recv_byte(&check_timeout)?;
 | 
					                *c = self.recv_byte(timeout)?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Prepare to send NACK then STOP after next byte
 | 
					            // Prepare to send NACK then STOP after next byte
 | 
				
			||||||
@@ -305,11 +233,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Receive last byte
 | 
					            // Receive last byte
 | 
				
			||||||
            *last = self.recv_byte(&check_timeout)?;
 | 
					            *last = self.recv_byte(timeout)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Wait for the STOP to be sent.
 | 
					            // Wait for the STOP to be sent.
 | 
				
			||||||
            while T::regs().cr1().read().stop() {
 | 
					            while T::regs().cr1().read().stop() {
 | 
				
			||||||
                check_timeout()?;
 | 
					                timeout.check()?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Fallthrough is success
 | 
					            // Fallthrough is success
 | 
				
			||||||
@@ -320,48 +248,33 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> {
 | 
					    pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> {
 | 
				
			||||||
        self.blocking_read_timeout(addr, read, || Ok(()))
 | 
					        self.blocking_read_timeout(addr, read, self.timeout())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn blocking_write_timeout(
 | 
					    pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> {
 | 
				
			||||||
        &mut self,
 | 
					        let timeout = self.timeout();
 | 
				
			||||||
        addr: u8,
 | 
					
 | 
				
			||||||
        write: &[u8],
 | 
					        self.write_bytes(addr, write, timeout)?;
 | 
				
			||||||
        check_timeout: impl Fn() -> Result<(), Error>,
 | 
					 | 
				
			||||||
    ) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        self.write_bytes(addr, write, &check_timeout)?;
 | 
					 | 
				
			||||||
        // Send a STOP condition
 | 
					        // Send a STOP condition
 | 
				
			||||||
        T::regs().cr1().modify(|reg| reg.set_stop(true));
 | 
					        T::regs().cr1().modify(|reg| reg.set_stop(true));
 | 
				
			||||||
        // Wait for STOP condition to transmit.
 | 
					        // Wait for STOP condition to transmit.
 | 
				
			||||||
        while T::regs().cr1().read().stop() {
 | 
					        while T::regs().cr1().read().stop() {
 | 
				
			||||||
            check_timeout()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Fallthrough is success
 | 
					        // Fallthrough is success
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> {
 | 
					    pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
 | 
				
			||||||
        self.blocking_write_timeout(addr, write, || Ok(()))
 | 
					        let timeout = self.timeout();
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn blocking_write_read_timeout(
 | 
					        self.write_bytes(addr, write, timeout)?;
 | 
				
			||||||
        &mut self,
 | 
					        self.blocking_read_timeout(addr, read, timeout)?;
 | 
				
			||||||
        addr: u8,
 | 
					 | 
				
			||||||
        write: &[u8],
 | 
					 | 
				
			||||||
        read: &mut [u8],
 | 
					 | 
				
			||||||
        check_timeout: impl Fn() -> Result<(), Error>,
 | 
					 | 
				
			||||||
    ) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        self.write_bytes(addr, write, &check_timeout)?;
 | 
					 | 
				
			||||||
        self.blocking_read_timeout(addr, read, &check_timeout)?;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        self.blocking_write_read_timeout(addr, write, read, || Ok(()))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Async
 | 
					    // Async
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[inline] // pretty sure this should always be inlined
 | 
					    #[inline] // pretty sure this should always be inlined
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,37 +4,13 @@ use core::task::Poll;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use embassy_embedded_hal::SetConfig;
 | 
					use embassy_embedded_hal::SetConfig;
 | 
				
			||||||
use embassy_hal_internal::drop::OnDrop;
 | 
					use embassy_hal_internal::drop::OnDrop;
 | 
				
			||||||
use embassy_hal_internal::{into_ref, PeripheralRef};
 | 
					 | 
				
			||||||
#[cfg(feature = "time")]
 | 
					 | 
				
			||||||
use embassy_time::{Duration, Instant};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
use super::*;
 | 
					use super::*;
 | 
				
			||||||
use crate::dma::{NoDma, Transfer};
 | 
					use crate::dma::Transfer;
 | 
				
			||||||
use crate::gpio::sealed::AFType;
 | 
					 | 
				
			||||||
use crate::gpio::Pull;
 | 
					 | 
				
			||||||
use crate::interrupt::typelevel::Interrupt;
 | 
					 | 
				
			||||||
use crate::pac::i2c;
 | 
					use crate::pac::i2c;
 | 
				
			||||||
use crate::time::Hertz;
 | 
					use crate::time::Hertz;
 | 
				
			||||||
use crate::{interrupt, Peripheral};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(feature = "time")]
 | 
					pub(crate) unsafe fn on_interrupt<T: Instance>() {
 | 
				
			||||||
fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> {
 | 
					 | 
				
			||||||
    let deadline = Instant::now() + timeout;
 | 
					 | 
				
			||||||
    move || {
 | 
					 | 
				
			||||||
        if Instant::now() > deadline {
 | 
					 | 
				
			||||||
            Err(Error::Timeout)
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            Ok(())
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[cfg(not(feature = "time"))]
 | 
					 | 
				
			||||||
pub fn no_timeout_fn() -> impl Fn() -> Result<(), Error> {
 | 
					 | 
				
			||||||
    move || Ok(())
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub unsafe fn on_interrupt<T: Instance>() {
 | 
					 | 
				
			||||||
    let regs = T::regs();
 | 
					    let regs = T::regs();
 | 
				
			||||||
    let isr = regs.isr().read();
 | 
					    let isr = regs.isr().read();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -48,70 +24,8 @@ pub unsafe fn on_interrupt<T: Instance>() {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[non_exhaustive]
 | 
					 | 
				
			||||||
#[derive(Copy, Clone)]
 | 
					 | 
				
			||||||
pub struct Config {
 | 
					 | 
				
			||||||
    pub sda_pullup: bool,
 | 
					 | 
				
			||||||
    pub scl_pullup: bool,
 | 
					 | 
				
			||||||
    #[cfg(feature = "time")]
 | 
					 | 
				
			||||||
    pub transaction_timeout: Duration,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Default for Config {
 | 
					 | 
				
			||||||
    fn default() -> Self {
 | 
					 | 
				
			||||||
        Self {
 | 
					 | 
				
			||||||
            sda_pullup: false,
 | 
					 | 
				
			||||||
            scl_pullup: false,
 | 
					 | 
				
			||||||
            #[cfg(feature = "time")]
 | 
					 | 
				
			||||||
            transaction_timeout: Duration::from_millis(100),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
 | 
					 | 
				
			||||||
    _peri: PeripheralRef<'d, T>,
 | 
					 | 
				
			||||||
    #[allow(dead_code)]
 | 
					 | 
				
			||||||
    tx_dma: PeripheralRef<'d, TXDMA>,
 | 
					 | 
				
			||||||
    #[allow(dead_code)]
 | 
					 | 
				
			||||||
    rx_dma: PeripheralRef<'d, RXDMA>,
 | 
					 | 
				
			||||||
    #[cfg(feature = "time")]
 | 
					 | 
				
			||||||
    timeout: Duration,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
					impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			||||||
    pub fn new(
 | 
					    pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
 | 
				
			||||||
        peri: impl Peripheral<P = T> + 'd,
 | 
					 | 
				
			||||||
        scl: impl Peripheral<P = impl SclPin<T>> + 'd,
 | 
					 | 
				
			||||||
        sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
 | 
					 | 
				
			||||||
        _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>>
 | 
					 | 
				
			||||||
            + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>>
 | 
					 | 
				
			||||||
            + 'd,
 | 
					 | 
				
			||||||
        tx_dma: impl Peripheral<P = TXDMA> + 'd,
 | 
					 | 
				
			||||||
        rx_dma: impl Peripheral<P = RXDMA> + 'd,
 | 
					 | 
				
			||||||
        freq: Hertz,
 | 
					 | 
				
			||||||
        config: Config,
 | 
					 | 
				
			||||||
    ) -> Self {
 | 
					 | 
				
			||||||
        into_ref!(peri, scl, sda, tx_dma, rx_dma);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        T::enable_and_reset();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        scl.set_as_af_pull(
 | 
					 | 
				
			||||||
            scl.af_num(),
 | 
					 | 
				
			||||||
            AFType::OutputOpenDrain,
 | 
					 | 
				
			||||||
            match config.scl_pullup {
 | 
					 | 
				
			||||||
                true => Pull::Up,
 | 
					 | 
				
			||||||
                false => Pull::None,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        sda.set_as_af_pull(
 | 
					 | 
				
			||||||
            sda.af_num(),
 | 
					 | 
				
			||||||
            AFType::OutputOpenDrain,
 | 
					 | 
				
			||||||
            match config.sda_pullup {
 | 
					 | 
				
			||||||
                true => Pull::Up,
 | 
					 | 
				
			||||||
                false => Pull::None,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        T::regs().cr1().modify(|reg| {
 | 
					        T::regs().cr1().modify(|reg| {
 | 
				
			||||||
            reg.set_pe(false);
 | 
					            reg.set_pe(false);
 | 
				
			||||||
            reg.set_anfoff(false);
 | 
					            reg.set_anfoff(false);
 | 
				
			||||||
@@ -130,17 +44,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
        T::regs().cr1().modify(|reg| {
 | 
					        T::regs().cr1().modify(|reg| {
 | 
				
			||||||
            reg.set_pe(true);
 | 
					            reg.set_pe(true);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					 | 
				
			||||||
        unsafe { T::EventInterrupt::enable() };
 | 
					 | 
				
			||||||
        unsafe { T::ErrorInterrupt::enable() };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Self {
 | 
					 | 
				
			||||||
            _peri: peri,
 | 
					 | 
				
			||||||
            tx_dma,
 | 
					 | 
				
			||||||
            rx_dma,
 | 
					 | 
				
			||||||
            #[cfg(feature = "time")]
 | 
					 | 
				
			||||||
            timeout: config.transaction_timeout,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn master_stop(&mut self) {
 | 
					    fn master_stop(&mut self) {
 | 
				
			||||||
@@ -153,7 +56,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
        stop: Stop,
 | 
					        stop: Stop,
 | 
				
			||||||
        reload: bool,
 | 
					        reload: bool,
 | 
				
			||||||
        restart: bool,
 | 
					        restart: bool,
 | 
				
			||||||
        check_timeout: impl Fn() -> Result<(), Error>,
 | 
					        timeout: Timeout,
 | 
				
			||||||
    ) -> Result<(), Error> {
 | 
					    ) -> Result<(), Error> {
 | 
				
			||||||
        assert!(length < 256);
 | 
					        assert!(length < 256);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -162,7 +65,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
            // automatically. This could be up to 50% of a bus
 | 
					            // automatically. This could be up to 50% of a bus
 | 
				
			||||||
            // cycle (ie. up to 0.5/freq)
 | 
					            // cycle (ie. up to 0.5/freq)
 | 
				
			||||||
            while T::regs().cr2().read().start() {
 | 
					            while T::regs().cr2().read().start() {
 | 
				
			||||||
                check_timeout()?;
 | 
					                timeout.check()?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -189,20 +92,14 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn master_write(
 | 
					    fn master_write(address: u8, length: usize, stop: Stop, reload: bool, timeout: Timeout) -> Result<(), Error> {
 | 
				
			||||||
        address: u8,
 | 
					 | 
				
			||||||
        length: usize,
 | 
					 | 
				
			||||||
        stop: Stop,
 | 
					 | 
				
			||||||
        reload: bool,
 | 
					 | 
				
			||||||
        check_timeout: impl Fn() -> Result<(), Error>,
 | 
					 | 
				
			||||||
    ) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        assert!(length < 256);
 | 
					        assert!(length < 256);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Wait for any previous address sequence to end
 | 
					        // Wait for any previous address sequence to end
 | 
				
			||||||
        // automatically. This could be up to 50% of a bus
 | 
					        // automatically. This could be up to 50% of a bus
 | 
				
			||||||
        // cycle (ie. up to 0.5/freq)
 | 
					        // cycle (ie. up to 0.5/freq)
 | 
				
			||||||
        while T::regs().cr2().read().start() {
 | 
					        while T::regs().cr2().read().start() {
 | 
				
			||||||
            check_timeout()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let reload = if reload {
 | 
					        let reload = if reload {
 | 
				
			||||||
@@ -227,15 +124,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn master_continue(
 | 
					    fn master_continue(length: usize, reload: bool, timeout: Timeout) -> Result<(), Error> {
 | 
				
			||||||
        length: usize,
 | 
					 | 
				
			||||||
        reload: bool,
 | 
					 | 
				
			||||||
        check_timeout: impl Fn() -> Result<(), Error>,
 | 
					 | 
				
			||||||
    ) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        assert!(length < 256 && length > 0);
 | 
					        assert!(length < 256 && length > 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        while !T::regs().isr().read().tcr() {
 | 
					        while !T::regs().isr().read().tcr() {
 | 
				
			||||||
            check_timeout()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let reload = if reload {
 | 
					        let reload = if reload {
 | 
				
			||||||
@@ -261,7 +154,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn wait_txe(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
 | 
					    fn wait_txe(&self, timeout: Timeout) -> Result<(), Error> {
 | 
				
			||||||
        loop {
 | 
					        loop {
 | 
				
			||||||
            let isr = T::regs().isr().read();
 | 
					            let isr = T::regs().isr().read();
 | 
				
			||||||
            if isr.txe() {
 | 
					            if isr.txe() {
 | 
				
			||||||
@@ -278,11 +171,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
                return Err(Error::Nack);
 | 
					                return Err(Error::Nack);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            check_timeout()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn wait_rxne(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
 | 
					    fn wait_rxne(&self, timeout: Timeout) -> Result<(), Error> {
 | 
				
			||||||
        loop {
 | 
					        loop {
 | 
				
			||||||
            let isr = T::regs().isr().read();
 | 
					            let isr = T::regs().isr().read();
 | 
				
			||||||
            if isr.rxne() {
 | 
					            if isr.rxne() {
 | 
				
			||||||
@@ -299,11 +192,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
                return Err(Error::Nack);
 | 
					                return Err(Error::Nack);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            check_timeout()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn wait_tc(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
 | 
					    fn wait_tc(&self, timeout: Timeout) -> Result<(), Error> {
 | 
				
			||||||
        loop {
 | 
					        loop {
 | 
				
			||||||
            let isr = T::regs().isr().read();
 | 
					            let isr = T::regs().isr().read();
 | 
				
			||||||
            if isr.tc() {
 | 
					            if isr.tc() {
 | 
				
			||||||
@@ -320,17 +213,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
                return Err(Error::Nack);
 | 
					                return Err(Error::Nack);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            check_timeout()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn read_internal(
 | 
					    fn read_internal(&mut self, address: u8, read: &mut [u8], restart: bool, timeout: Timeout) -> Result<(), Error> {
 | 
				
			||||||
        &mut self,
 | 
					 | 
				
			||||||
        address: u8,
 | 
					 | 
				
			||||||
        read: &mut [u8],
 | 
					 | 
				
			||||||
        restart: bool,
 | 
					 | 
				
			||||||
        check_timeout: impl Fn() -> Result<(), Error>,
 | 
					 | 
				
			||||||
    ) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        let completed_chunks = read.len() / 255;
 | 
					        let completed_chunks = read.len() / 255;
 | 
				
			||||||
        let total_chunks = if completed_chunks * 255 == read.len() {
 | 
					        let total_chunks = if completed_chunks * 255 == read.len() {
 | 
				
			||||||
            completed_chunks
 | 
					            completed_chunks
 | 
				
			||||||
@@ -345,17 +232,17 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
            Stop::Automatic,
 | 
					            Stop::Automatic,
 | 
				
			||||||
            last_chunk_idx != 0,
 | 
					            last_chunk_idx != 0,
 | 
				
			||||||
            restart,
 | 
					            restart,
 | 
				
			||||||
            &check_timeout,
 | 
					            timeout,
 | 
				
			||||||
        )?;
 | 
					        )?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (number, chunk) in read.chunks_mut(255).enumerate() {
 | 
					        for (number, chunk) in read.chunks_mut(255).enumerate() {
 | 
				
			||||||
            if number != 0 {
 | 
					            if number != 0 {
 | 
				
			||||||
                Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?;
 | 
					                Self::master_continue(chunk.len(), number != last_chunk_idx, timeout)?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for byte in chunk {
 | 
					            for byte in chunk {
 | 
				
			||||||
                // Wait until we have received something
 | 
					                // Wait until we have received something
 | 
				
			||||||
                self.wait_rxne(&check_timeout)?;
 | 
					                self.wait_rxne(timeout)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                *byte = T::regs().rxdr().read().rxdata();
 | 
					                *byte = T::regs().rxdr().read().rxdata();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -363,13 +250,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn write_internal(
 | 
					    fn write_internal(&mut self, address: u8, write: &[u8], send_stop: bool, timeout: Timeout) -> Result<(), Error> {
 | 
				
			||||||
        &mut self,
 | 
					 | 
				
			||||||
        address: u8,
 | 
					 | 
				
			||||||
        write: &[u8],
 | 
					 | 
				
			||||||
        send_stop: bool,
 | 
					 | 
				
			||||||
        check_timeout: impl Fn() -> Result<(), Error>,
 | 
					 | 
				
			||||||
    ) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        let completed_chunks = write.len() / 255;
 | 
					        let completed_chunks = write.len() / 255;
 | 
				
			||||||
        let total_chunks = if completed_chunks * 255 == write.len() {
 | 
					        let total_chunks = if completed_chunks * 255 == write.len() {
 | 
				
			||||||
            completed_chunks
 | 
					            completed_chunks
 | 
				
			||||||
@@ -386,7 +267,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
            write.len().min(255),
 | 
					            write.len().min(255),
 | 
				
			||||||
            Stop::Software,
 | 
					            Stop::Software,
 | 
				
			||||||
            last_chunk_idx != 0,
 | 
					            last_chunk_idx != 0,
 | 
				
			||||||
            &check_timeout,
 | 
					            timeout,
 | 
				
			||||||
        ) {
 | 
					        ) {
 | 
				
			||||||
            if send_stop {
 | 
					            if send_stop {
 | 
				
			||||||
                self.master_stop();
 | 
					                self.master_stop();
 | 
				
			||||||
@@ -396,14 +277,14 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        for (number, chunk) in write.chunks(255).enumerate() {
 | 
					        for (number, chunk) in write.chunks(255).enumerate() {
 | 
				
			||||||
            if number != 0 {
 | 
					            if number != 0 {
 | 
				
			||||||
                Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?;
 | 
					                Self::master_continue(chunk.len(), number != last_chunk_idx, timeout)?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for byte in chunk {
 | 
					            for byte in chunk {
 | 
				
			||||||
                // Wait until we are allowed to send data
 | 
					                // Wait until we are allowed to send data
 | 
				
			||||||
                // (START has been ACKed or last byte when
 | 
					                // (START has been ACKed or last byte when
 | 
				
			||||||
                // through)
 | 
					                // through)
 | 
				
			||||||
                if let Err(err) = self.wait_txe(&check_timeout) {
 | 
					                if let Err(err) = self.wait_txe(timeout) {
 | 
				
			||||||
                    if send_stop {
 | 
					                    if send_stop {
 | 
				
			||||||
                        self.master_stop();
 | 
					                        self.master_stop();
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@@ -414,7 +295,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // Wait until the write finishes
 | 
					        // Wait until the write finishes
 | 
				
			||||||
        let result = self.wait_tc(&check_timeout);
 | 
					        let result = self.wait_tc(timeout);
 | 
				
			||||||
        if send_stop {
 | 
					        if send_stop {
 | 
				
			||||||
            self.master_stop();
 | 
					            self.master_stop();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -427,7 +308,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
        write: &[u8],
 | 
					        write: &[u8],
 | 
				
			||||||
        first_slice: bool,
 | 
					        first_slice: bool,
 | 
				
			||||||
        last_slice: bool,
 | 
					        last_slice: bool,
 | 
				
			||||||
        check_timeout: impl Fn() -> Result<(), Error>,
 | 
					        timeout: Timeout,
 | 
				
			||||||
    ) -> Result<(), Error>
 | 
					    ) -> Result<(), Error>
 | 
				
			||||||
    where
 | 
					    where
 | 
				
			||||||
        TXDMA: crate::i2c::TxDma<T>,
 | 
					        TXDMA: crate::i2c::TxDma<T>,
 | 
				
			||||||
@@ -473,10 +354,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
                        total_len.min(255),
 | 
					                        total_len.min(255),
 | 
				
			||||||
                        Stop::Software,
 | 
					                        Stop::Software,
 | 
				
			||||||
                        (total_len > 255) || !last_slice,
 | 
					                        (total_len > 255) || !last_slice,
 | 
				
			||||||
                        &check_timeout,
 | 
					                        timeout,
 | 
				
			||||||
                    )?;
 | 
					                    )?;
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, &check_timeout)?;
 | 
					                    Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, timeout)?;
 | 
				
			||||||
                    T::regs().cr1().modify(|w| w.set_tcie(true));
 | 
					                    T::regs().cr1().modify(|w| w.set_tcie(true));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else if !(isr.tcr() || isr.tc()) {
 | 
					            } else if !(isr.tcr() || isr.tc()) {
 | 
				
			||||||
@@ -487,7 +368,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                let last_piece = (remaining_len <= 255) && last_slice;
 | 
					                let last_piece = (remaining_len <= 255) && last_slice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) {
 | 
					                if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, timeout) {
 | 
				
			||||||
                    return Poll::Ready(Err(e));
 | 
					                    return Poll::Ready(Err(e));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                T::regs().cr1().modify(|w| w.set_tcie(true));
 | 
					                T::regs().cr1().modify(|w| w.set_tcie(true));
 | 
				
			||||||
@@ -502,7 +383,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if last_slice {
 | 
					        if last_slice {
 | 
				
			||||||
            // This should be done already
 | 
					            // This should be done already
 | 
				
			||||||
            self.wait_tc(&check_timeout)?;
 | 
					            self.wait_tc(timeout)?;
 | 
				
			||||||
            self.master_stop();
 | 
					            self.master_stop();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -516,7 +397,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
        address: u8,
 | 
					        address: u8,
 | 
				
			||||||
        buffer: &mut [u8],
 | 
					        buffer: &mut [u8],
 | 
				
			||||||
        restart: bool,
 | 
					        restart: bool,
 | 
				
			||||||
        check_timeout: impl Fn() -> Result<(), Error>,
 | 
					        timeout: Timeout,
 | 
				
			||||||
    ) -> Result<(), Error>
 | 
					    ) -> Result<(), Error>
 | 
				
			||||||
    where
 | 
					    where
 | 
				
			||||||
        RXDMA: crate::i2c::RxDma<T>,
 | 
					        RXDMA: crate::i2c::RxDma<T>,
 | 
				
			||||||
@@ -558,7 +439,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
                    Stop::Software,
 | 
					                    Stop::Software,
 | 
				
			||||||
                    total_len > 255,
 | 
					                    total_len > 255,
 | 
				
			||||||
                    restart,
 | 
					                    restart,
 | 
				
			||||||
                    &check_timeout,
 | 
					                    timeout,
 | 
				
			||||||
                )?;
 | 
					                )?;
 | 
				
			||||||
            } else if !(isr.tcr() || isr.tc()) {
 | 
					            } else if !(isr.tcr() || isr.tc()) {
 | 
				
			||||||
                // poll_fn was woken without an interrupt present
 | 
					                // poll_fn was woken without an interrupt present
 | 
				
			||||||
@@ -568,7 +449,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                let last_piece = remaining_len <= 255;
 | 
					                let last_piece = remaining_len <= 255;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) {
 | 
					                if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, timeout) {
 | 
				
			||||||
                    return Poll::Ready(Err(e));
 | 
					                    return Poll::Ready(Err(e));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                T::regs().cr1().modify(|w| w.set_tcie(true));
 | 
					                T::regs().cr1().modify(|w| w.set_tcie(true));
 | 
				
			||||||
@@ -582,7 +463,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
        dma_transfer.await;
 | 
					        dma_transfer.await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // This should be done already
 | 
					        // This should be done already
 | 
				
			||||||
        self.wait_tc(&check_timeout)?;
 | 
					        self.wait_tc(timeout)?;
 | 
				
			||||||
        self.master_stop();
 | 
					        self.master_stop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        drop(on_drop);
 | 
					        drop(on_drop);
 | 
				
			||||||
@@ -592,41 +473,31 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // =========================
 | 
					    // =========================
 | 
				
			||||||
    //  Async public API
 | 
					    //  Async public API
 | 
				
			||||||
    #[cfg(feature = "time")]
 | 
					
 | 
				
			||||||
 | 
					    /// Write.
 | 
				
			||||||
    pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
 | 
					    pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
 | 
				
			||||||
    where
 | 
					    where
 | 
				
			||||||
        TXDMA: crate::i2c::TxDma<T>,
 | 
					        TXDMA: crate::i2c::TxDma<T>,
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        let timeout = self.timeout();
 | 
				
			||||||
        if write.is_empty() {
 | 
					        if write.is_empty() {
 | 
				
			||||||
            self.write_internal(address, write, true, timeout_fn(self.timeout))
 | 
					            self.write_internal(address, write, true, timeout)
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            embassy_time::with_timeout(
 | 
					            timeout
 | 
				
			||||||
                self.timeout,
 | 
					                .with(self.write_dma_internal(address, write, true, true, timeout))
 | 
				
			||||||
                self.write_dma_internal(address, write, true, true, timeout_fn(self.timeout)),
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
            .await
 | 
					 | 
				
			||||||
            .unwrap_or(Err(Error::Timeout))
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(not(feature = "time"))]
 | 
					 | 
				
			||||||
    pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
 | 
					 | 
				
			||||||
    where
 | 
					 | 
				
			||||||
        TXDMA: crate::i2c::TxDma<T>,
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if write.is_empty() {
 | 
					 | 
				
			||||||
            self.write_internal(address, write, true, no_timeout_fn())
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            self.write_dma_internal(address, write, true, true, no_timeout_fn())
 | 
					 | 
				
			||||||
                .await
 | 
					                .await
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[cfg(feature = "time")]
 | 
					    /// Write multiple buffers.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// The buffers are concatenated in a single write transaction.
 | 
				
			||||||
    pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error>
 | 
					    pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error>
 | 
				
			||||||
    where
 | 
					    where
 | 
				
			||||||
        TXDMA: crate::i2c::TxDma<T>,
 | 
					        TXDMA: crate::i2c::TxDma<T>,
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        let timeout = self.timeout();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if write.is_empty() {
 | 
					        if write.is_empty() {
 | 
				
			||||||
            return Err(Error::ZeroLengthTransfer);
 | 
					            return Err(Error::ZeroLengthTransfer);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -638,123 +509,49 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
            let next = iter.next();
 | 
					            let next = iter.next();
 | 
				
			||||||
            let is_last = next.is_none();
 | 
					            let is_last = next.is_none();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            embassy_time::with_timeout(
 | 
					            let fut = self.write_dma_internal(address, c, first, is_last, timeout);
 | 
				
			||||||
                self.timeout,
 | 
					            timeout.with(fut).await?;
 | 
				
			||||||
                self.write_dma_internal(address, c, first, is_last, timeout_fn(self.timeout)),
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
            .await
 | 
					 | 
				
			||||||
            .unwrap_or(Err(Error::Timeout))?;
 | 
					 | 
				
			||||||
            first = false;
 | 
					            first = false;
 | 
				
			||||||
            current = next;
 | 
					            current = next;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[cfg(not(feature = "time"))]
 | 
					    /// Read.
 | 
				
			||||||
    pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error>
 | 
					 | 
				
			||||||
    where
 | 
					 | 
				
			||||||
        TXDMA: crate::i2c::TxDma<T>,
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if write.is_empty() {
 | 
					 | 
				
			||||||
            return Err(Error::ZeroLengthTransfer);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        let mut iter = write.iter();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let mut first = true;
 | 
					 | 
				
			||||||
        let mut current = iter.next();
 | 
					 | 
				
			||||||
        while let Some(c) = current {
 | 
					 | 
				
			||||||
            let next = iter.next();
 | 
					 | 
				
			||||||
            let is_last = next.is_none();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            self.write_dma_internal(address, c, first, is_last, no_timeout_fn())
 | 
					 | 
				
			||||||
                .await?;
 | 
					 | 
				
			||||||
            first = false;
 | 
					 | 
				
			||||||
            current = next;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        Ok(())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(feature = "time")]
 | 
					 | 
				
			||||||
    pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
 | 
					    pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
 | 
				
			||||||
    where
 | 
					    where
 | 
				
			||||||
        RXDMA: crate::i2c::RxDma<T>,
 | 
					        RXDMA: crate::i2c::RxDma<T>,
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        let timeout = self.timeout();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if buffer.is_empty() {
 | 
					        if buffer.is_empty() {
 | 
				
			||||||
            self.read_internal(address, buffer, false, timeout_fn(self.timeout))
 | 
					            self.read_internal(address, buffer, false, timeout)
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            embassy_time::with_timeout(
 | 
					            let fut = self.read_dma_internal(address, buffer, false, timeout);
 | 
				
			||||||
                self.timeout,
 | 
					            timeout.with(fut).await
 | 
				
			||||||
                self.read_dma_internal(address, buffer, false, timeout_fn(self.timeout)),
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
            .await
 | 
					 | 
				
			||||||
            .unwrap_or(Err(Error::Timeout))
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[cfg(not(feature = "time"))]
 | 
					    /// Write, restart, read.
 | 
				
			||||||
    pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
 | 
					 | 
				
			||||||
    where
 | 
					 | 
				
			||||||
        RXDMA: crate::i2c::RxDma<T>,
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if buffer.is_empty() {
 | 
					 | 
				
			||||||
            self.read_internal(address, buffer, false, no_timeout_fn())
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            self.read_dma_internal(address, buffer, false, no_timeout_fn()).await
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(feature = "time")]
 | 
					 | 
				
			||||||
    pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
 | 
					    pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
 | 
				
			||||||
    where
 | 
					    where
 | 
				
			||||||
        TXDMA: super::TxDma<T>,
 | 
					        TXDMA: super::TxDma<T>,
 | 
				
			||||||
        RXDMA: super::RxDma<T>,
 | 
					        RXDMA: super::RxDma<T>,
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        let start_instant = Instant::now();
 | 
					        let timeout = self.timeout();
 | 
				
			||||||
        let check_timeout = timeout_fn(self.timeout);
 | 
					
 | 
				
			||||||
        if write.is_empty() {
 | 
					        if write.is_empty() {
 | 
				
			||||||
            self.write_internal(address, write, false, &check_timeout)?;
 | 
					            self.write_internal(address, write, false, timeout)?;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            embassy_time::with_timeout(
 | 
					            let fut = self.write_dma_internal(address, write, true, true, timeout);
 | 
				
			||||||
                self.timeout,
 | 
					            timeout.with(fut).await?;
 | 
				
			||||||
                self.write_dma_internal(address, write, true, true, &check_timeout),
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
            .await
 | 
					 | 
				
			||||||
            .unwrap_or(Err(Error::Timeout))?;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let time_left_until_timeout = self.timeout - Instant::now().duration_since(start_instant);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if read.is_empty() {
 | 
					 | 
				
			||||||
            self.read_internal(address, read, true, &check_timeout)?;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            embassy_time::with_timeout(
 | 
					 | 
				
			||||||
                time_left_until_timeout,
 | 
					 | 
				
			||||||
                self.read_dma_internal(address, read, true, &check_timeout),
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
            .await
 | 
					 | 
				
			||||||
            .unwrap_or(Err(Error::Timeout))?;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Ok(())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(not(feature = "time"))]
 | 
					 | 
				
			||||||
    pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
 | 
					 | 
				
			||||||
    where
 | 
					 | 
				
			||||||
        TXDMA: super::TxDma<T>,
 | 
					 | 
				
			||||||
        RXDMA: super::RxDma<T>,
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        let no_timeout = no_timeout_fn();
 | 
					 | 
				
			||||||
        if write.is_empty() {
 | 
					 | 
				
			||||||
            self.write_internal(address, write, false, &no_timeout)?;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            self.write_dma_internal(address, write, true, true, &no_timeout).await?;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if read.is_empty() {
 | 
					        if read.is_empty() {
 | 
				
			||||||
            self.read_internal(address, read, true, &no_timeout)?;
 | 
					            self.read_internal(address, read, true, timeout)?;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            self.read_dma_internal(address, read, true, &no_timeout).await?;
 | 
					            let fut = self.read_dma_internal(address, read, true, timeout);
 | 
				
			||||||
 | 
					            timeout.with(fut).await?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
@@ -763,105 +560,35 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
    // =========================
 | 
					    // =========================
 | 
				
			||||||
    //  Blocking public API
 | 
					    //  Blocking public API
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[cfg(feature = "time")]
 | 
					    /// Blocking read.
 | 
				
			||||||
    pub fn blocking_read_timeout(&mut self, address: u8, read: &mut [u8], timeout: Duration) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        self.read_internal(address, read, false, timeout_fn(timeout))
 | 
					 | 
				
			||||||
        // Automatic Stop
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(not(feature = "time"))]
 | 
					 | 
				
			||||||
    pub fn blocking_read_timeout(
 | 
					 | 
				
			||||||
        &mut self,
 | 
					 | 
				
			||||||
        address: u8,
 | 
					 | 
				
			||||||
        read: &mut [u8],
 | 
					 | 
				
			||||||
        check_timeout: impl Fn() -> Result<(), Error>,
 | 
					 | 
				
			||||||
    ) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        self.read_internal(address, read, false, check_timeout)
 | 
					 | 
				
			||||||
        // Automatic Stop
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(feature = "time")]
 | 
					 | 
				
			||||||
    pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
 | 
					    pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
 | 
				
			||||||
        self.blocking_read_timeout(address, read, self.timeout)
 | 
					        self.read_internal(address, read, false, self.timeout())
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(not(feature = "time"))]
 | 
					 | 
				
			||||||
    pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        self.blocking_read_timeout(address, read, || Ok(()))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(feature = "time")]
 | 
					 | 
				
			||||||
    pub fn blocking_write_timeout(&mut self, address: u8, write: &[u8], timeout: Duration) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        self.write_internal(address, write, true, timeout_fn(timeout))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(not(feature = "time"))]
 | 
					 | 
				
			||||||
    pub fn blocking_write_timeout(
 | 
					 | 
				
			||||||
        &mut self,
 | 
					 | 
				
			||||||
        address: u8,
 | 
					 | 
				
			||||||
        write: &[u8],
 | 
					 | 
				
			||||||
        check_timeout: impl Fn() -> Result<(), Error>,
 | 
					 | 
				
			||||||
    ) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        self.write_internal(address, write, true, check_timeout)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(feature = "time")]
 | 
					 | 
				
			||||||
    pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        self.blocking_write_timeout(address, write, self.timeout)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(not(feature = "time"))]
 | 
					 | 
				
			||||||
    pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        self.blocking_write_timeout(address, write, || Ok(()))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(feature = "time")]
 | 
					 | 
				
			||||||
    pub fn blocking_write_read_timeout(
 | 
					 | 
				
			||||||
        &mut self,
 | 
					 | 
				
			||||||
        address: u8,
 | 
					 | 
				
			||||||
        write: &[u8],
 | 
					 | 
				
			||||||
        read: &mut [u8],
 | 
					 | 
				
			||||||
        timeout: Duration,
 | 
					 | 
				
			||||||
    ) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        let check_timeout = timeout_fn(timeout);
 | 
					 | 
				
			||||||
        self.write_internal(address, write, false, &check_timeout)?;
 | 
					 | 
				
			||||||
        self.read_internal(address, read, true, &check_timeout)
 | 
					 | 
				
			||||||
        // Automatic Stop
 | 
					        // Automatic Stop
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[cfg(not(feature = "time"))]
 | 
					    /// Blocking write.
 | 
				
			||||||
    pub fn blocking_write_read_timeout(
 | 
					    pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
 | 
				
			||||||
        &mut self,
 | 
					        self.write_internal(address, write, true, self.timeout())
 | 
				
			||||||
        address: u8,
 | 
					    }
 | 
				
			||||||
        write: &[u8],
 | 
					
 | 
				
			||||||
        read: &mut [u8],
 | 
					    /// Blocking write, restart, read.
 | 
				
			||||||
        check_timeout: impl Fn() -> Result<(), Error>,
 | 
					    pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
 | 
				
			||||||
    ) -> Result<(), Error> {
 | 
					        let timeout = self.timeout();
 | 
				
			||||||
        self.write_internal(address, write, false, &check_timeout)?;
 | 
					        self.write_internal(address, write, false, timeout)?;
 | 
				
			||||||
        self.read_internal(address, read, true, &check_timeout)
 | 
					        self.read_internal(address, read, true, timeout)
 | 
				
			||||||
        // Automatic Stop
 | 
					        // Automatic Stop
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[cfg(feature = "time")]
 | 
					    /// Blocking write multiple buffers.
 | 
				
			||||||
    pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
 | 
					    ///
 | 
				
			||||||
        self.blocking_write_read_timeout(address, write, read, self.timeout)
 | 
					    /// The buffers are concatenated in a single write transaction.
 | 
				
			||||||
    }
 | 
					    pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {
 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(not(feature = "time"))]
 | 
					 | 
				
			||||||
    pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        self.blocking_write_read_timeout(address, write, read, || Ok(()))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn blocking_write_vectored_with_timeout(
 | 
					 | 
				
			||||||
        &mut self,
 | 
					 | 
				
			||||||
        address: u8,
 | 
					 | 
				
			||||||
        write: &[&[u8]],
 | 
					 | 
				
			||||||
        check_timeout: impl Fn() -> Result<(), Error>,
 | 
					 | 
				
			||||||
    ) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        if write.is_empty() {
 | 
					        if write.is_empty() {
 | 
				
			||||||
            return Err(Error::ZeroLengthTransfer);
 | 
					            return Err(Error::ZeroLengthTransfer);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let timeout = self.timeout();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let first_length = write[0].len();
 | 
					        let first_length = write[0].len();
 | 
				
			||||||
        let last_slice_index = write.len() - 1;
 | 
					        let last_slice_index = write.len() - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -870,7 +597,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
            first_length.min(255),
 | 
					            first_length.min(255),
 | 
				
			||||||
            Stop::Software,
 | 
					            Stop::Software,
 | 
				
			||||||
            (first_length > 255) || (last_slice_index != 0),
 | 
					            (first_length > 255) || (last_slice_index != 0),
 | 
				
			||||||
            &check_timeout,
 | 
					            timeout,
 | 
				
			||||||
        ) {
 | 
					        ) {
 | 
				
			||||||
            self.master_stop();
 | 
					            self.master_stop();
 | 
				
			||||||
            return Err(err);
 | 
					            return Err(err);
 | 
				
			||||||
@@ -890,7 +617,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
                if let Err(err) = Self::master_continue(
 | 
					                if let Err(err) = Self::master_continue(
 | 
				
			||||||
                    slice_len.min(255),
 | 
					                    slice_len.min(255),
 | 
				
			||||||
                    (idx != last_slice_index) || (slice_len > 255),
 | 
					                    (idx != last_slice_index) || (slice_len > 255),
 | 
				
			||||||
                    &check_timeout,
 | 
					                    timeout,
 | 
				
			||||||
                ) {
 | 
					                ) {
 | 
				
			||||||
                    self.master_stop();
 | 
					                    self.master_stop();
 | 
				
			||||||
                    return Err(err);
 | 
					                    return Err(err);
 | 
				
			||||||
@@ -902,7 +629,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
                    if let Err(err) = Self::master_continue(
 | 
					                    if let Err(err) = Self::master_continue(
 | 
				
			||||||
                        chunk.len(),
 | 
					                        chunk.len(),
 | 
				
			||||||
                        (number != last_chunk_idx) || (idx != last_slice_index),
 | 
					                        (number != last_chunk_idx) || (idx != last_slice_index),
 | 
				
			||||||
                        &check_timeout,
 | 
					                        timeout,
 | 
				
			||||||
                    ) {
 | 
					                    ) {
 | 
				
			||||||
                        self.master_stop();
 | 
					                        self.master_stop();
 | 
				
			||||||
                        return Err(err);
 | 
					                        return Err(err);
 | 
				
			||||||
@@ -913,7 +640,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
                    // Wait until we are allowed to send data
 | 
					                    // Wait until we are allowed to send data
 | 
				
			||||||
                    // (START has been ACKed or last byte when
 | 
					                    // (START has been ACKed or last byte when
 | 
				
			||||||
                    // through)
 | 
					                    // through)
 | 
				
			||||||
                    if let Err(err) = self.wait_txe(&check_timeout) {
 | 
					                    if let Err(err) = self.wait_txe(timeout) {
 | 
				
			||||||
                        self.master_stop();
 | 
					                        self.master_stop();
 | 
				
			||||||
                        return Err(err);
 | 
					                        return Err(err);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@@ -925,41 +652,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // Wait until the write finishes
 | 
					        // Wait until the write finishes
 | 
				
			||||||
        let result = self.wait_tc(&check_timeout);
 | 
					        let result = self.wait_tc(timeout);
 | 
				
			||||||
        self.master_stop();
 | 
					        self.master_stop();
 | 
				
			||||||
        result
 | 
					        result
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(feature = "time")]
 | 
					 | 
				
			||||||
    pub fn blocking_write_vectored_timeout(
 | 
					 | 
				
			||||||
        &mut self,
 | 
					 | 
				
			||||||
        address: u8,
 | 
					 | 
				
			||||||
        write: &[&[u8]],
 | 
					 | 
				
			||||||
        timeout: Duration,
 | 
					 | 
				
			||||||
    ) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        let check_timeout = timeout_fn(timeout);
 | 
					 | 
				
			||||||
        self.blocking_write_vectored_with_timeout(address, write, check_timeout)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(not(feature = "time"))]
 | 
					 | 
				
			||||||
    pub fn blocking_write_vectored_timeout(
 | 
					 | 
				
			||||||
        &mut self,
 | 
					 | 
				
			||||||
        address: u8,
 | 
					 | 
				
			||||||
        write: &[&[u8]],
 | 
					 | 
				
			||||||
        check_timeout: impl Fn() -> Result<(), Error>,
 | 
					 | 
				
			||||||
    ) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        self.blocking_write_vectored_with_timeout(address, write, check_timeout)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(feature = "time")]
 | 
					 | 
				
			||||||
    pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        self.blocking_write_vectored_timeout(address, write, self.timeout)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(not(feature = "time"))]
 | 
					 | 
				
			||||||
    pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {
 | 
					 | 
				
			||||||
        self.blocking_write_vectored_timeout(address, write, || Ok(()))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
 | 
					impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user