Merge pull request #2974 from embassy-rs/spi-nogenerics
stm32/i2c: remove peripheral generic param.
This commit is contained in:
		
						commit
						a636bace98
					
				@ -653,9 +653,9 @@ fn main() {
 | 
				
			|||||||
                        crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
 | 
					                        crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
 | 
				
			||||||
                        #decr_stop_refcount
 | 
					                        #decr_stop_refcount
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    fn enable_bit() -> crate::rcc::ClockEnableBit {
 | 
					
 | 
				
			||||||
                        unsafe { crate::rcc::ClockEnableBit::new(#en_reg_offs, #en_bit_offs) }
 | 
					                    const ENABLE_BIT: crate::rcc::ClockEnableBit =
 | 
				
			||||||
                    }
 | 
					                        unsafe { crate::rcc::ClockEnableBit::new(#en_reg_offs, #en_bit_offs) };
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                impl crate::rcc::RccPeripheral for peripherals::#pname {}
 | 
					                impl crate::rcc::RccPeripheral for peripherals::#pname {}
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ use core::future::Future;
 | 
				
			|||||||
use core::iter;
 | 
					use core::iter;
 | 
				
			||||||
use core::marker::PhantomData;
 | 
					use core::marker::PhantomData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
 | 
					use embassy_hal_internal::{into_ref, Peripheral};
 | 
				
			||||||
use embassy_sync::waitqueue::AtomicWaker;
 | 
					use embassy_sync::waitqueue::AtomicWaker;
 | 
				
			||||||
#[cfg(feature = "time")]
 | 
					#[cfg(feature = "time")]
 | 
				
			||||||
use embassy_time::{Duration, Instant};
 | 
					use embassy_time::{Duration, Instant};
 | 
				
			||||||
@ -18,6 +18,7 @@ use crate::dma::ChannelAndRequest;
 | 
				
			|||||||
use crate::gpio::{AFType, Pull};
 | 
					use crate::gpio::{AFType, Pull};
 | 
				
			||||||
use crate::interrupt::typelevel::Interrupt;
 | 
					use crate::interrupt::typelevel::Interrupt;
 | 
				
			||||||
use crate::mode::{Async, Blocking, Mode};
 | 
					use crate::mode::{Async, Blocking, Mode};
 | 
				
			||||||
 | 
					use crate::rcc::{ClockEnableBit, SealedRccPeripheral};
 | 
				
			||||||
use crate::time::Hertz;
 | 
					use crate::time::Hertz;
 | 
				
			||||||
use crate::{interrupt, peripherals};
 | 
					use crate::{interrupt, peripherals};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -72,8 +73,10 @@ impl Default for Config {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// I2C driver.
 | 
					/// I2C driver.
 | 
				
			||||||
pub struct I2c<'d, T: Instance, M: Mode> {
 | 
					pub struct I2c<'d, M: Mode> {
 | 
				
			||||||
    _peri: PeripheralRef<'d, T>,
 | 
					    info: &'static Info,
 | 
				
			||||||
 | 
					    state: &'static State,
 | 
				
			||||||
 | 
					    kernel_clock: Hertz,
 | 
				
			||||||
    tx_dma: Option<ChannelAndRequest<'d>>,
 | 
					    tx_dma: Option<ChannelAndRequest<'d>>,
 | 
				
			||||||
    rx_dma: Option<ChannelAndRequest<'d>>,
 | 
					    rx_dma: Option<ChannelAndRequest<'d>>,
 | 
				
			||||||
    #[cfg(feature = "time")]
 | 
					    #[cfg(feature = "time")]
 | 
				
			||||||
@ -81,9 +84,9 @@ pub struct I2c<'d, T: Instance, M: Mode> {
 | 
				
			|||||||
    _phantom: PhantomData<M>,
 | 
					    _phantom: PhantomData<M>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
					impl<'d> I2c<'d, Async> {
 | 
				
			||||||
    /// Create a new I2C driver.
 | 
					    /// Create a new I2C driver.
 | 
				
			||||||
    pub fn new(
 | 
					    pub fn new<T: Instance>(
 | 
				
			||||||
        peri: impl Peripheral<P = T> + 'd,
 | 
					        peri: impl Peripheral<P = T> + 'd,
 | 
				
			||||||
        scl: impl Peripheral<P = impl SclPin<T>> + 'd,
 | 
					        scl: impl Peripheral<P = impl SclPin<T>> + 'd,
 | 
				
			||||||
        sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
 | 
					        sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
 | 
				
			||||||
@ -99,9 +102,9 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance> I2c<'d, T, Blocking> {
 | 
					impl<'d> I2c<'d, Blocking> {
 | 
				
			||||||
    /// Create a new blocking I2C driver.
 | 
					    /// Create a new blocking I2C driver.
 | 
				
			||||||
    pub fn new_blocking(
 | 
					    pub fn new_blocking<T: Instance>(
 | 
				
			||||||
        peri: impl Peripheral<P = T> + 'd,
 | 
					        peri: impl Peripheral<P = T> + 'd,
 | 
				
			||||||
        scl: impl Peripheral<P = impl SclPin<T>> + 'd,
 | 
					        scl: impl Peripheral<P = impl SclPin<T>> + 'd,
 | 
				
			||||||
        sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
 | 
					        sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
 | 
				
			||||||
@ -112,10 +115,10 @@ impl<'d, T: Instance> I2c<'d, T, Blocking> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
					impl<'d, M: Mode> I2c<'d, M> {
 | 
				
			||||||
    /// Create a new I2C driver.
 | 
					    /// Create a new I2C driver.
 | 
				
			||||||
    fn new_inner(
 | 
					    fn new_inner<T: Instance>(
 | 
				
			||||||
        peri: impl Peripheral<P = T> + 'd,
 | 
					        _peri: impl Peripheral<P = T> + 'd,
 | 
				
			||||||
        scl: impl Peripheral<P = impl SclPin<T>> + 'd,
 | 
					        scl: impl Peripheral<P = impl SclPin<T>> + 'd,
 | 
				
			||||||
        sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
 | 
					        sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
 | 
				
			||||||
        tx_dma: Option<ChannelAndRequest<'d>>,
 | 
					        tx_dma: Option<ChannelAndRequest<'d>>,
 | 
				
			||||||
@ -123,7 +126,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
        freq: Hertz,
 | 
					        freq: Hertz,
 | 
				
			||||||
        config: Config,
 | 
					        config: Config,
 | 
				
			||||||
    ) -> Self {
 | 
					    ) -> Self {
 | 
				
			||||||
        into_ref!(peri, scl, sda);
 | 
					        into_ref!(scl, sda);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        T::enable_and_reset();
 | 
					        T::enable_and_reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -148,7 +151,9 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
        unsafe { T::ErrorInterrupt::enable() };
 | 
					        unsafe { T::ErrorInterrupt::enable() };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut this = Self {
 | 
					        let mut this = Self {
 | 
				
			||||||
            _peri: peri,
 | 
					            info: T::info(),
 | 
				
			||||||
 | 
					            state: T::state(),
 | 
				
			||||||
 | 
					            kernel_clock: T::frequency(),
 | 
				
			||||||
            tx_dma,
 | 
					            tx_dma,
 | 
				
			||||||
            rx_dma,
 | 
					            rx_dma,
 | 
				
			||||||
            #[cfg(feature = "time")]
 | 
					            #[cfg(feature = "time")]
 | 
				
			||||||
@ -217,19 +222,14 @@ impl State {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
trait SealedInstance: crate::rcc::RccPeripheral {
 | 
					struct Info {
 | 
				
			||||||
    fn regs() -> crate::pac::i2c::I2c;
 | 
					    regs: crate::pac::i2c::I2c,
 | 
				
			||||||
    fn state() -> &'static State;
 | 
					    pub(crate) enable_bit: ClockEnableBit,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// I2C peripheral instance
 | 
					peri_trait!(
 | 
				
			||||||
#[allow(private_bounds)]
 | 
					    irqs: [EventInterrupt, ErrorInterrupt],
 | 
				
			||||||
pub trait Instance: SealedInstance + 'static {
 | 
					);
 | 
				
			||||||
    /// Event interrupt for this instance
 | 
					 | 
				
			||||||
    type EventInterrupt: interrupt::typelevel::Interrupt;
 | 
					 | 
				
			||||||
    /// Error interrupt for this instance
 | 
					 | 
				
			||||||
    type ErrorInterrupt: interrupt::typelevel::Interrupt;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
pin_trait!(SclPin, Instance);
 | 
					pin_trait!(SclPin, Instance);
 | 
				
			||||||
pin_trait!(SdaPin, Instance);
 | 
					pin_trait!(SdaPin, Instance);
 | 
				
			||||||
@ -260,11 +260,15 @@ impl<T: Instance> interrupt::typelevel::Handler<T::ErrorInterrupt> for ErrorInte
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
foreach_peripheral!(
 | 
					foreach_peripheral!(
 | 
				
			||||||
    (i2c, $inst:ident) => {
 | 
					    (i2c, $inst:ident) => {
 | 
				
			||||||
 | 
					        #[allow(private_interfaces)]
 | 
				
			||||||
        impl SealedInstance for peripherals::$inst {
 | 
					        impl SealedInstance for peripherals::$inst {
 | 
				
			||||||
            fn regs() -> crate::pac::i2c::I2c {
 | 
					            fn info() -> &'static Info {
 | 
				
			||||||
                crate::pac::$inst
 | 
					                static INFO: Info = Info{
 | 
				
			||||||
 | 
					                    regs: crate::pac::$inst,
 | 
				
			||||||
 | 
					                    enable_bit: crate::peripherals::$inst::ENABLE_BIT,
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                &INFO
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					 | 
				
			||||||
            fn state() -> &'static State {
 | 
					            fn state() -> &'static State {
 | 
				
			||||||
                static STATE: State = State::new();
 | 
					                static STATE: State = State::new();
 | 
				
			||||||
                &STATE
 | 
					                &STATE
 | 
				
			||||||
@ -278,7 +282,7 @@ foreach_peripheral!(
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, T, M> {
 | 
					impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, M> {
 | 
				
			||||||
    type Error = Error;
 | 
					    type Error = Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
 | 
					    fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
 | 
				
			||||||
@ -286,7 +290,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, T, M> {
 | 
					impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, M> {
 | 
				
			||||||
    type Error = Error;
 | 
					    type Error = Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
 | 
					    fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
 | 
				
			||||||
@ -294,7 +298,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, T, M> {
 | 
					impl<'d, M: Mode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M> {
 | 
				
			||||||
    type Error = Error;
 | 
					    type Error = Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
 | 
					    fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
 | 
				
			||||||
@ -318,11 +322,11 @@ impl embedded_hal_1::i2c::Error for Error {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance, M: Mode> embedded_hal_1::i2c::ErrorType for I2c<'d, T, M> {
 | 
					impl<'d, M: Mode> embedded_hal_1::i2c::ErrorType for I2c<'d, M> {
 | 
				
			||||||
    type Error = Error;
 | 
					    type Error = Error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, T, M> {
 | 
					impl<'d, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, M> {
 | 
				
			||||||
    fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
 | 
					    fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
 | 
				
			||||||
        self.blocking_read(address, read)
 | 
					        self.blocking_read(address, read)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -344,7 +348,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, T, M> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance> embedded_hal_async::i2c::I2c for I2c<'d, T, Async> {
 | 
					impl<'d> embedded_hal_async::i2c::I2c for I2c<'d, Async> {
 | 
				
			||||||
    async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
 | 
					    async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
 | 
				
			||||||
        self.read(address, read).await
 | 
					        self.read(address, read).await
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -28,7 +28,7 @@ use crate::pac::i2c;
 | 
				
			|||||||
// There's some more details there, and we might have a fix for you. But please let us know if you
 | 
					// There's some more details there, and we might have a fix for you. But please let us know if you
 | 
				
			||||||
// hit a case like this!
 | 
					// hit a case like this!
 | 
				
			||||||
pub unsafe fn on_interrupt<T: Instance>() {
 | 
					pub unsafe fn on_interrupt<T: Instance>() {
 | 
				
			||||||
    let regs = T::regs();
 | 
					    let regs = T::info().regs;
 | 
				
			||||||
    // i2c v2 only woke the task on transfer complete interrupts. v1 uses interrupts for a bunch of
 | 
					    // i2c v2 only woke the task on transfer complete interrupts. v1 uses interrupts for a bunch of
 | 
				
			||||||
    // other stuff, so we wake the task on every interrupt.
 | 
					    // other stuff, so we wake the task on every interrupt.
 | 
				
			||||||
    T::state().waker.wake();
 | 
					    T::state().waker.wake();
 | 
				
			||||||
@ -41,9 +41,9 @@ pub unsafe fn on_interrupt<T: Instance>() {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
 | 
					impl<'d, M: PeriMode> I2c<'d, M> {
 | 
				
			||||||
    pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
 | 
					    pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
 | 
				
			||||||
        T::regs().cr1().modify(|reg| {
 | 
					        self.info.regs.cr1().modify(|reg| {
 | 
				
			||||||
            reg.set_pe(false);
 | 
					            reg.set_pe(false);
 | 
				
			||||||
            //reg.set_anfoff(false);
 | 
					            //reg.set_anfoff(false);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
@ -67,39 +67,39 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
 | 
				
			|||||||
        //
 | 
					        //
 | 
				
			||||||
        // This presents as an ~infinite hang on read or write, as the START condition
 | 
					        // This presents as an ~infinite hang on read or write, as the START condition
 | 
				
			||||||
        // is never generated, meaning the start event is never generated.
 | 
					        // is never generated, meaning the start event is never generated.
 | 
				
			||||||
        T::regs().cr1().modify(|reg| {
 | 
					        self.info.regs.cr1().modify(|reg| {
 | 
				
			||||||
            reg.set_swrst(true);
 | 
					            reg.set_swrst(true);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        T::regs().cr1().modify(|reg| {
 | 
					        self.info.regs.cr1().modify(|reg| {
 | 
				
			||||||
            reg.set_swrst(false);
 | 
					            reg.set_swrst(false);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let timings = Timings::new(T::frequency(), freq);
 | 
					        let timings = Timings::new(self.kernel_clock, freq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        T::regs().cr2().modify(|reg| {
 | 
					        self.info.regs.cr2().modify(|reg| {
 | 
				
			||||||
            reg.set_freq(timings.freq);
 | 
					            reg.set_freq(timings.freq);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        T::regs().ccr().modify(|reg| {
 | 
					        self.info.regs.ccr().modify(|reg| {
 | 
				
			||||||
            reg.set_f_s(timings.mode.f_s());
 | 
					            reg.set_f_s(timings.mode.f_s());
 | 
				
			||||||
            reg.set_duty(timings.duty.duty());
 | 
					            reg.set_duty(timings.duty.duty());
 | 
				
			||||||
            reg.set_ccr(timings.ccr);
 | 
					            reg.set_ccr(timings.ccr);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        T::regs().trise().modify(|reg| {
 | 
					        self.info.regs.trise().modify(|reg| {
 | 
				
			||||||
            reg.set_trise(timings.trise);
 | 
					            reg.set_trise(timings.trise);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        T::regs().cr1().modify(|reg| {
 | 
					        self.info.regs.cr1().modify(|reg| {
 | 
				
			||||||
            reg.set_pe(true);
 | 
					            reg.set_pe(true);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn check_and_clear_error_flags() -> Result<i2c::regs::Sr1, Error> {
 | 
					    fn check_and_clear_error_flags(info: &'static Info) -> Result<i2c::regs::Sr1, Error> {
 | 
				
			||||||
        // Note that flags should only be cleared once they have been registered. If flags are
 | 
					        // Note that flags should only be cleared once they have been registered. If flags are
 | 
				
			||||||
        // cleared otherwise, there may be an inherent race condition and flags may be missed.
 | 
					        // cleared otherwise, there may be an inherent race condition and flags may be missed.
 | 
				
			||||||
        let sr1 = T::regs().sr1().read();
 | 
					        let sr1 = info.regs.sr1().read();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if sr1.timeout() {
 | 
					        if sr1.timeout() {
 | 
				
			||||||
            T::regs().sr1().write(|reg| {
 | 
					            info.regs.sr1().write(|reg| {
 | 
				
			||||||
                reg.0 = !0;
 | 
					                reg.0 = !0;
 | 
				
			||||||
                reg.set_timeout(false);
 | 
					                reg.set_timeout(false);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
@ -107,7 +107,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if sr1.pecerr() {
 | 
					        if sr1.pecerr() {
 | 
				
			||||||
            T::regs().sr1().write(|reg| {
 | 
					            info.regs.sr1().write(|reg| {
 | 
				
			||||||
                reg.0 = !0;
 | 
					                reg.0 = !0;
 | 
				
			||||||
                reg.set_pecerr(false);
 | 
					                reg.set_pecerr(false);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
@ -115,7 +115,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if sr1.ovr() {
 | 
					        if sr1.ovr() {
 | 
				
			||||||
            T::regs().sr1().write(|reg| {
 | 
					            info.regs.sr1().write(|reg| {
 | 
				
			||||||
                reg.0 = !0;
 | 
					                reg.0 = !0;
 | 
				
			||||||
                reg.set_ovr(false);
 | 
					                reg.set_ovr(false);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
@ -123,7 +123,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if sr1.af() {
 | 
					        if sr1.af() {
 | 
				
			||||||
            T::regs().sr1().write(|reg| {
 | 
					            info.regs.sr1().write(|reg| {
 | 
				
			||||||
                reg.0 = !0;
 | 
					                reg.0 = !0;
 | 
				
			||||||
                reg.set_af(false);
 | 
					                reg.set_af(false);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
@ -131,7 +131,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if sr1.arlo() {
 | 
					        if sr1.arlo() {
 | 
				
			||||||
            T::regs().sr1().write(|reg| {
 | 
					            info.regs.sr1().write(|reg| {
 | 
				
			||||||
                reg.0 = !0;
 | 
					                reg.0 = !0;
 | 
				
			||||||
                reg.set_arlo(false);
 | 
					                reg.set_arlo(false);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
@ -141,7 +141,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
 | 
				
			|||||||
        // The errata indicates that BERR may be incorrectly detected. It recommends ignoring and
 | 
					        // The errata indicates that BERR may be incorrectly detected. It recommends ignoring and
 | 
				
			||||||
        // clearing the BERR bit instead.
 | 
					        // clearing the BERR bit instead.
 | 
				
			||||||
        if sr1.berr() {
 | 
					        if sr1.berr() {
 | 
				
			||||||
            T::regs().sr1().write(|reg| {
 | 
					            info.regs.sr1().write(|reg| {
 | 
				
			||||||
                reg.0 = !0;
 | 
					                reg.0 = !0;
 | 
				
			||||||
                reg.set_berr(false);
 | 
					                reg.set_berr(false);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
@ -154,32 +154,32 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
 | 
				
			|||||||
        if frame.send_start() {
 | 
					        if frame.send_start() {
 | 
				
			||||||
            // Send a START condition
 | 
					            // Send a START condition
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            T::regs().cr1().modify(|reg| {
 | 
					            self.info.regs.cr1().modify(|reg| {
 | 
				
			||||||
                reg.set_start(true);
 | 
					                reg.set_start(true);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // 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(self.info)?.start() {
 | 
				
			||||||
                timeout.check()?;
 | 
					                timeout.check()?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Check if we were the ones to generate START
 | 
					            // Check if we were the ones to generate START
 | 
				
			||||||
            if T::regs().cr1().read().start() || !T::regs().sr2().read().msl() {
 | 
					            if self.info.regs.cr1().read().start() || !self.info.regs.sr2().read().msl() {
 | 
				
			||||||
                return Err(Error::Arbitration);
 | 
					                return Err(Error::Arbitration);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Set up current address we're trying to talk to
 | 
					            // Set up current address we're trying to talk to
 | 
				
			||||||
            T::regs().dr().write(|reg| reg.set_dr(addr << 1));
 | 
					            self.info.regs.dr().write(|reg| reg.set_dr(addr << 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Wait until address was sent
 | 
					            // Wait until address was sent
 | 
				
			||||||
            // 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(self.info)?.addr() {
 | 
				
			||||||
                timeout.check()?;
 | 
					                timeout.check()?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Clear condition by reading SR2
 | 
					            // Clear condition by reading SR2
 | 
				
			||||||
            let _ = T::regs().sr2().read();
 | 
					            let _ = self.info.regs.sr2().read();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Send bytes
 | 
					        // Send bytes
 | 
				
			||||||
@ -189,7 +189,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if frame.send_stop() {
 | 
					        if frame.send_stop() {
 | 
				
			||||||
            // Send a STOP condition
 | 
					            // Send a STOP condition
 | 
				
			||||||
            T::regs().cr1().modify(|reg| reg.set_stop(true));
 | 
					            self.info.regs.cr1().modify(|reg| reg.set_stop(true));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Fallthrough is success
 | 
					        // Fallthrough is success
 | 
				
			||||||
@ -200,18 +200,18 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
 | 
				
			|||||||
        // 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(self.info)?.txe()
 | 
				
			||||||
        } {
 | 
					        } {
 | 
				
			||||||
            timeout.check()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Push out a byte of data
 | 
					        // Push out a byte of data
 | 
				
			||||||
        T::regs().dr().write(|reg| reg.set_dr(byte));
 | 
					        self.info.regs.dr().write(|reg| reg.set_dr(byte));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Wait until byte is transferred
 | 
					        // Wait until byte is transferred
 | 
				
			||||||
        while {
 | 
					        while {
 | 
				
			||||||
            // 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(self.info)?.btf()
 | 
				
			||||||
        } {
 | 
					        } {
 | 
				
			||||||
            timeout.check()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -222,14 +222,14 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
 | 
				
			|||||||
    fn recv_byte(&self, timeout: Timeout) -> 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(self.info)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            !T::regs().sr1().read().rxne()
 | 
					            !self.info.regs.sr1().read().rxne()
 | 
				
			||||||
        } {
 | 
					        } {
 | 
				
			||||||
            timeout.check()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let value = T::regs().dr().read().dr();
 | 
					        let value = self.info.regs.dr().read().dr();
 | 
				
			||||||
        Ok(value)
 | 
					        Ok(value)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -246,32 +246,32 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if frame.send_start() {
 | 
					        if frame.send_start() {
 | 
				
			||||||
            // Send a START condition and set ACK bit
 | 
					            // Send a START condition and set ACK bit
 | 
				
			||||||
            T::regs().cr1().modify(|reg| {
 | 
					            self.info.regs.cr1().modify(|reg| {
 | 
				
			||||||
                reg.set_start(true);
 | 
					                reg.set_start(true);
 | 
				
			||||||
                reg.set_ack(true);
 | 
					                reg.set_ack(true);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // 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(self.info)?.start() {
 | 
				
			||||||
                timeout.check()?;
 | 
					                timeout.check()?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Check if we were the ones to generate START
 | 
					            // Check if we were the ones to generate START
 | 
				
			||||||
            if T::regs().cr1().read().start() || !T::regs().sr2().read().msl() {
 | 
					            if self.info.regs.cr1().read().start() || !self.info.regs.sr2().read().msl() {
 | 
				
			||||||
                return Err(Error::Arbitration);
 | 
					                return Err(Error::Arbitration);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Set up current address we're trying to talk to
 | 
					            // Set up current address we're trying to talk to
 | 
				
			||||||
            T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1));
 | 
					            self.info.regs.dr().write(|reg| reg.set_dr((addr << 1) + 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // 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(self.info)?.addr() {
 | 
				
			||||||
                timeout.check()?;
 | 
					                timeout.check()?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Clear condition by reading SR2
 | 
					            // Clear condition by reading SR2
 | 
				
			||||||
            let _ = T::regs().sr2().read();
 | 
					            let _ = self.info.regs.sr2().read();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Receive bytes into buffer
 | 
					        // Receive bytes into buffer
 | 
				
			||||||
@ -280,7 +280,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Prepare to send NACK then STOP after next byte
 | 
					        // Prepare to send NACK then STOP after next byte
 | 
				
			||||||
        T::regs().cr1().modify(|reg| {
 | 
					        self.info.regs.cr1().modify(|reg| {
 | 
				
			||||||
            if frame.send_nack() {
 | 
					            if frame.send_nack() {
 | 
				
			||||||
                reg.set_ack(false);
 | 
					                reg.set_ack(false);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -346,17 +346,17 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
 | 
				
			|||||||
    // Async
 | 
					    // Async
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[inline] // pretty sure this should always be inlined
 | 
					    #[inline] // pretty sure this should always be inlined
 | 
				
			||||||
    fn enable_interrupts() -> () {
 | 
					    fn enable_interrupts(info: &'static Info) -> () {
 | 
				
			||||||
        T::regs().cr2().modify(|w| {
 | 
					        info.regs.cr2().modify(|w| {
 | 
				
			||||||
            w.set_iterren(true);
 | 
					            w.set_iterren(true);
 | 
				
			||||||
            w.set_itevten(true);
 | 
					            w.set_itevten(true);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
					impl<'d> I2c<'d, Async> {
 | 
				
			||||||
    async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error> {
 | 
					    async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error> {
 | 
				
			||||||
        T::regs().cr2().modify(|w| {
 | 
					        self.info.regs.cr2().modify(|w| {
 | 
				
			||||||
            // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
 | 
					            // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
 | 
				
			||||||
            // reception.
 | 
					            // reception.
 | 
				
			||||||
            w.set_itbufen(false);
 | 
					            w.set_itbufen(false);
 | 
				
			||||||
@ -370,33 +370,31 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
        // Sentinel to disable transfer when an error occurs or future is canceled.
 | 
					        // Sentinel to disable transfer when an error occurs or future is canceled.
 | 
				
			||||||
        // TODO: Generate STOP condition on cancel?
 | 
					        // TODO: Generate STOP condition on cancel?
 | 
				
			||||||
        let on_drop = OnDrop::new(|| {
 | 
					        let on_drop = OnDrop::new(|| {
 | 
				
			||||||
            T::regs().cr2().modify(|w| {
 | 
					            self.info.regs.cr2().modify(|w| {
 | 
				
			||||||
                w.set_dmaen(false);
 | 
					                w.set_dmaen(false);
 | 
				
			||||||
                w.set_iterren(false);
 | 
					                w.set_iterren(false);
 | 
				
			||||||
                w.set_itevten(false);
 | 
					                w.set_itevten(false);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let state = T::state();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if frame.send_start() {
 | 
					        if frame.send_start() {
 | 
				
			||||||
            // Send a START condition
 | 
					            // Send a START condition
 | 
				
			||||||
            T::regs().cr1().modify(|reg| {
 | 
					            self.info.regs.cr1().modify(|reg| {
 | 
				
			||||||
                reg.set_start(true);
 | 
					                reg.set_start(true);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Wait until START condition was generated
 | 
					            // Wait until START condition was generated
 | 
				
			||||||
            poll_fn(|cx| {
 | 
					            poll_fn(|cx| {
 | 
				
			||||||
                state.waker.register(cx.waker());
 | 
					                self.state.waker.register(cx.waker());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                match Self::check_and_clear_error_flags() {
 | 
					                match Self::check_and_clear_error_flags(self.info) {
 | 
				
			||||||
                    Err(e) => Poll::Ready(Err(e)),
 | 
					                    Err(e) => Poll::Ready(Err(e)),
 | 
				
			||||||
                    Ok(sr1) => {
 | 
					                    Ok(sr1) => {
 | 
				
			||||||
                        if sr1.start() {
 | 
					                        if sr1.start() {
 | 
				
			||||||
                            Poll::Ready(Ok(()))
 | 
					                            Poll::Ready(Ok(()))
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            // When pending, (re-)enable interrupts to wake us up.
 | 
					                            // When pending, (re-)enable interrupts to wake us up.
 | 
				
			||||||
                            Self::enable_interrupts();
 | 
					                            Self::enable_interrupts(self.info);
 | 
				
			||||||
                            Poll::Pending
 | 
					                            Poll::Pending
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@ -405,25 +403,25 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
            .await?;
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Check if we were the ones to generate START
 | 
					            // Check if we were the ones to generate START
 | 
				
			||||||
            if T::regs().cr1().read().start() || !T::regs().sr2().read().msl() {
 | 
					            if self.info.regs.cr1().read().start() || !self.info.regs.sr2().read().msl() {
 | 
				
			||||||
                return Err(Error::Arbitration);
 | 
					                return Err(Error::Arbitration);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Set up current address we're trying to talk to
 | 
					            // Set up current address we're trying to talk to
 | 
				
			||||||
            T::regs().dr().write(|reg| reg.set_dr(address << 1));
 | 
					            self.info.regs.dr().write(|reg| reg.set_dr(address << 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Wait for the address to be acknowledged
 | 
					            // Wait for the address to be acknowledged
 | 
				
			||||||
            poll_fn(|cx| {
 | 
					            poll_fn(|cx| {
 | 
				
			||||||
                state.waker.register(cx.waker());
 | 
					                self.state.waker.register(cx.waker());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                match Self::check_and_clear_error_flags() {
 | 
					                match Self::check_and_clear_error_flags(self.info) {
 | 
				
			||||||
                    Err(e) => Poll::Ready(Err(e)),
 | 
					                    Err(e) => Poll::Ready(Err(e)),
 | 
				
			||||||
                    Ok(sr1) => {
 | 
					                    Ok(sr1) => {
 | 
				
			||||||
                        if sr1.addr() {
 | 
					                        if sr1.addr() {
 | 
				
			||||||
                            Poll::Ready(Ok(()))
 | 
					                            Poll::Ready(Ok(()))
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            // When pending, (re-)enable interrupts to wake us up.
 | 
					                            // When pending, (re-)enable interrupts to wake us up.
 | 
				
			||||||
                            Self::enable_interrupts();
 | 
					                            Self::enable_interrupts(self.info);
 | 
				
			||||||
                            Poll::Pending
 | 
					                            Poll::Pending
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@ -432,26 +430,26 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
            .await?;
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Clear condition by reading SR2
 | 
					            // Clear condition by reading SR2
 | 
				
			||||||
            T::regs().sr2().read();
 | 
					            self.info.regs.sr2().read();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let dma_transfer = unsafe {
 | 
					        let dma_transfer = unsafe {
 | 
				
			||||||
            // Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved to
 | 
					            // Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved to
 | 
				
			||||||
            // this address from the memory after each TxE event.
 | 
					            // this address from the memory after each TxE event.
 | 
				
			||||||
            let dst = T::regs().dr().as_ptr() as *mut u8;
 | 
					            let dst = self.info.regs.dr().as_ptr() as *mut u8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.tx_dma.as_mut().unwrap().write(write, dst, Default::default())
 | 
					            self.tx_dma.as_mut().unwrap().write(write, dst, Default::default())
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Wait for bytes to be sent, or an error to occur.
 | 
					        // Wait for bytes to be sent, or an error to occur.
 | 
				
			||||||
        let poll_error = poll_fn(|cx| {
 | 
					        let poll_error = poll_fn(|cx| {
 | 
				
			||||||
            state.waker.register(cx.waker());
 | 
					            self.state.waker.register(cx.waker());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            match Self::check_and_clear_error_flags() {
 | 
					            match Self::check_and_clear_error_flags(self.info) {
 | 
				
			||||||
                Err(e) => Poll::Ready(Err::<(), Error>(e)),
 | 
					                Err(e) => Poll::Ready(Err::<(), Error>(e)),
 | 
				
			||||||
                Ok(_) => {
 | 
					                Ok(_) => {
 | 
				
			||||||
                    // When pending, (re-)enable interrupts to wake us up.
 | 
					                    // When pending, (re-)enable interrupts to wake us up.
 | 
				
			||||||
                    Self::enable_interrupts();
 | 
					                    Self::enable_interrupts(self.info);
 | 
				
			||||||
                    Poll::Pending
 | 
					                    Poll::Pending
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -463,7 +461,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
            _ => Ok(()),
 | 
					            _ => Ok(()),
 | 
				
			||||||
        }?;
 | 
					        }?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        T::regs().cr2().modify(|w| {
 | 
					        self.info.regs.cr2().modify(|w| {
 | 
				
			||||||
            w.set_dmaen(false);
 | 
					            w.set_dmaen(false);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -473,16 +471,16 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
            // 18.3.8 “Master transmitter: In the interrupt routine after the EOT interrupt, disable DMA
 | 
					            // 18.3.8 “Master transmitter: In the interrupt routine after the EOT interrupt, disable DMA
 | 
				
			||||||
            // requests then wait for a BTF event before programming the Stop condition.”
 | 
					            // requests then wait for a BTF event before programming the Stop condition.”
 | 
				
			||||||
            poll_fn(|cx| {
 | 
					            poll_fn(|cx| {
 | 
				
			||||||
                state.waker.register(cx.waker());
 | 
					                self.state.waker.register(cx.waker());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                match Self::check_and_clear_error_flags() {
 | 
					                match Self::check_and_clear_error_flags(self.info) {
 | 
				
			||||||
                    Err(e) => Poll::Ready(Err(e)),
 | 
					                    Err(e) => Poll::Ready(Err(e)),
 | 
				
			||||||
                    Ok(sr1) => {
 | 
					                    Ok(sr1) => {
 | 
				
			||||||
                        if sr1.btf() {
 | 
					                        if sr1.btf() {
 | 
				
			||||||
                            Poll::Ready(Ok(()))
 | 
					                            Poll::Ready(Ok(()))
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            // When pending, (re-)enable interrupts to wake us up.
 | 
					                            // When pending, (re-)enable interrupts to wake us up.
 | 
				
			||||||
                            Self::enable_interrupts();
 | 
					                            Self::enable_interrupts(self.info);
 | 
				
			||||||
                            Poll::Pending
 | 
					                            Poll::Pending
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@ -490,7 +488,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
            })
 | 
					            })
 | 
				
			||||||
            .await?;
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            T::regs().cr1().modify(|w| {
 | 
					            self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
                w.set_stop(true);
 | 
					                w.set_stop(true);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -525,7 +523,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
        // Some branches below depend on whether the buffer contains only a single byte.
 | 
					        // Some branches below depend on whether the buffer contains only a single byte.
 | 
				
			||||||
        let single_byte = buffer.len() == 1;
 | 
					        let single_byte = buffer.len() == 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        T::regs().cr2().modify(|w| {
 | 
					        self.info.regs.cr2().modify(|w| {
 | 
				
			||||||
            // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
 | 
					            // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
 | 
				
			||||||
            // reception.
 | 
					            // reception.
 | 
				
			||||||
            w.set_itbufen(false);
 | 
					            w.set_itbufen(false);
 | 
				
			||||||
@ -541,34 +539,32 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
        // Sentinel to disable transfer when an error occurs or future is canceled.
 | 
					        // Sentinel to disable transfer when an error occurs or future is canceled.
 | 
				
			||||||
        // TODO: Generate STOP condition on cancel?
 | 
					        // TODO: Generate STOP condition on cancel?
 | 
				
			||||||
        let on_drop = OnDrop::new(|| {
 | 
					        let on_drop = OnDrop::new(|| {
 | 
				
			||||||
            T::regs().cr2().modify(|w| {
 | 
					            self.info.regs.cr2().modify(|w| {
 | 
				
			||||||
                w.set_dmaen(false);
 | 
					                w.set_dmaen(false);
 | 
				
			||||||
                w.set_iterren(false);
 | 
					                w.set_iterren(false);
 | 
				
			||||||
                w.set_itevten(false);
 | 
					                w.set_itevten(false);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let state = T::state();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if frame.send_start() {
 | 
					        if frame.send_start() {
 | 
				
			||||||
            // Send a START condition and set ACK bit
 | 
					            // Send a START condition and set ACK bit
 | 
				
			||||||
            T::regs().cr1().modify(|reg| {
 | 
					            self.info.regs.cr1().modify(|reg| {
 | 
				
			||||||
                reg.set_start(true);
 | 
					                reg.set_start(true);
 | 
				
			||||||
                reg.set_ack(true);
 | 
					                reg.set_ack(true);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Wait until START condition was generated
 | 
					            // Wait until START condition was generated
 | 
				
			||||||
            poll_fn(|cx| {
 | 
					            poll_fn(|cx| {
 | 
				
			||||||
                state.waker.register(cx.waker());
 | 
					                self.state.waker.register(cx.waker());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                match Self::check_and_clear_error_flags() {
 | 
					                match Self::check_and_clear_error_flags(self.info) {
 | 
				
			||||||
                    Err(e) => Poll::Ready(Err(e)),
 | 
					                    Err(e) => Poll::Ready(Err(e)),
 | 
				
			||||||
                    Ok(sr1) => {
 | 
					                    Ok(sr1) => {
 | 
				
			||||||
                        if sr1.start() {
 | 
					                        if sr1.start() {
 | 
				
			||||||
                            Poll::Ready(Ok(()))
 | 
					                            Poll::Ready(Ok(()))
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            // When pending, (re-)enable interrupts to wake us up.
 | 
					                            // When pending, (re-)enable interrupts to wake us up.
 | 
				
			||||||
                            Self::enable_interrupts();
 | 
					                            Self::enable_interrupts(self.info);
 | 
				
			||||||
                            Poll::Pending
 | 
					                            Poll::Pending
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@ -577,25 +573,25 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
            .await?;
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Check if we were the ones to generate START
 | 
					            // Check if we were the ones to generate START
 | 
				
			||||||
            if T::regs().cr1().read().start() || !T::regs().sr2().read().msl() {
 | 
					            if self.info.regs.cr1().read().start() || !self.info.regs.sr2().read().msl() {
 | 
				
			||||||
                return Err(Error::Arbitration);
 | 
					                return Err(Error::Arbitration);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Set up current address we're trying to talk to
 | 
					            // Set up current address we're trying to talk to
 | 
				
			||||||
            T::regs().dr().write(|reg| reg.set_dr((address << 1) + 1));
 | 
					            self.info.regs.dr().write(|reg| reg.set_dr((address << 1) + 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Wait for the address to be acknowledged
 | 
					            // Wait for the address to be acknowledged
 | 
				
			||||||
            poll_fn(|cx| {
 | 
					            poll_fn(|cx| {
 | 
				
			||||||
                state.waker.register(cx.waker());
 | 
					                self.state.waker.register(cx.waker());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                match Self::check_and_clear_error_flags() {
 | 
					                match Self::check_and_clear_error_flags(self.info) {
 | 
				
			||||||
                    Err(e) => Poll::Ready(Err(e)),
 | 
					                    Err(e) => Poll::Ready(Err(e)),
 | 
				
			||||||
                    Ok(sr1) => {
 | 
					                    Ok(sr1) => {
 | 
				
			||||||
                        if sr1.addr() {
 | 
					                        if sr1.addr() {
 | 
				
			||||||
                            Poll::Ready(Ok(()))
 | 
					                            Poll::Ready(Ok(()))
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            // When pending, (re-)enable interrupts to wake us up.
 | 
					                            // When pending, (re-)enable interrupts to wake us up.
 | 
				
			||||||
                            Self::enable_interrupts();
 | 
					                            Self::enable_interrupts(self.info);
 | 
				
			||||||
                            Poll::Pending
 | 
					                            Poll::Pending
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@ -606,18 +602,18 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
            // 18.3.8: When a single byte must be received: the NACK must be programmed during EV6
 | 
					            // 18.3.8: When a single byte must be received: the NACK must be programmed during EV6
 | 
				
			||||||
            // event, i.e. program ACK=0 when ADDR=1, before clearing ADDR flag.
 | 
					            // event, i.e. program ACK=0 when ADDR=1, before clearing ADDR flag.
 | 
				
			||||||
            if frame.send_nack() && single_byte {
 | 
					            if frame.send_nack() && single_byte {
 | 
				
			||||||
                T::regs().cr1().modify(|w| {
 | 
					                self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
                    w.set_ack(false);
 | 
					                    w.set_ack(false);
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Clear condition by reading SR2
 | 
					            // Clear condition by reading SR2
 | 
				
			||||||
            T::regs().sr2().read();
 | 
					            self.info.regs.sr2().read();
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            // Before starting reception of single byte (but without START condition, i.e. in case
 | 
					            // Before starting reception of single byte (but without START condition, i.e. in case
 | 
				
			||||||
            // of continued frame), program NACK to emit at end of this byte.
 | 
					            // of continued frame), program NACK to emit at end of this byte.
 | 
				
			||||||
            if frame.send_nack() && single_byte {
 | 
					            if frame.send_nack() && single_byte {
 | 
				
			||||||
                T::regs().cr1().modify(|w| {
 | 
					                self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
                    w.set_ack(false);
 | 
					                    w.set_ack(false);
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -627,7 +623,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
        // condition either after clearing ADDR flag, or in the DMA Transfer Complete interrupt
 | 
					        // condition either after clearing ADDR flag, or in the DMA Transfer Complete interrupt
 | 
				
			||||||
        // routine.
 | 
					        // routine.
 | 
				
			||||||
        if frame.send_stop() && single_byte {
 | 
					        if frame.send_stop() && single_byte {
 | 
				
			||||||
            T::regs().cr1().modify(|w| {
 | 
					            self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
                w.set_stop(true);
 | 
					                w.set_stop(true);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -635,20 +631,20 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
        let dma_transfer = unsafe {
 | 
					        let dma_transfer = unsafe {
 | 
				
			||||||
            // Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved
 | 
					            // Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved
 | 
				
			||||||
            // from this address from the memory after each RxE event.
 | 
					            // from this address from the memory after each RxE event.
 | 
				
			||||||
            let src = T::regs().dr().as_ptr() as *mut u8;
 | 
					            let src = self.info.regs.dr().as_ptr() as *mut u8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
 | 
					            self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Wait for bytes to be received, or an error to occur.
 | 
					        // Wait for bytes to be received, or an error to occur.
 | 
				
			||||||
        let poll_error = poll_fn(|cx| {
 | 
					        let poll_error = poll_fn(|cx| {
 | 
				
			||||||
            state.waker.register(cx.waker());
 | 
					            self.state.waker.register(cx.waker());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            match Self::check_and_clear_error_flags() {
 | 
					            match Self::check_and_clear_error_flags(self.info) {
 | 
				
			||||||
                Err(e) => Poll::Ready(Err::<(), Error>(e)),
 | 
					                Err(e) => Poll::Ready(Err::<(), Error>(e)),
 | 
				
			||||||
                _ => {
 | 
					                _ => {
 | 
				
			||||||
                    // When pending, (re-)enable interrupts to wake us up.
 | 
					                    // When pending, (re-)enable interrupts to wake us up.
 | 
				
			||||||
                    Self::enable_interrupts();
 | 
					                    Self::enable_interrupts(self.info);
 | 
				
			||||||
                    Poll::Pending
 | 
					                    Poll::Pending
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -659,12 +655,12 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
            _ => Ok(()),
 | 
					            _ => Ok(()),
 | 
				
			||||||
        }?;
 | 
					        }?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        T::regs().cr2().modify(|w| {
 | 
					        self.info.regs.cr2().modify(|w| {
 | 
				
			||||||
            w.set_dmaen(false);
 | 
					            w.set_dmaen(false);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if frame.send_stop() && !single_byte {
 | 
					        if frame.send_stop() && !single_byte {
 | 
				
			||||||
            T::regs().cr1().modify(|w| {
 | 
					            self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
                w.set_stop(true);
 | 
					                w.set_stop(true);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -704,9 +700,9 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance, M: PeriMode> Drop for I2c<'d, T, M> {
 | 
					impl<'d, M: PeriMode> Drop for I2c<'d, M> {
 | 
				
			||||||
    fn drop(&mut self) {
 | 
					    fn drop(&mut self) {
 | 
				
			||||||
        T::disable();
 | 
					        self.info.enable_bit.disable()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -810,20 +806,20 @@ impl Timings {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance, M: PeriMode> SetConfig for I2c<'d, T, M> {
 | 
					impl<'d, M: PeriMode> SetConfig for I2c<'d, M> {
 | 
				
			||||||
    type Config = Hertz;
 | 
					    type Config = Hertz;
 | 
				
			||||||
    type ConfigError = ();
 | 
					    type ConfigError = ();
 | 
				
			||||||
    fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
 | 
					    fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
 | 
				
			||||||
        let timings = Timings::new(T::frequency(), *config);
 | 
					        let timings = Timings::new(self.kernel_clock, *config);
 | 
				
			||||||
        T::regs().cr2().modify(|reg| {
 | 
					        self.info.regs.cr2().modify(|reg| {
 | 
				
			||||||
            reg.set_freq(timings.freq);
 | 
					            reg.set_freq(timings.freq);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        T::regs().ccr().modify(|reg| {
 | 
					        self.info.regs.ccr().modify(|reg| {
 | 
				
			||||||
            reg.set_f_s(timings.mode.f_s());
 | 
					            reg.set_f_s(timings.mode.f_s());
 | 
				
			||||||
            reg.set_duty(timings.duty.duty());
 | 
					            reg.set_duty(timings.duty.duty());
 | 
				
			||||||
            reg.set_ccr(timings.ccr);
 | 
					            reg.set_ccr(timings.ccr);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        T::regs().trise().modify(|reg| {
 | 
					        self.info.regs.trise().modify(|reg| {
 | 
				
			||||||
            reg.set_trise(timings.trise);
 | 
					            reg.set_trise(timings.trise);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,7 @@ use super::*;
 | 
				
			|||||||
use crate::pac::i2c;
 | 
					use crate::pac::i2c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub(crate) unsafe fn on_interrupt<T: Instance>() {
 | 
					pub(crate) unsafe fn on_interrupt<T: Instance>() {
 | 
				
			||||||
    let regs = T::regs();
 | 
					    let regs = T::info().regs;
 | 
				
			||||||
    let isr = regs.isr().read();
 | 
					    let isr = regs.isr().read();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if isr.tcr() || isr.tc() {
 | 
					    if isr.tcr() || isr.tc() {
 | 
				
			||||||
@ -23,16 +23,16 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
					impl<'d, M: Mode> I2c<'d, M> {
 | 
				
			||||||
    pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
 | 
					    pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
 | 
				
			||||||
        T::regs().cr1().modify(|reg| {
 | 
					        self.info.regs.cr1().modify(|reg| {
 | 
				
			||||||
            reg.set_pe(false);
 | 
					            reg.set_pe(false);
 | 
				
			||||||
            reg.set_anfoff(false);
 | 
					            reg.set_anfoff(false);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let timings = Timings::new(T::frequency(), freq.into());
 | 
					        let timings = Timings::new(self.kernel_clock, freq.into());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        T::regs().timingr().write(|reg| {
 | 
					        self.info.regs.timingr().write(|reg| {
 | 
				
			||||||
            reg.set_presc(timings.prescale);
 | 
					            reg.set_presc(timings.prescale);
 | 
				
			||||||
            reg.set_scll(timings.scll);
 | 
					            reg.set_scll(timings.scll);
 | 
				
			||||||
            reg.set_sclh(timings.sclh);
 | 
					            reg.set_sclh(timings.sclh);
 | 
				
			||||||
@ -40,16 +40,17 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
            reg.set_scldel(timings.scldel);
 | 
					            reg.set_scldel(timings.scldel);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        T::regs().cr1().modify(|reg| {
 | 
					        self.info.regs.cr1().modify(|reg| {
 | 
				
			||||||
            reg.set_pe(true);
 | 
					            reg.set_pe(true);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn master_stop(&mut self) {
 | 
					    fn master_stop(&mut self) {
 | 
				
			||||||
        T::regs().cr2().write(|w| w.set_stop(true));
 | 
					        self.info.regs.cr2().write(|w| w.set_stop(true));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn master_read(
 | 
					    fn master_read(
 | 
				
			||||||
 | 
					        info: &'static Info,
 | 
				
			||||||
        address: u8,
 | 
					        address: u8,
 | 
				
			||||||
        length: usize,
 | 
					        length: usize,
 | 
				
			||||||
        stop: Stop,
 | 
					        stop: Stop,
 | 
				
			||||||
@ -63,7 +64,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
            // 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 info.regs.cr2().read().start() {
 | 
				
			||||||
                timeout.check()?;
 | 
					                timeout.check()?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -78,7 +79,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
            i2c::vals::Reload::COMPLETED
 | 
					            i2c::vals::Reload::COMPLETED
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        T::regs().cr2().modify(|w| {
 | 
					        info.regs.cr2().modify(|w| {
 | 
				
			||||||
            w.set_sadd((address << 1 | 0) as u16);
 | 
					            w.set_sadd((address << 1 | 0) as u16);
 | 
				
			||||||
            w.set_add10(i2c::vals::Addmode::BIT7);
 | 
					            w.set_add10(i2c::vals::Addmode::BIT7);
 | 
				
			||||||
            w.set_dir(i2c::vals::Dir::READ);
 | 
					            w.set_dir(i2c::vals::Dir::READ);
 | 
				
			||||||
@ -91,13 +92,20 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn master_write(address: u8, length: usize, stop: Stop, reload: bool, timeout: Timeout) -> Result<(), Error> {
 | 
					    fn master_write(
 | 
				
			||||||
 | 
					        info: &'static Info,
 | 
				
			||||||
 | 
					        address: u8,
 | 
				
			||||||
 | 
					        length: usize,
 | 
				
			||||||
 | 
					        stop: Stop,
 | 
				
			||||||
 | 
					        reload: bool,
 | 
				
			||||||
 | 
					        timeout: Timeout,
 | 
				
			||||||
 | 
					    ) -> 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 info.regs.cr2().read().start() {
 | 
				
			||||||
            timeout.check()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -110,7 +118,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
        // Set START and prepare to send `bytes`. The
 | 
					        // Set START and prepare to send `bytes`. The
 | 
				
			||||||
        // START bit can be set even if the bus is BUSY or
 | 
					        // START bit can be set even if the bus is BUSY or
 | 
				
			||||||
        // I2C is in slave mode.
 | 
					        // I2C is in slave mode.
 | 
				
			||||||
        T::regs().cr2().modify(|w| {
 | 
					        info.regs.cr2().modify(|w| {
 | 
				
			||||||
            w.set_sadd((address << 1 | 0) as u16);
 | 
					            w.set_sadd((address << 1 | 0) as u16);
 | 
				
			||||||
            w.set_add10(i2c::vals::Addmode::BIT7);
 | 
					            w.set_add10(i2c::vals::Addmode::BIT7);
 | 
				
			||||||
            w.set_dir(i2c::vals::Dir::WRITE);
 | 
					            w.set_dir(i2c::vals::Dir::WRITE);
 | 
				
			||||||
@ -123,10 +131,10 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn master_continue(length: usize, reload: bool, timeout: Timeout) -> Result<(), Error> {
 | 
					    fn master_continue(info: &'static Info, length: usize, reload: bool, timeout: Timeout) -> Result<(), Error> {
 | 
				
			||||||
        assert!(length < 256 && length > 0);
 | 
					        assert!(length < 256 && length > 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        while !T::regs().isr().read().tcr() {
 | 
					        while !info.regs.isr().read().tcr() {
 | 
				
			||||||
            timeout.check()?;
 | 
					            timeout.check()?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -136,7 +144,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
            i2c::vals::Reload::COMPLETED
 | 
					            i2c::vals::Reload::COMPLETED
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        T::regs().cr2().modify(|w| {
 | 
					        info.regs.cr2().modify(|w| {
 | 
				
			||||||
            w.set_nbytes(length as u8);
 | 
					            w.set_nbytes(length as u8);
 | 
				
			||||||
            w.set_reload(reload);
 | 
					            w.set_reload(reload);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
@ -145,27 +153,27 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn flush_txdr(&self) {
 | 
					    fn flush_txdr(&self) {
 | 
				
			||||||
        if T::regs().isr().read().txis() {
 | 
					        if self.info.regs.isr().read().txis() {
 | 
				
			||||||
            T::regs().txdr().write(|w| w.set_txdata(0));
 | 
					            self.info.regs.txdr().write(|w| w.set_txdata(0));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if !T::regs().isr().read().txe() {
 | 
					        if !self.info.regs.isr().read().txe() {
 | 
				
			||||||
            T::regs().isr().modify(|w| w.set_txe(true))
 | 
					            self.info.regs.isr().modify(|w| w.set_txe(true))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn wait_txe(&self, timeout: Timeout) -> Result<(), Error> {
 | 
					    fn wait_txe(&self, timeout: Timeout) -> Result<(), Error> {
 | 
				
			||||||
        loop {
 | 
					        loop {
 | 
				
			||||||
            let isr = T::regs().isr().read();
 | 
					            let isr = self.info.regs.isr().read();
 | 
				
			||||||
            if isr.txe() {
 | 
					            if isr.txe() {
 | 
				
			||||||
                return Ok(());
 | 
					                return Ok(());
 | 
				
			||||||
            } else if isr.berr() {
 | 
					            } else if isr.berr() {
 | 
				
			||||||
                T::regs().icr().write(|reg| reg.set_berrcf(true));
 | 
					                self.info.regs.icr().write(|reg| reg.set_berrcf(true));
 | 
				
			||||||
                return Err(Error::Bus);
 | 
					                return Err(Error::Bus);
 | 
				
			||||||
            } else if isr.arlo() {
 | 
					            } else if isr.arlo() {
 | 
				
			||||||
                T::regs().icr().write(|reg| reg.set_arlocf(true));
 | 
					                self.info.regs.icr().write(|reg| reg.set_arlocf(true));
 | 
				
			||||||
                return Err(Error::Arbitration);
 | 
					                return Err(Error::Arbitration);
 | 
				
			||||||
            } else if isr.nackf() {
 | 
					            } else if isr.nackf() {
 | 
				
			||||||
                T::regs().icr().write(|reg| reg.set_nackcf(true));
 | 
					                self.info.regs.icr().write(|reg| reg.set_nackcf(true));
 | 
				
			||||||
                self.flush_txdr();
 | 
					                self.flush_txdr();
 | 
				
			||||||
                return Err(Error::Nack);
 | 
					                return Err(Error::Nack);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -176,17 +184,17 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fn wait_rxne(&self, timeout: Timeout) -> Result<(), Error> {
 | 
					    fn wait_rxne(&self, timeout: Timeout) -> Result<(), Error> {
 | 
				
			||||||
        loop {
 | 
					        loop {
 | 
				
			||||||
            let isr = T::regs().isr().read();
 | 
					            let isr = self.info.regs.isr().read();
 | 
				
			||||||
            if isr.rxne() {
 | 
					            if isr.rxne() {
 | 
				
			||||||
                return Ok(());
 | 
					                return Ok(());
 | 
				
			||||||
            } else if isr.berr() {
 | 
					            } else if isr.berr() {
 | 
				
			||||||
                T::regs().icr().write(|reg| reg.set_berrcf(true));
 | 
					                self.info.regs.icr().write(|reg| reg.set_berrcf(true));
 | 
				
			||||||
                return Err(Error::Bus);
 | 
					                return Err(Error::Bus);
 | 
				
			||||||
            } else if isr.arlo() {
 | 
					            } else if isr.arlo() {
 | 
				
			||||||
                T::regs().icr().write(|reg| reg.set_arlocf(true));
 | 
					                self.info.regs.icr().write(|reg| reg.set_arlocf(true));
 | 
				
			||||||
                return Err(Error::Arbitration);
 | 
					                return Err(Error::Arbitration);
 | 
				
			||||||
            } else if isr.nackf() {
 | 
					            } else if isr.nackf() {
 | 
				
			||||||
                T::regs().icr().write(|reg| reg.set_nackcf(true));
 | 
					                self.info.regs.icr().write(|reg| reg.set_nackcf(true));
 | 
				
			||||||
                self.flush_txdr();
 | 
					                self.flush_txdr();
 | 
				
			||||||
                return Err(Error::Nack);
 | 
					                return Err(Error::Nack);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -197,17 +205,17 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fn wait_tc(&self, timeout: Timeout) -> Result<(), Error> {
 | 
					    fn wait_tc(&self, timeout: Timeout) -> Result<(), Error> {
 | 
				
			||||||
        loop {
 | 
					        loop {
 | 
				
			||||||
            let isr = T::regs().isr().read();
 | 
					            let isr = self.info.regs.isr().read();
 | 
				
			||||||
            if isr.tc() {
 | 
					            if isr.tc() {
 | 
				
			||||||
                return Ok(());
 | 
					                return Ok(());
 | 
				
			||||||
            } else if isr.berr() {
 | 
					            } else if isr.berr() {
 | 
				
			||||||
                T::regs().icr().write(|reg| reg.set_berrcf(true));
 | 
					                self.info.regs.icr().write(|reg| reg.set_berrcf(true));
 | 
				
			||||||
                return Err(Error::Bus);
 | 
					                return Err(Error::Bus);
 | 
				
			||||||
            } else if isr.arlo() {
 | 
					            } else if isr.arlo() {
 | 
				
			||||||
                T::regs().icr().write(|reg| reg.set_arlocf(true));
 | 
					                self.info.regs.icr().write(|reg| reg.set_arlocf(true));
 | 
				
			||||||
                return Err(Error::Arbitration);
 | 
					                return Err(Error::Arbitration);
 | 
				
			||||||
            } else if isr.nackf() {
 | 
					            } else if isr.nackf() {
 | 
				
			||||||
                T::regs().icr().write(|reg| reg.set_nackcf(true));
 | 
					                self.info.regs.icr().write(|reg| reg.set_nackcf(true));
 | 
				
			||||||
                self.flush_txdr();
 | 
					                self.flush_txdr();
 | 
				
			||||||
                return Err(Error::Nack);
 | 
					                return Err(Error::Nack);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -226,6 +234,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
        let last_chunk_idx = total_chunks.saturating_sub(1);
 | 
					        let last_chunk_idx = total_chunks.saturating_sub(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Self::master_read(
 | 
					        Self::master_read(
 | 
				
			||||||
 | 
					            self.info,
 | 
				
			||||||
            address,
 | 
					            address,
 | 
				
			||||||
            read.len().min(255),
 | 
					            read.len().min(255),
 | 
				
			||||||
            Stop::Automatic,
 | 
					            Stop::Automatic,
 | 
				
			||||||
@ -236,14 +245,14 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        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, timeout)?;
 | 
					                Self::master_continue(self.info, 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(timeout)?;
 | 
					                self.wait_rxne(timeout)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                *byte = T::regs().rxdr().read().rxdata();
 | 
					                *byte = self.info.regs.rxdr().read().rxdata();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
@ -262,6 +271,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
        //
 | 
					        //
 | 
				
			||||||
        // ST SAD+W
 | 
					        // ST SAD+W
 | 
				
			||||||
        if let Err(err) = Self::master_write(
 | 
					        if let Err(err) = Self::master_write(
 | 
				
			||||||
 | 
					            self.info,
 | 
				
			||||||
            address,
 | 
					            address,
 | 
				
			||||||
            write.len().min(255),
 | 
					            write.len().min(255),
 | 
				
			||||||
            Stop::Software,
 | 
					            Stop::Software,
 | 
				
			||||||
@ -276,7 +286,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        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, timeout)?;
 | 
					                Self::master_continue(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for byte in chunk {
 | 
					            for byte in chunk {
 | 
				
			||||||
@ -290,7 +300,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
                    return Err(err);
 | 
					                    return Err(err);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                T::regs().txdr().write(|w| w.set_txdata(*byte));
 | 
					                self.info.regs.txdr().write(|w| w.set_txdata(*byte));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // Wait until the write finishes
 | 
					        // Wait until the write finishes
 | 
				
			||||||
@ -348,6 +358,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
        let last_slice_index = write.len() - 1;
 | 
					        let last_slice_index = write.len() - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if let Err(err) = Self::master_write(
 | 
					        if let Err(err) = Self::master_write(
 | 
				
			||||||
 | 
					            self.info,
 | 
				
			||||||
            address,
 | 
					            address,
 | 
				
			||||||
            first_length.min(255),
 | 
					            first_length.min(255),
 | 
				
			||||||
            Stop::Software,
 | 
					            Stop::Software,
 | 
				
			||||||
@ -370,6 +381,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if idx != 0 {
 | 
					            if idx != 0 {
 | 
				
			||||||
                if let Err(err) = Self::master_continue(
 | 
					                if let Err(err) = Self::master_continue(
 | 
				
			||||||
 | 
					                    self.info,
 | 
				
			||||||
                    slice_len.min(255),
 | 
					                    slice_len.min(255),
 | 
				
			||||||
                    (idx != last_slice_index) || (slice_len > 255),
 | 
					                    (idx != last_slice_index) || (slice_len > 255),
 | 
				
			||||||
                    timeout,
 | 
					                    timeout,
 | 
				
			||||||
@ -382,6 +394,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
            for (number, chunk) in slice.chunks(255).enumerate() {
 | 
					            for (number, chunk) in slice.chunks(255).enumerate() {
 | 
				
			||||||
                if number != 0 {
 | 
					                if number != 0 {
 | 
				
			||||||
                    if let Err(err) = Self::master_continue(
 | 
					                    if let Err(err) = Self::master_continue(
 | 
				
			||||||
 | 
					                        self.info,
 | 
				
			||||||
                        chunk.len(),
 | 
					                        chunk.len(),
 | 
				
			||||||
                        (number != last_chunk_idx) || (idx != last_slice_index),
 | 
					                        (number != last_chunk_idx) || (idx != last_slice_index),
 | 
				
			||||||
                        timeout,
 | 
					                        timeout,
 | 
				
			||||||
@ -402,7 +415,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    // Put byte on the wire
 | 
					                    // Put byte on the wire
 | 
				
			||||||
                    //self.i2c.txdr.write(|w| w.txdata().bits(*byte));
 | 
					                    //self.i2c.txdr.write(|w| w.txdata().bits(*byte));
 | 
				
			||||||
                    T::regs().txdr().write(|w| w.set_txdata(*byte));
 | 
					                    self.info.regs.txdr().write(|w| w.set_txdata(*byte));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -413,7 +426,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
					impl<'d> I2c<'d, Async> {
 | 
				
			||||||
    async fn write_dma_internal(
 | 
					    async fn write_dma_internal(
 | 
				
			||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
        address: u8,
 | 
					        address: u8,
 | 
				
			||||||
@ -425,7 +438,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
        let total_len = write.len();
 | 
					        let total_len = write.len();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let dma_transfer = unsafe {
 | 
					        let dma_transfer = unsafe {
 | 
				
			||||||
            let regs = T::regs();
 | 
					            let regs = self.info.regs;
 | 
				
			||||||
            regs.cr1().modify(|w| {
 | 
					            regs.cr1().modify(|w| {
 | 
				
			||||||
                w.set_txdmaen(true);
 | 
					                w.set_txdmaen(true);
 | 
				
			||||||
                if first_slice {
 | 
					                if first_slice {
 | 
				
			||||||
@ -437,11 +450,10 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
            self.tx_dma.as_mut().unwrap().write(write, dst, Default::default())
 | 
					            self.tx_dma.as_mut().unwrap().write(write, dst, Default::default())
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let state = T::state();
 | 
					 | 
				
			||||||
        let mut remaining_len = total_len;
 | 
					        let mut remaining_len = total_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let on_drop = OnDrop::new(|| {
 | 
					        let on_drop = OnDrop::new(|| {
 | 
				
			||||||
            let regs = T::regs();
 | 
					            let regs = self.info.regs;
 | 
				
			||||||
            regs.cr1().modify(|w| {
 | 
					            regs.cr1().modify(|w| {
 | 
				
			||||||
                if last_slice {
 | 
					                if last_slice {
 | 
				
			||||||
                    w.set_txdmaen(false);
 | 
					                    w.set_txdmaen(false);
 | 
				
			||||||
@ -451,12 +463,13 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        poll_fn(|cx| {
 | 
					        poll_fn(|cx| {
 | 
				
			||||||
            state.waker.register(cx.waker());
 | 
					            self.state.waker.register(cx.waker());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let isr = T::regs().isr().read();
 | 
					            let isr = self.info.regs.isr().read();
 | 
				
			||||||
            if remaining_len == total_len {
 | 
					            if remaining_len == total_len {
 | 
				
			||||||
                if first_slice {
 | 
					                if first_slice {
 | 
				
			||||||
                    Self::master_write(
 | 
					                    Self::master_write(
 | 
				
			||||||
 | 
					                        self.info,
 | 
				
			||||||
                        address,
 | 
					                        address,
 | 
				
			||||||
                        total_len.min(255),
 | 
					                        total_len.min(255),
 | 
				
			||||||
                        Stop::Software,
 | 
					                        Stop::Software,
 | 
				
			||||||
@ -464,8 +477,8 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
                        timeout,
 | 
					                        timeout,
 | 
				
			||||||
                    )?;
 | 
					                    )?;
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, timeout)?;
 | 
					                    Self::master_continue(self.info, total_len.min(255), (total_len > 255) || !last_slice, timeout)?;
 | 
				
			||||||
                    T::regs().cr1().modify(|w| w.set_tcie(true));
 | 
					                    self.info.regs.cr1().modify(|w| w.set_tcie(true));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } 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
 | 
				
			||||||
@ -475,10 +488,10 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
            } 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, timeout) {
 | 
					                if let Err(e) = Self::master_continue(self.info, 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));
 | 
					                self.info.regs.cr1().modify(|w| w.set_tcie(true));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            remaining_len = remaining_len.saturating_sub(255);
 | 
					            remaining_len = remaining_len.saturating_sub(255);
 | 
				
			||||||
@ -509,7 +522,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
        let total_len = buffer.len();
 | 
					        let total_len = buffer.len();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let dma_transfer = unsafe {
 | 
					        let dma_transfer = unsafe {
 | 
				
			||||||
            let regs = T::regs();
 | 
					            let regs = self.info.regs;
 | 
				
			||||||
            regs.cr1().modify(|w| {
 | 
					            regs.cr1().modify(|w| {
 | 
				
			||||||
                w.set_rxdmaen(true);
 | 
					                w.set_rxdmaen(true);
 | 
				
			||||||
                w.set_tcie(true);
 | 
					                w.set_tcie(true);
 | 
				
			||||||
@ -519,11 +532,10 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
            self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
 | 
					            self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let state = T::state();
 | 
					 | 
				
			||||||
        let mut remaining_len = total_len;
 | 
					        let mut remaining_len = total_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let on_drop = OnDrop::new(|| {
 | 
					        let on_drop = OnDrop::new(|| {
 | 
				
			||||||
            let regs = T::regs();
 | 
					            let regs = self.info.regs;
 | 
				
			||||||
            regs.cr1().modify(|w| {
 | 
					            regs.cr1().modify(|w| {
 | 
				
			||||||
                w.set_rxdmaen(false);
 | 
					                w.set_rxdmaen(false);
 | 
				
			||||||
                w.set_tcie(false);
 | 
					                w.set_tcie(false);
 | 
				
			||||||
@ -531,11 +543,12 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        poll_fn(|cx| {
 | 
					        poll_fn(|cx| {
 | 
				
			||||||
            state.waker.register(cx.waker());
 | 
					            self.state.waker.register(cx.waker());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let isr = T::regs().isr().read();
 | 
					            let isr = self.info.regs.isr().read();
 | 
				
			||||||
            if remaining_len == total_len {
 | 
					            if remaining_len == total_len {
 | 
				
			||||||
                Self::master_read(
 | 
					                Self::master_read(
 | 
				
			||||||
 | 
					                    self.info,
 | 
				
			||||||
                    address,
 | 
					                    address,
 | 
				
			||||||
                    total_len.min(255),
 | 
					                    total_len.min(255),
 | 
				
			||||||
                    Stop::Software,
 | 
					                    Stop::Software,
 | 
				
			||||||
@ -551,10 +564,10 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
            } 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, timeout) {
 | 
					                if let Err(e) = Self::master_continue(self.info, 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));
 | 
					                self.info.regs.cr1().modify(|w| w.set_tcie(true));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            remaining_len = remaining_len.saturating_sub(255);
 | 
					            remaining_len = remaining_len.saturating_sub(255);
 | 
				
			||||||
@ -658,9 +671,9 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance, M: Mode> Drop for I2c<'d, T, M> {
 | 
					impl<'d, M: Mode> Drop for I2c<'d, M> {
 | 
				
			||||||
    fn drop(&mut self) {
 | 
					    fn drop(&mut self) {
 | 
				
			||||||
        T::disable();
 | 
					        self.info.enable_bit.disable();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -788,12 +801,12 @@ impl Timings {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance, M: Mode> SetConfig for I2c<'d, T, M> {
 | 
					impl<'d, M: Mode> SetConfig for I2c<'d, M> {
 | 
				
			||||||
    type Config = Hertz;
 | 
					    type Config = Hertz;
 | 
				
			||||||
    type ConfigError = ();
 | 
					    type ConfigError = ();
 | 
				
			||||||
    fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
 | 
					    fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
 | 
				
			||||||
        let timings = Timings::new(T::frequency(), *config);
 | 
					        let timings = Timings::new(self.kernel_clock, *config);
 | 
				
			||||||
        T::regs().timingr().write(|reg| {
 | 
					        self.info.regs.timingr().write(|reg| {
 | 
				
			||||||
            reg.set_presc(timings.prescale);
 | 
					            reg.set_presc(timings.prescale);
 | 
				
			||||||
            reg.set_scll(timings.scll);
 | 
					            reg.set_scll(timings.scll);
 | 
				
			||||||
            reg.set_sclh(timings.sclh);
 | 
					            reg.set_sclh(timings.sclh);
 | 
				
			||||||
 | 
				
			|||||||
@ -208,7 +208,7 @@ impl<'d> I2S<'d> {
 | 
				
			|||||||
            // rate to reach the proper audio sample frequency. The ODD bit in the SPI_I2SPR
 | 
					            // rate to reach the proper audio sample frequency. The ODD bit in the SPI_I2SPR
 | 
				
			||||||
            // register also has to be defined.
 | 
					            // register also has to be defined.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            spi.regs.i2spr().modify(|w| {
 | 
					            spi.info.regs.i2spr().modify(|w| {
 | 
				
			||||||
                w.set_i2sdiv(div);
 | 
					                w.set_i2sdiv(div);
 | 
				
			||||||
                w.set_odd(match odd {
 | 
					                w.set_odd(match odd {
 | 
				
			||||||
                    true => Odd::ODD,
 | 
					                    true => Odd::ODD,
 | 
				
			||||||
@ -235,7 +235,7 @@ impl<'d> I2S<'d> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            // 5. The I2SE bit in SPI_I2SCFGR register must be set.
 | 
					            // 5. The I2SE bit in SPI_I2SCFGR register must be set.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            spi.regs.i2scfgr().modify(|w| {
 | 
					            spi.info.regs.i2scfgr().modify(|w| {
 | 
				
			||||||
                w.set_ckpol(config.clock_polarity.ckpol());
 | 
					                w.set_ckpol(config.clock_polarity.ckpol());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                w.set_i2smod(true);
 | 
					                w.set_i2smod(true);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,16 +1,25 @@
 | 
				
			|||||||
#![macro_use]
 | 
					#![macro_use]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
macro_rules! peri_trait {
 | 
					macro_rules! peri_trait {
 | 
				
			||||||
    () => {
 | 
					    (
 | 
				
			||||||
 | 
					        $(irqs: [$($irq:ident),*],)?
 | 
				
			||||||
 | 
					    ) => {
 | 
				
			||||||
        #[allow(private_interfaces)]
 | 
					        #[allow(private_interfaces)]
 | 
				
			||||||
        pub(crate) trait SealedInstance {
 | 
					        pub(crate) trait SealedInstance {
 | 
				
			||||||
            const INFO: Info;
 | 
					            #[allow(unused)]
 | 
				
			||||||
            const STATE: &'static State;
 | 
					            fn info() -> &'static Info;
 | 
				
			||||||
 | 
					            #[allow(unused)]
 | 
				
			||||||
 | 
					            fn state() -> &'static State;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// SPI instance trait.
 | 
					        /// Peripheral instance trait.
 | 
				
			||||||
        #[allow(private_bounds)]
 | 
					        #[allow(private_bounds)]
 | 
				
			||||||
        pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {}
 | 
					        pub trait Instance: crate::Peripheral<P = Self> + SealedInstance + crate::rcc::RccPeripheral {
 | 
				
			||||||
 | 
					            $($(
 | 
				
			||||||
 | 
					                /// Interrupt for this peripheral.
 | 
				
			||||||
 | 
					                type $irq: crate::interrupt::typelevel::Interrupt;
 | 
				
			||||||
 | 
					            )*)?
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -18,8 +27,14 @@ macro_rules! peri_trait_impl {
 | 
				
			|||||||
    ($instance:ident, $info:expr) => {
 | 
					    ($instance:ident, $info:expr) => {
 | 
				
			||||||
        #[allow(private_interfaces)]
 | 
					        #[allow(private_interfaces)]
 | 
				
			||||||
        impl SealedInstance for crate::peripherals::$instance {
 | 
					        impl SealedInstance for crate::peripherals::$instance {
 | 
				
			||||||
            const INFO: Info = $info;
 | 
					            fn info() -> &'static Info {
 | 
				
			||||||
            const STATE: &'static State = &State::new();
 | 
					                static INFO: Info = $info;
 | 
				
			||||||
 | 
					                &INFO
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            fn state() -> &'static State {
 | 
				
			||||||
 | 
					                static STATE: State = State::new();
 | 
				
			||||||
 | 
					                &STATE
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        impl Instance for crate::peripherals::$instance {}
 | 
					        impl Instance for crate::peripherals::$instance {}
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
				
			|||||||
@ -67,10 +67,11 @@ pub(crate) unsafe fn get_freqs() -> &'static Clocks {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub(crate) trait SealedRccPeripheral {
 | 
					pub(crate) trait SealedRccPeripheral {
 | 
				
			||||||
 | 
					    const ENABLE_BIT: ClockEnableBit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn frequency() -> Hertz;
 | 
					    fn frequency() -> Hertz;
 | 
				
			||||||
    fn enable_and_reset_with_cs(cs: CriticalSection);
 | 
					    fn enable_and_reset_with_cs(cs: CriticalSection);
 | 
				
			||||||
    fn disable_with_cs(cs: CriticalSection);
 | 
					    fn disable_with_cs(cs: CriticalSection);
 | 
				
			||||||
    fn enable_bit() -> ClockEnableBit;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn enable_and_reset() {
 | 
					    fn enable_and_reset() {
 | 
				
			||||||
        critical_section::with(|cs| Self::enable_and_reset_with_cs(cs))
 | 
					        critical_section::with(|cs| Self::enable_and_reset_with_cs(cs))
 | 
				
			||||||
@ -151,7 +152,7 @@ pub(crate) struct ClockEnableBit {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl ClockEnableBit {
 | 
					impl ClockEnableBit {
 | 
				
			||||||
    /// Safety: offset+bit must correspond to a valid xxxEN bit.
 | 
					    /// Safety: offset+bit must correspond to a valid xxxEN bit.
 | 
				
			||||||
    pub(crate) unsafe fn new(offset: u8, bit: u8) -> Self {
 | 
					    pub(crate) const unsafe fn new(offset: u8, bit: u8) -> Self {
 | 
				
			||||||
        Self { offset, bit }
 | 
					        Self { offset, bit }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@ use crate::dma::{slice_ptr_parts, word, ChannelAndRequest};
 | 
				
			|||||||
use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
 | 
					use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
 | 
				
			||||||
use crate::mode::{Async, Blocking, Mode as PeriMode};
 | 
					use crate::mode::{Async, Blocking, Mode as PeriMode};
 | 
				
			||||||
use crate::pac::spi::{regs, vals, Spi as Regs};
 | 
					use crate::pac::spi::{regs, vals, Spi as Regs};
 | 
				
			||||||
use crate::rcc::{ClockEnableBit, RccPeripheral};
 | 
					use crate::rcc::{ClockEnableBit, SealedRccPeripheral};
 | 
				
			||||||
use crate::time::Hertz;
 | 
					use crate::time::Hertz;
 | 
				
			||||||
use crate::Peripheral;
 | 
					use crate::Peripheral;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -93,8 +93,7 @@ impl Config {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
/// SPI driver.
 | 
					/// SPI driver.
 | 
				
			||||||
pub struct Spi<'d, M: PeriMode> {
 | 
					pub struct Spi<'d, M: PeriMode> {
 | 
				
			||||||
    pub(crate) regs: Regs,
 | 
					    pub(crate) info: &'static Info,
 | 
				
			||||||
    enable_bit: ClockEnableBit,
 | 
					 | 
				
			||||||
    kernel_clock: Hertz,
 | 
					    kernel_clock: Hertz,
 | 
				
			||||||
    sck: Option<PeripheralRef<'d, AnyPin>>,
 | 
					    sck: Option<PeripheralRef<'d, AnyPin>>,
 | 
				
			||||||
    mosi: Option<PeripheralRef<'d, AnyPin>>,
 | 
					    mosi: Option<PeripheralRef<'d, AnyPin>>,
 | 
				
			||||||
@ -115,7 +114,7 @@ impl<'d, M: PeriMode> Spi<'d, M> {
 | 
				
			|||||||
        rx_dma: Option<ChannelAndRequest<'d>>,
 | 
					        rx_dma: Option<ChannelAndRequest<'d>>,
 | 
				
			||||||
        config: Config,
 | 
					        config: Config,
 | 
				
			||||||
    ) -> Self {
 | 
					    ) -> Self {
 | 
				
			||||||
        let regs = T::INFO.regs;
 | 
					        let regs = T::info().regs;
 | 
				
			||||||
        let kernel_clock = T::frequency();
 | 
					        let kernel_clock = T::frequency();
 | 
				
			||||||
        let br = compute_baud_rate(kernel_clock, config.frequency);
 | 
					        let br = compute_baud_rate(kernel_clock, config.frequency);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -205,8 +204,7 @@ impl<'d, M: PeriMode> Spi<'d, M> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            regs,
 | 
					            info: T::info(),
 | 
				
			||||||
            enable_bit: T::enable_bit(),
 | 
					 | 
				
			||||||
            kernel_clock,
 | 
					            kernel_clock,
 | 
				
			||||||
            sck,
 | 
					            sck,
 | 
				
			||||||
            mosi,
 | 
					            mosi,
 | 
				
			||||||
@ -228,7 +226,7 @@ impl<'d, M: PeriMode> Spi<'d, M> {
 | 
				
			|||||||
        let br = compute_baud_rate(self.kernel_clock, config.frequency);
 | 
					        let br = compute_baud_rate(self.kernel_clock, config.frequency);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #[cfg(any(spi_v1, spi_f1, spi_v2))]
 | 
					        #[cfg(any(spi_v1, spi_f1, spi_v2))]
 | 
				
			||||||
        self.regs.cr1().modify(|w| {
 | 
					        self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
            w.set_cpha(cpha);
 | 
					            w.set_cpha(cpha);
 | 
				
			||||||
            w.set_cpol(cpol);
 | 
					            w.set_cpol(cpol);
 | 
				
			||||||
            w.set_br(br);
 | 
					            w.set_br(br);
 | 
				
			||||||
@ -237,12 +235,12 @@ impl<'d, M: PeriMode> Spi<'d, M> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        #[cfg(any(spi_v3, spi_v4, spi_v5))]
 | 
					        #[cfg(any(spi_v3, spi_v4, spi_v5))]
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            self.regs.cfg2().modify(|w| {
 | 
					            self.info.regs.cfg2().modify(|w| {
 | 
				
			||||||
                w.set_cpha(cpha);
 | 
					                w.set_cpha(cpha);
 | 
				
			||||||
                w.set_cpol(cpol);
 | 
					                w.set_cpol(cpol);
 | 
				
			||||||
                w.set_lsbfirst(lsbfirst);
 | 
					                w.set_lsbfirst(lsbfirst);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            self.regs.cfg1().modify(|w| {
 | 
					            self.info.regs.cfg1().modify(|w| {
 | 
				
			||||||
                w.set_mbr(br);
 | 
					                w.set_mbr(br);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -252,11 +250,11 @@ impl<'d, M: PeriMode> Spi<'d, M> {
 | 
				
			|||||||
    /// Get current SPI configuration.
 | 
					    /// Get current SPI configuration.
 | 
				
			||||||
    pub fn get_current_config(&self) -> Config {
 | 
					    pub fn get_current_config(&self) -> Config {
 | 
				
			||||||
        #[cfg(any(spi_v1, spi_f1, spi_v2))]
 | 
					        #[cfg(any(spi_v1, spi_f1, spi_v2))]
 | 
				
			||||||
        let cfg = self.regs.cr1().read();
 | 
					        let cfg = self.info.regs.cr1().read();
 | 
				
			||||||
        #[cfg(any(spi_v3, spi_v4, spi_v5))]
 | 
					        #[cfg(any(spi_v3, spi_v4, spi_v5))]
 | 
				
			||||||
        let cfg = self.regs.cfg2().read();
 | 
					        let cfg = self.info.regs.cfg2().read();
 | 
				
			||||||
        #[cfg(any(spi_v3, spi_v4, spi_v5))]
 | 
					        #[cfg(any(spi_v3, spi_v4, spi_v5))]
 | 
				
			||||||
        let cfg1 = self.regs.cfg1().read();
 | 
					        let cfg1 = self.info.regs.cfg1().read();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let polarity = if cfg.cpol() == vals::Cpol::IDLELOW {
 | 
					        let polarity = if cfg.cpol() == vals::Cpol::IDLELOW {
 | 
				
			||||||
            Polarity::IdleLow
 | 
					            Polarity::IdleLow
 | 
				
			||||||
@ -296,40 +294,40 @@ impl<'d, M: PeriMode> Spi<'d, M> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        #[cfg(any(spi_v1, spi_f1))]
 | 
					        #[cfg(any(spi_v1, spi_f1))]
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            self.regs.cr1().modify(|reg| {
 | 
					            self.info.regs.cr1().modify(|reg| {
 | 
				
			||||||
                reg.set_spe(false);
 | 
					                reg.set_spe(false);
 | 
				
			||||||
                reg.set_dff(word_size)
 | 
					                reg.set_dff(word_size)
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            self.regs.cr1().modify(|reg| {
 | 
					            self.info.regs.cr1().modify(|reg| {
 | 
				
			||||||
                reg.set_spe(true);
 | 
					                reg.set_spe(true);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        #[cfg(spi_v2)]
 | 
					        #[cfg(spi_v2)]
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            self.regs.cr1().modify(|w| {
 | 
					            self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
                w.set_spe(false);
 | 
					                w.set_spe(false);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            self.regs.cr2().modify(|w| {
 | 
					            self.info.regs.cr2().modify(|w| {
 | 
				
			||||||
                w.set_frxth(word_size.1);
 | 
					                w.set_frxth(word_size.1);
 | 
				
			||||||
                w.set_ds(word_size.0);
 | 
					                w.set_ds(word_size.0);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            self.regs.cr1().modify(|w| {
 | 
					            self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
                w.set_spe(true);
 | 
					                w.set_spe(true);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        #[cfg(any(spi_v3, spi_v4, spi_v5))]
 | 
					        #[cfg(any(spi_v3, spi_v4, spi_v5))]
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            self.regs.cr1().modify(|w| {
 | 
					            self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
                w.set_csusp(true);
 | 
					                w.set_csusp(true);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            while self.regs.sr().read().eot() {}
 | 
					            while self.info.regs.sr().read().eot() {}
 | 
				
			||||||
            self.regs.cr1().modify(|w| {
 | 
					            self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
                w.set_spe(false);
 | 
					                w.set_spe(false);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            self.regs.cfg1().modify(|w| {
 | 
					            self.info.regs.cfg1().modify(|w| {
 | 
				
			||||||
                w.set_dsize(word_size);
 | 
					                w.set_dsize(word_size);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            self.regs.cr1().modify(|w| {
 | 
					            self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
                w.set_csusp(false);
 | 
					                w.set_csusp(false);
 | 
				
			||||||
                w.set_spe(true);
 | 
					                w.set_spe(true);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
@ -340,22 +338,22 @@ impl<'d, M: PeriMode> Spi<'d, M> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /// Blocking write.
 | 
					    /// Blocking write.
 | 
				
			||||||
    pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> {
 | 
					    pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> {
 | 
				
			||||||
        self.regs.cr1().modify(|w| w.set_spe(true));
 | 
					        self.info.regs.cr1().modify(|w| w.set_spe(true));
 | 
				
			||||||
        flush_rx_fifo(self.regs);
 | 
					        flush_rx_fifo(self.info.regs);
 | 
				
			||||||
        self.set_word_size(W::CONFIG);
 | 
					        self.set_word_size(W::CONFIG);
 | 
				
			||||||
        for word in words.iter() {
 | 
					        for word in words.iter() {
 | 
				
			||||||
            let _ = transfer_word(self.regs, *word)?;
 | 
					            let _ = transfer_word(self.info.regs, *word)?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Blocking read.
 | 
					    /// Blocking read.
 | 
				
			||||||
    pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
 | 
					    pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
 | 
				
			||||||
        self.regs.cr1().modify(|w| w.set_spe(true));
 | 
					        self.info.regs.cr1().modify(|w| w.set_spe(true));
 | 
				
			||||||
        flush_rx_fifo(self.regs);
 | 
					        flush_rx_fifo(self.info.regs);
 | 
				
			||||||
        self.set_word_size(W::CONFIG);
 | 
					        self.set_word_size(W::CONFIG);
 | 
				
			||||||
        for word in words.iter_mut() {
 | 
					        for word in words.iter_mut() {
 | 
				
			||||||
            *word = transfer_word(self.regs, W::default())?;
 | 
					            *word = transfer_word(self.info.regs, W::default())?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -364,11 +362,11 @@ impl<'d, M: PeriMode> Spi<'d, M> {
 | 
				
			|||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// This writes the contents of `data` on MOSI, and puts the received data on MISO in `data`, at the same time.
 | 
					    /// This writes the contents of `data` on MOSI, and puts the received data on MISO in `data`, at the same time.
 | 
				
			||||||
    pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
 | 
					    pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
 | 
				
			||||||
        self.regs.cr1().modify(|w| w.set_spe(true));
 | 
					        self.info.regs.cr1().modify(|w| w.set_spe(true));
 | 
				
			||||||
        flush_rx_fifo(self.regs);
 | 
					        flush_rx_fifo(self.info.regs);
 | 
				
			||||||
        self.set_word_size(W::CONFIG);
 | 
					        self.set_word_size(W::CONFIG);
 | 
				
			||||||
        for word in words.iter_mut() {
 | 
					        for word in words.iter_mut() {
 | 
				
			||||||
            *word = transfer_word(self.regs, *word)?;
 | 
					            *word = transfer_word(self.info.regs, *word)?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -380,13 +378,13 @@ impl<'d, M: PeriMode> Spi<'d, M> {
 | 
				
			|||||||
    /// The transfer runs for `max(read.len(), write.len())` bytes. If `read` is shorter extra bytes are ignored.
 | 
					    /// The transfer runs for `max(read.len(), write.len())` bytes. If `read` is shorter extra bytes are ignored.
 | 
				
			||||||
    /// If `write` is shorter it is padded with zero bytes.
 | 
					    /// If `write` is shorter it is padded with zero bytes.
 | 
				
			||||||
    pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> {
 | 
					    pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> {
 | 
				
			||||||
        self.regs.cr1().modify(|w| w.set_spe(true));
 | 
					        self.info.regs.cr1().modify(|w| w.set_spe(true));
 | 
				
			||||||
        flush_rx_fifo(self.regs);
 | 
					        flush_rx_fifo(self.info.regs);
 | 
				
			||||||
        self.set_word_size(W::CONFIG);
 | 
					        self.set_word_size(W::CONFIG);
 | 
				
			||||||
        let len = read.len().max(write.len());
 | 
					        let len = read.len().max(write.len());
 | 
				
			||||||
        for i in 0..len {
 | 
					        for i in 0..len {
 | 
				
			||||||
            let wb = write.get(i).copied().unwrap_or_default();
 | 
					            let wb = write.get(i).copied().unwrap_or_default();
 | 
				
			||||||
            let rb = transfer_word(self.regs, wb)?;
 | 
					            let rb = transfer_word(self.info.regs, wb)?;
 | 
				
			||||||
            if let Some(r) = read.get_mut(i) {
 | 
					            if let Some(r) = read.get_mut(i) {
 | 
				
			||||||
                *r = rb;
 | 
					                *r = rb;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -588,25 +586,25 @@ impl<'d> Spi<'d, Async> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.set_word_size(W::CONFIG);
 | 
					        self.set_word_size(W::CONFIG);
 | 
				
			||||||
        self.regs.cr1().modify(|w| {
 | 
					        self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
            w.set_spe(false);
 | 
					            w.set_spe(false);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let tx_dst = self.regs.tx_ptr();
 | 
					        let tx_dst = self.info.regs.tx_ptr();
 | 
				
			||||||
        let tx_f = unsafe { self.tx_dma.as_mut().unwrap().write(data, tx_dst, Default::default()) };
 | 
					        let tx_f = unsafe { self.tx_dma.as_mut().unwrap().write(data, tx_dst, Default::default()) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        set_txdmaen(self.regs, true);
 | 
					        set_txdmaen(self.info.regs, true);
 | 
				
			||||||
        self.regs.cr1().modify(|w| {
 | 
					        self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
            w.set_spe(true);
 | 
					            w.set_spe(true);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        #[cfg(any(spi_v3, spi_v4, spi_v5))]
 | 
					        #[cfg(any(spi_v3, spi_v4, spi_v5))]
 | 
				
			||||||
        self.regs.cr1().modify(|w| {
 | 
					        self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
            w.set_cstart(true);
 | 
					            w.set_cstart(true);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tx_f.await;
 | 
					        tx_f.await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        finish_dma(self.regs);
 | 
					        finish_dma(self.info.regs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -618,22 +616,22 @@ impl<'d> Spi<'d, Async> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.set_word_size(W::CONFIG);
 | 
					        self.set_word_size(W::CONFIG);
 | 
				
			||||||
        self.regs.cr1().modify(|w| {
 | 
					        self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
            w.set_spe(false);
 | 
					            w.set_spe(false);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // SPIv3 clears rxfifo on SPE=0
 | 
					        // SPIv3 clears rxfifo on SPE=0
 | 
				
			||||||
        #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
 | 
					        #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
 | 
				
			||||||
        flush_rx_fifo(self.regs);
 | 
					        flush_rx_fifo(self.info.regs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        set_rxdmaen(self.regs, true);
 | 
					        set_rxdmaen(self.info.regs, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let clock_byte_count = data.len();
 | 
					        let clock_byte_count = data.len();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let rx_src = self.regs.rx_ptr();
 | 
					        let rx_src = self.info.regs.rx_ptr();
 | 
				
			||||||
        let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read(rx_src, data, Default::default()) };
 | 
					        let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read(rx_src, data, Default::default()) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let tx_dst = self.regs.tx_ptr();
 | 
					        let tx_dst = self.info.regs.tx_ptr();
 | 
				
			||||||
        let clock_byte = 0x00u8;
 | 
					        let clock_byte = 0x00u8;
 | 
				
			||||||
        let tx_f = unsafe {
 | 
					        let tx_f = unsafe {
 | 
				
			||||||
            self.tx_dma
 | 
					            self.tx_dma
 | 
				
			||||||
@ -642,18 +640,18 @@ impl<'d> Spi<'d, Async> {
 | 
				
			|||||||
                .write_repeated(&clock_byte, clock_byte_count, tx_dst, Default::default())
 | 
					                .write_repeated(&clock_byte, clock_byte_count, tx_dst, Default::default())
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        set_txdmaen(self.regs, true);
 | 
					        set_txdmaen(self.info.regs, true);
 | 
				
			||||||
        self.regs.cr1().modify(|w| {
 | 
					        self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
            w.set_spe(true);
 | 
					            w.set_spe(true);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        #[cfg(any(spi_v3, spi_v4, spi_v5))]
 | 
					        #[cfg(any(spi_v3, spi_v4, spi_v5))]
 | 
				
			||||||
        self.regs.cr1().modify(|w| {
 | 
					        self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
            w.set_cstart(true);
 | 
					            w.set_cstart(true);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        join(tx_f, rx_f).await;
 | 
					        join(tx_f, rx_f).await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        finish_dma(self.regs);
 | 
					        finish_dma(self.info.regs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -667,20 +665,20 @@ impl<'d> Spi<'d, Async> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.set_word_size(W::CONFIG);
 | 
					        self.set_word_size(W::CONFIG);
 | 
				
			||||||
        self.regs.cr1().modify(|w| {
 | 
					        self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
            w.set_spe(false);
 | 
					            w.set_spe(false);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // SPIv3 clears rxfifo on SPE=0
 | 
					        // SPIv3 clears rxfifo on SPE=0
 | 
				
			||||||
        #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
 | 
					        #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
 | 
				
			||||||
        flush_rx_fifo(self.regs);
 | 
					        flush_rx_fifo(self.info.regs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        set_rxdmaen(self.regs, true);
 | 
					        set_rxdmaen(self.info.regs, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let rx_src = self.regs.rx_ptr();
 | 
					        let rx_src = self.info.regs.rx_ptr();
 | 
				
			||||||
        let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) };
 | 
					        let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let tx_dst = self.regs.tx_ptr();
 | 
					        let tx_dst = self.info.regs.tx_ptr();
 | 
				
			||||||
        let tx_f = unsafe {
 | 
					        let tx_f = unsafe {
 | 
				
			||||||
            self.tx_dma
 | 
					            self.tx_dma
 | 
				
			||||||
                .as_mut()
 | 
					                .as_mut()
 | 
				
			||||||
@ -688,18 +686,18 @@ impl<'d> Spi<'d, Async> {
 | 
				
			|||||||
                .write_raw(write, tx_dst, Default::default())
 | 
					                .write_raw(write, tx_dst, Default::default())
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        set_txdmaen(self.regs, true);
 | 
					        set_txdmaen(self.info.regs, true);
 | 
				
			||||||
        self.regs.cr1().modify(|w| {
 | 
					        self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
            w.set_spe(true);
 | 
					            w.set_spe(true);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        #[cfg(any(spi_v3, spi_v4, spi_v5))]
 | 
					        #[cfg(any(spi_v3, spi_v4, spi_v5))]
 | 
				
			||||||
        self.regs.cr1().modify(|w| {
 | 
					        self.info.regs.cr1().modify(|w| {
 | 
				
			||||||
            w.set_cstart(true);
 | 
					            w.set_cstart(true);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        join(tx_f, rx_f).await;
 | 
					        join(tx_f, rx_f).await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        finish_dma(self.regs);
 | 
					        finish_dma(self.info.regs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -728,7 +726,7 @@ impl<'d, M: PeriMode> Drop for Spi<'d, M> {
 | 
				
			|||||||
        self.mosi.as_ref().map(|x| x.set_as_disconnected());
 | 
					        self.mosi.as_ref().map(|x| x.set_as_disconnected());
 | 
				
			||||||
        self.miso.as_ref().map(|x| x.set_as_disconnected());
 | 
					        self.miso.as_ref().map(|x| x.set_as_disconnected());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.enable_bit.disable();
 | 
					        self.info.enable_bit.disable();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1106,8 +1104,9 @@ mod word_impl {
 | 
				
			|||||||
    impl_word!(u32, 32 - 1);
 | 
					    impl_word!(u32, 32 - 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Info {
 | 
					pub(crate) struct Info {
 | 
				
			||||||
    regs: Regs,
 | 
					    pub(crate) regs: Regs,
 | 
				
			||||||
 | 
					    pub(crate) enable_bit: ClockEnableBit,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct State {}
 | 
					struct State {}
 | 
				
			||||||
@ -1134,6 +1133,7 @@ foreach_peripheral!(
 | 
				
			|||||||
    (spi, $inst:ident) => {
 | 
					    (spi, $inst:ident) => {
 | 
				
			||||||
        peri_trait_impl!($inst, Info {
 | 
					        peri_trait_impl!($inst, Info {
 | 
				
			||||||
            regs: crate::pac::$inst,
 | 
					            regs: crate::pac::$inst,
 | 
				
			||||||
 | 
					            enable_bit: crate::peripherals::$inst::ENABLE_BIT,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
				
			|||||||
@ -6,11 +6,10 @@ use core::cell::RefCell;
 | 
				
			|||||||
use defmt::*;
 | 
					use defmt::*;
 | 
				
			||||||
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
 | 
					use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
 | 
				
			||||||
use embassy_executor::Spawner;
 | 
					use embassy_executor::Spawner;
 | 
				
			||||||
use embassy_stm32::bind_interrupts;
 | 
					 | 
				
			||||||
use embassy_stm32::i2c::{self, I2c};
 | 
					use embassy_stm32::i2c::{self, I2c};
 | 
				
			||||||
use embassy_stm32::mode::Async;
 | 
					use embassy_stm32::mode::Async;
 | 
				
			||||||
use embassy_stm32::peripherals::{self, I2C1};
 | 
					 | 
				
			||||||
use embassy_stm32::time::Hertz;
 | 
					use embassy_stm32::time::Hertz;
 | 
				
			||||||
 | 
					use embassy_stm32::{bind_interrupts, peripherals};
 | 
				
			||||||
use embassy_sync::blocking_mutex::NoopMutex;
 | 
					use embassy_sync::blocking_mutex::NoopMutex;
 | 
				
			||||||
use embassy_time::{Duration, Timer};
 | 
					use embassy_time::{Duration, Timer};
 | 
				
			||||||
use static_cell::StaticCell;
 | 
					use static_cell::StaticCell;
 | 
				
			||||||
@ -24,7 +23,7 @@ const SHTC3_WAKEUP: [u8; 2] = [0x35, 0x17];
 | 
				
			|||||||
const SHTC3_MEASURE_RH_FIRST: [u8; 2] = [0x5c, 0x24];
 | 
					const SHTC3_MEASURE_RH_FIRST: [u8; 2] = [0x5c, 0x24];
 | 
				
			||||||
const SHTC3_SLEEP: [u8; 2] = [0xb0, 0x98];
 | 
					const SHTC3_SLEEP: [u8; 2] = [0xb0, 0x98];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static I2C_BUS: StaticCell<NoopMutex<RefCell<I2c<'static, I2C1, Async>>>> = StaticCell::new();
 | 
					static I2C_BUS: StaticCell<NoopMutex<RefCell<I2c<'static, Async>>>> = StaticCell::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bind_interrupts!(struct Irqs {
 | 
					bind_interrupts!(struct Irqs {
 | 
				
			||||||
    I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
 | 
					    I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
 | 
				
			||||||
 | 
				
			|||||||
@ -60,7 +60,7 @@ pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>;
 | 
				
			|||||||
pub type SpeInt = exti::ExtiInput<'static>;
 | 
					pub type SpeInt = exti::ExtiInput<'static>;
 | 
				
			||||||
pub type SpeRst = Output<'static>;
 | 
					pub type SpeRst = Output<'static>;
 | 
				
			||||||
pub type Adin1110T = ADIN1110<SpeSpiCs>;
 | 
					pub type Adin1110T = ADIN1110<SpeSpiCs>;
 | 
				
			||||||
pub type TempSensI2c = I2c<'static, peripherals::I2C3, Async>;
 | 
					pub type TempSensI2c = I2c<'static, Async>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static TEMP: AtomicI32 = AtomicI32::new(0);
 | 
					static TEMP: AtomicI32 = AtomicI32::new(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user