From 6a508b32101b0af1a77624ef0a22c72c972b1b74 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis <dirbaio@dirbaio.net> Date: Tue, 21 May 2024 01:24:10 +0200 Subject: [PATCH 1/2] stm32: use funcs for info/state, const for ENABLE_BIT. --- embassy-stm32/build.rs | 6 +- embassy-stm32/src/i2s.rs | 4 +- embassy-stm32/src/macros.rs | 16 +++-- embassy-stm32/src/rcc/mod.rs | 5 +- embassy-stm32/src/spi/mod.rs | 122 +++++++++++++++++------------------ 5 files changed, 81 insertions(+), 72 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index f17c6bef6..e615c6307 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -653,9 +653,9 @@ fn main() { crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); #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 {} diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index c102c0035..c78810a38 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs @@ -208,7 +208,7 @@ impl<'d> I2S<'d> { // rate to reach the proper audio sample frequency. The ODD bit in the SPI_I2SPR // register also has to be defined. - spi.regs.i2spr().modify(|w| { + spi.info.regs.i2spr().modify(|w| { w.set_i2sdiv(div); w.set_odd(match odd { true => Odd::ODD, @@ -235,7 +235,7 @@ impl<'d> I2S<'d> { // 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_i2smod(true); diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs index 9c459a932..6a5691181 100644 --- a/embassy-stm32/src/macros.rs +++ b/embassy-stm32/src/macros.rs @@ -4,8 +4,10 @@ macro_rules! peri_trait { () => { #[allow(private_interfaces)] pub(crate) trait SealedInstance { - const INFO: Info; - const STATE: &'static State; + #[allow(unused)] + fn info() -> &'static Info; + #[allow(unused)] + fn state() -> &'static State; } /// SPI instance trait. @@ -18,8 +20,14 @@ macro_rules! peri_trait_impl { ($instance:ident, $info:expr) => { #[allow(private_interfaces)] impl SealedInstance for crate::peripherals::$instance { - const INFO: Info = $info; - const STATE: &'static State = &State::new(); + fn info() -> &'static Info { + static INFO: Info = $info; + &INFO + } + fn state() -> &'static State { + static STATE: State = State::new(); + &STATE + } } impl Instance for crate::peripherals::$instance {} }; diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index c413b62ef..28816256c 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -67,10 +67,11 @@ pub(crate) unsafe fn get_freqs() -> &'static Clocks { } pub(crate) trait SealedRccPeripheral { + const ENABLE_BIT: ClockEnableBit; + fn frequency() -> Hertz; fn enable_and_reset_with_cs(cs: CriticalSection); fn disable_with_cs(cs: CriticalSection); - fn enable_bit() -> ClockEnableBit; fn enable_and_reset() { critical_section::with(|cs| Self::enable_and_reset_with_cs(cs)) @@ -151,7 +152,7 @@ pub(crate) struct ClockEnableBit { impl ClockEnableBit { /// 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 } } diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 5a2ee105d..0875cfe41 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -13,7 +13,7 @@ use crate::dma::{slice_ptr_parts, word, ChannelAndRequest}; use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed}; use crate::mode::{Async, Blocking, Mode as PeriMode}; 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::Peripheral; @@ -93,8 +93,7 @@ impl Config { } /// SPI driver. pub struct Spi<'d, M: PeriMode> { - pub(crate) regs: Regs, - enable_bit: ClockEnableBit, + pub(crate) info: &'static Info, kernel_clock: Hertz, sck: 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>>, config: Config, ) -> Self { - let regs = T::INFO.regs; + let regs = T::info().regs; let kernel_clock = T::frequency(); let br = compute_baud_rate(kernel_clock, config.frequency); @@ -205,8 +204,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { } Self { - regs, - enable_bit: T::enable_bit(), + info: T::info(), kernel_clock, sck, mosi, @@ -228,7 +226,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { let br = compute_baud_rate(self.kernel_clock, config.frequency); #[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_cpol(cpol); w.set_br(br); @@ -237,12 +235,12 @@ impl<'d, M: PeriMode> Spi<'d, M> { #[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_cpol(cpol); w.set_lsbfirst(lsbfirst); }); - self.regs.cfg1().modify(|w| { + self.info.regs.cfg1().modify(|w| { w.set_mbr(br); }); } @@ -252,11 +250,11 @@ impl<'d, M: PeriMode> Spi<'d, M> { /// Get current SPI configuration. pub fn get_current_config(&self) -> Config { #[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))] - let cfg = self.regs.cfg2().read(); + let cfg = self.info.regs.cfg2().read(); #[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 { Polarity::IdleLow @@ -296,40 +294,40 @@ impl<'d, M: PeriMode> Spi<'d, M> { #[cfg(any(spi_v1, spi_f1))] { - self.regs.cr1().modify(|reg| { + self.info.regs.cr1().modify(|reg| { reg.set_spe(false); reg.set_dff(word_size) }); - self.regs.cr1().modify(|reg| { + self.info.regs.cr1().modify(|reg| { reg.set_spe(true); }); } #[cfg(spi_v2)] { - self.regs.cr1().modify(|w| { + self.info.regs.cr1().modify(|w| { w.set_spe(false); }); - self.regs.cr2().modify(|w| { + self.info.regs.cr2().modify(|w| { w.set_frxth(word_size.1); w.set_ds(word_size.0); }); - self.regs.cr1().modify(|w| { + self.info.regs.cr1().modify(|w| { w.set_spe(true); }); } #[cfg(any(spi_v3, spi_v4, spi_v5))] { - self.regs.cr1().modify(|w| { + self.info.regs.cr1().modify(|w| { w.set_csusp(true); }); - while self.regs.sr().read().eot() {} - self.regs.cr1().modify(|w| { + while self.info.regs.sr().read().eot() {} + self.info.regs.cr1().modify(|w| { w.set_spe(false); }); - self.regs.cfg1().modify(|w| { + self.info.regs.cfg1().modify(|w| { w.set_dsize(word_size); }); - self.regs.cr1().modify(|w| { + self.info.regs.cr1().modify(|w| { w.set_csusp(false); w.set_spe(true); }); @@ -340,22 +338,22 @@ impl<'d, M: PeriMode> Spi<'d, M> { /// Blocking write. pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> { - self.regs.cr1().modify(|w| w.set_spe(true)); - flush_rx_fifo(self.regs); + self.info.regs.cr1().modify(|w| w.set_spe(true)); + flush_rx_fifo(self.info.regs); self.set_word_size(W::CONFIG); for word in words.iter() { - let _ = transfer_word(self.regs, *word)?; + let _ = transfer_word(self.info.regs, *word)?; } Ok(()) } /// Blocking read. pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> { - self.regs.cr1().modify(|w| w.set_spe(true)); - flush_rx_fifo(self.regs); + self.info.regs.cr1().modify(|w| w.set_spe(true)); + flush_rx_fifo(self.info.regs); self.set_word_size(W::CONFIG); for word in words.iter_mut() { - *word = transfer_word(self.regs, W::default())?; + *word = transfer_word(self.info.regs, W::default())?; } 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. pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> { - self.regs.cr1().modify(|w| w.set_spe(true)); - flush_rx_fifo(self.regs); + self.info.regs.cr1().modify(|w| w.set_spe(true)); + flush_rx_fifo(self.info.regs); self.set_word_size(W::CONFIG); for word in words.iter_mut() { - *word = transfer_word(self.regs, *word)?; + *word = transfer_word(self.info.regs, *word)?; } 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. /// 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> { - self.regs.cr1().modify(|w| w.set_spe(true)); - flush_rx_fifo(self.regs); + self.info.regs.cr1().modify(|w| w.set_spe(true)); + flush_rx_fifo(self.info.regs); self.set_word_size(W::CONFIG); let len = read.len().max(write.len()); for i in 0..len { 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) { *r = rb; } @@ -588,25 +586,25 @@ impl<'d> Spi<'d, Async> { } self.set_word_size(W::CONFIG); - self.regs.cr1().modify(|w| { + self.info.regs.cr1().modify(|w| { 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()) }; - set_txdmaen(self.regs, true); - self.regs.cr1().modify(|w| { + set_txdmaen(self.info.regs, true); + self.info.regs.cr1().modify(|w| { w.set_spe(true); }); #[cfg(any(spi_v3, spi_v4, spi_v5))] - self.regs.cr1().modify(|w| { + self.info.regs.cr1().modify(|w| { w.set_cstart(true); }); tx_f.await; - finish_dma(self.regs); + finish_dma(self.info.regs); Ok(()) } @@ -618,22 +616,22 @@ impl<'d> Spi<'d, Async> { } self.set_word_size(W::CONFIG); - self.regs.cr1().modify(|w| { + self.info.regs.cr1().modify(|w| { w.set_spe(false); }); // SPIv3 clears rxfifo on SPE=0 #[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 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 tx_dst = self.regs.tx_ptr(); + let tx_dst = self.info.regs.tx_ptr(); let clock_byte = 0x00u8; let tx_f = unsafe { self.tx_dma @@ -642,18 +640,18 @@ impl<'d> Spi<'d, Async> { .write_repeated(&clock_byte, clock_byte_count, tx_dst, Default::default()) }; - set_txdmaen(self.regs, true); - self.regs.cr1().modify(|w| { + set_txdmaen(self.info.regs, true); + self.info.regs.cr1().modify(|w| { w.set_spe(true); }); #[cfg(any(spi_v3, spi_v4, spi_v5))] - self.regs.cr1().modify(|w| { + self.info.regs.cr1().modify(|w| { w.set_cstart(true); }); join(tx_f, rx_f).await; - finish_dma(self.regs); + finish_dma(self.info.regs); Ok(()) } @@ -667,20 +665,20 @@ impl<'d> Spi<'d, Async> { } self.set_word_size(W::CONFIG); - self.regs.cr1().modify(|w| { + self.info.regs.cr1().modify(|w| { w.set_spe(false); }); // SPIv3 clears rxfifo on SPE=0 #[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 tx_dst = self.regs.tx_ptr(); + let tx_dst = self.info.regs.tx_ptr(); let tx_f = unsafe { self.tx_dma .as_mut() @@ -688,18 +686,18 @@ impl<'d> Spi<'d, Async> { .write_raw(write, tx_dst, Default::default()) }; - set_txdmaen(self.regs, true); - self.regs.cr1().modify(|w| { + set_txdmaen(self.info.regs, true); + self.info.regs.cr1().modify(|w| { w.set_spe(true); }); #[cfg(any(spi_v3, spi_v4, spi_v5))] - self.regs.cr1().modify(|w| { + self.info.regs.cr1().modify(|w| { w.set_cstart(true); }); join(tx_f, rx_f).await; - finish_dma(self.regs); + finish_dma(self.info.regs); 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.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); } -struct Info { - regs: Regs, +pub(crate) struct Info { + pub(crate) regs: Regs, + pub(crate) enable_bit: ClockEnableBit, } struct State {} @@ -1134,6 +1133,7 @@ foreach_peripheral!( (spi, $inst:ident) => { peri_trait_impl!($inst, Info { regs: crate::pac::$inst, + enable_bit: crate::peripherals::$inst::ENABLE_BIT, }); }; ); From 45a12fd41f1f6230a4aabbfe87552adc610fdc99 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis <dirbaio@dirbaio.net> Date: Tue, 21 May 2024 01:25:49 +0200 Subject: [PATCH 2/2] stm32/i2c: remove peripheral generic param. --- embassy-stm32/src/i2c/mod.rs | 68 ++++--- embassy-stm32/src/i2c/v1.rs | 184 +++++++++--------- embassy-stm32/src/i2c/v2.rs | 129 ++++++------ embassy-stm32/src/macros.rs | 13 +- examples/stm32h7/src/bin/i2c_shared.rs | 5 +- .../src/bin/spe_adin1110_http_server.rs | 2 +- 6 files changed, 210 insertions(+), 191 deletions(-) diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 0b2a56305..ef5fd0972 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -9,7 +9,7 @@ use core::future::Future; use core::iter; use core::marker::PhantomData; -use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; +use embassy_hal_internal::{into_ref, Peripheral}; use embassy_sync::waitqueue::AtomicWaker; #[cfg(feature = "time")] use embassy_time::{Duration, Instant}; @@ -18,6 +18,7 @@ use crate::dma::ChannelAndRequest; use crate::gpio::{AFType, Pull}; use crate::interrupt::typelevel::Interrupt; use crate::mode::{Async, Blocking, Mode}; +use crate::rcc::{ClockEnableBit, SealedRccPeripheral}; use crate::time::Hertz; use crate::{interrupt, peripherals}; @@ -72,8 +73,10 @@ impl Default for Config { } /// I2C driver. -pub struct I2c<'d, T: Instance, M: Mode> { - _peri: PeripheralRef<'d, T>, +pub struct I2c<'d, M: Mode> { + info: &'static Info, + state: &'static State, + kernel_clock: Hertz, tx_dma: Option<ChannelAndRequest<'d>>, rx_dma: Option<ChannelAndRequest<'d>>, #[cfg(feature = "time")] @@ -81,9 +84,9 @@ pub struct I2c<'d, T: Instance, M: Mode> { _phantom: PhantomData<M>, } -impl<'d, T: Instance> I2c<'d, T, Async> { +impl<'d> I2c<'d, Async> { /// Create a new I2C driver. - pub fn new( + pub fn new<T: Instance>( peri: impl Peripheral<P = T> + 'd, scl: impl Peripheral<P = impl SclPin<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. - pub fn new_blocking( + pub fn new_blocking<T: Instance>( peri: impl Peripheral<P = T> + 'd, scl: impl Peripheral<P = impl SclPin<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. - fn new_inner( - peri: impl Peripheral<P = T> + 'd, + fn new_inner<T: Instance>( + _peri: impl Peripheral<P = T> + 'd, scl: impl Peripheral<P = impl SclPin<T>> + 'd, sda: impl Peripheral<P = impl SdaPin<T>> + 'd, tx_dma: Option<ChannelAndRequest<'d>>, @@ -123,7 +126,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { freq: Hertz, config: Config, ) -> Self { - into_ref!(peri, scl, sda); + into_ref!(scl, sda); T::enable_and_reset(); @@ -148,7 +151,9 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { unsafe { T::ErrorInterrupt::enable() }; let mut this = Self { - _peri: peri, + info: T::info(), + state: T::state(), + kernel_clock: T::frequency(), tx_dma, rx_dma, #[cfg(feature = "time")] @@ -217,19 +222,14 @@ impl State { } } -trait SealedInstance: crate::rcc::RccPeripheral { - fn regs() -> crate::pac::i2c::I2c; - fn state() -> &'static State; +struct Info { + regs: crate::pac::i2c::I2c, + pub(crate) enable_bit: ClockEnableBit, } -/// I2C peripheral instance -#[allow(private_bounds)] -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; -} +peri_trait!( + irqs: [EventInterrupt, ErrorInterrupt], +); pin_trait!(SclPin, Instance); pin_trait!(SdaPin, Instance); @@ -260,11 +260,15 @@ impl<T: Instance> interrupt::typelevel::Handler<T::ErrorInterrupt> for ErrorInte foreach_peripheral!( (i2c, $inst:ident) => { + #[allow(private_interfaces)] impl SealedInstance for peripherals::$inst { - fn regs() -> crate::pac::i2c::I2c { - crate::pac::$inst + fn info() -> &'static Info { + static INFO: Info = Info{ + regs: crate::pac::$inst, + enable_bit: crate::peripherals::$inst::ENABLE_BIT, + }; + &INFO } - fn state() -> &'static State { static STATE: State = State::new(); &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; 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; 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; 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; } -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> { 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> { self.read(address, read).await } diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index ac4fa1b9e..0269e53aa 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -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 // hit a case like this! 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 // other stuff, so we wake the task on every interrupt. 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) { - T::regs().cr1().modify(|reg| { + self.info.regs.cr1().modify(|reg| { reg.set_pe(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 // 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); }); - T::regs().cr1().modify(|reg| { + self.info.regs.cr1().modify(|reg| { 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); }); - T::regs().ccr().modify(|reg| { + self.info.regs.ccr().modify(|reg| { reg.set_f_s(timings.mode.f_s()); reg.set_duty(timings.duty.duty()); reg.set_ccr(timings.ccr); }); - T::regs().trise().modify(|reg| { + self.info.regs.trise().modify(|reg| { reg.set_trise(timings.trise); }); - T::regs().cr1().modify(|reg| { + self.info.regs.cr1().modify(|reg| { 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 // 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() { - T::regs().sr1().write(|reg| { + info.regs.sr1().write(|reg| { reg.0 = !0; reg.set_timeout(false); }); @@ -107,7 +107,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> { } if sr1.pecerr() { - T::regs().sr1().write(|reg| { + info.regs.sr1().write(|reg| { reg.0 = !0; reg.set_pecerr(false); }); @@ -115,7 +115,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> { } if sr1.ovr() { - T::regs().sr1().write(|reg| { + info.regs.sr1().write(|reg| { reg.0 = !0; reg.set_ovr(false); }); @@ -123,7 +123,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> { } if sr1.af() { - T::regs().sr1().write(|reg| { + info.regs.sr1().write(|reg| { reg.0 = !0; reg.set_af(false); }); @@ -131,7 +131,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> { } if sr1.arlo() { - T::regs().sr1().write(|reg| { + info.regs.sr1().write(|reg| { reg.0 = !0; 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 // clearing the BERR bit instead. if sr1.berr() { - T::regs().sr1().write(|reg| { + info.regs.sr1().write(|reg| { reg.0 = !0; reg.set_berr(false); }); @@ -154,32 +154,32 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> { if frame.send_start() { // Send a START condition - T::regs().cr1().modify(|reg| { + self.info.regs.cr1().modify(|reg| { reg.set_start(true); }); // 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()?; } // 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); } // 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 for the address to be acknowledged // 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()?; } // Clear condition by reading SR2 - let _ = T::regs().sr2().read(); + let _ = self.info.regs.sr2().read(); } // Send bytes @@ -189,7 +189,7 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> { if frame.send_stop() { // 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 @@ -200,18 +200,18 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> { // Wait until we're ready for sending while { // 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()?; } // 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 while { // Check for any potential error conditions. - !Self::check_and_clear_error_flags()?.btf() + !Self::check_and_clear_error_flags(self.info)?.btf() } { 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> { while { // 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()?; } - let value = T::regs().dr().read().dr(); + let value = self.info.regs.dr().read().dr(); Ok(value) } @@ -246,32 +246,32 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> { if frame.send_start() { // 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_ack(true); }); // 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()?; } // 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); } // 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 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()?; } // Clear condition by reading SR2 - let _ = T::regs().sr2().read(); + let _ = self.info.regs.sr2().read(); } // 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 - T::regs().cr1().modify(|reg| { + self.info.regs.cr1().modify(|reg| { if frame.send_nack() { reg.set_ack(false); } @@ -346,17 +346,17 @@ impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> { // Async #[inline] // pretty sure this should always be inlined - fn enable_interrupts() -> () { - T::regs().cr2().modify(|w| { + fn enable_interrupts(info: &'static Info) -> () { + info.regs.cr2().modify(|w| { w.set_iterren(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> { - 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 // reception. 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. // TODO: Generate STOP condition on cancel? let on_drop = OnDrop::new(|| { - T::regs().cr2().modify(|w| { + self.info.regs.cr2().modify(|w| { w.set_dmaen(false); w.set_iterren(false); w.set_itevten(false); }) }); - let state = T::state(); - if frame.send_start() { // Send a START condition - T::regs().cr1().modify(|reg| { + self.info.regs.cr1().modify(|reg| { reg.set_start(true); }); // Wait until START condition was generated 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)), Ok(sr1) => { if sr1.start() { Poll::Ready(Ok(())) } else { // When pending, (re-)enable interrupts to wake us up. - Self::enable_interrupts(); + Self::enable_interrupts(self.info); Poll::Pending } } @@ -405,25 +403,25 @@ impl<'d, T: Instance> I2c<'d, T, Async> { .await?; // 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); } // 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 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)), Ok(sr1) => { if sr1.addr() { Poll::Ready(Ok(())) } else { // When pending, (re-)enable interrupts to wake us up. - Self::enable_interrupts(); + Self::enable_interrupts(self.info); Poll::Pending } } @@ -432,26 +430,26 @@ impl<'d, T: Instance> I2c<'d, T, Async> { .await?; // Clear condition by reading SR2 - T::regs().sr2().read(); + self.info.regs.sr2().read(); } let dma_transfer = unsafe { // 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. - 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()) }; // Wait for bytes to be sent, or an error to occur. 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)), Ok(_) => { // When pending, (re-)enable interrupts to wake us up. - Self::enable_interrupts(); + Self::enable_interrupts(self.info); Poll::Pending } } @@ -463,7 +461,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { _ => Ok(()), }?; - T::regs().cr2().modify(|w| { + self.info.regs.cr2().modify(|w| { 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 // requests then wait for a BTF event before programming the Stop condition.” 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)), Ok(sr1) => { if sr1.btf() { Poll::Ready(Ok(())) } else { // When pending, (re-)enable interrupts to wake us up. - Self::enable_interrupts(); + Self::enable_interrupts(self.info); Poll::Pending } } @@ -490,7 +488,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { }) .await?; - T::regs().cr1().modify(|w| { + self.info.regs.cr1().modify(|w| { 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. 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 // reception. 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. // TODO: Generate STOP condition on cancel? let on_drop = OnDrop::new(|| { - T::regs().cr2().modify(|w| { + self.info.regs.cr2().modify(|w| { w.set_dmaen(false); w.set_iterren(false); w.set_itevten(false); }) }); - let state = T::state(); - if frame.send_start() { // 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_ack(true); }); // Wait until START condition was generated 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)), Ok(sr1) => { if sr1.start() { Poll::Ready(Ok(())) } else { // When pending, (re-)enable interrupts to wake us up. - Self::enable_interrupts(); + Self::enable_interrupts(self.info); Poll::Pending } } @@ -577,25 +573,25 @@ impl<'d, T: Instance> I2c<'d, T, Async> { .await?; // 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); } // 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 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)), Ok(sr1) => { if sr1.addr() { Poll::Ready(Ok(())) } else { // When pending, (re-)enable interrupts to wake us up. - Self::enable_interrupts(); + Self::enable_interrupts(self.info); 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 // event, i.e. program ACK=0 when ADDR=1, before clearing ADDR flag. if frame.send_nack() && single_byte { - T::regs().cr1().modify(|w| { + self.info.regs.cr1().modify(|w| { w.set_ack(false); }); } // Clear condition by reading SR2 - T::regs().sr2().read(); + self.info.regs.sr2().read(); } else { // 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. if frame.send_nack() && single_byte { - T::regs().cr1().modify(|w| { + self.info.regs.cr1().modify(|w| { 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 // routine. if frame.send_stop() && single_byte { - T::regs().cr1().modify(|w| { + self.info.regs.cr1().modify(|w| { w.set_stop(true); }); } @@ -635,20 +631,20 @@ impl<'d, T: Instance> I2c<'d, T, Async> { let dma_transfer = unsafe { // 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. - 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()) }; // Wait for bytes to be received, or an error to occur. 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)), _ => { // When pending, (re-)enable interrupts to wake us up. - Self::enable_interrupts(); + Self::enable_interrupts(self.info); Poll::Pending } } @@ -659,12 +655,12 @@ impl<'d, T: Instance> I2c<'d, T, Async> { _ => Ok(()), }?; - T::regs().cr2().modify(|w| { + self.info.regs.cr2().modify(|w| { w.set_dmaen(false); }); if frame.send_stop() && !single_byte { - T::regs().cr1().modify(|w| { + self.info.regs.cr1().modify(|w| { 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) { - 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 ConfigError = (); fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { - let timings = Timings::new(T::frequency(), *config); - T::regs().cr2().modify(|reg| { + let timings = Timings::new(self.kernel_clock, *config); + self.info.regs.cr2().modify(|reg| { 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_duty(timings.duty.duty()); reg.set_ccr(timings.ccr); }); - T::regs().trise().modify(|reg| { + self.info.regs.trise().modify(|reg| { reg.set_trise(timings.trise); }); diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 12df98534..aa6daf786 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -10,7 +10,7 @@ use super::*; use crate::pac::i2c; pub(crate) unsafe fn on_interrupt<T: Instance>() { - let regs = T::regs(); + let regs = T::info().regs; let isr = regs.isr().read(); 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) { - T::regs().cr1().modify(|reg| { + self.info.regs.cr1().modify(|reg| { reg.set_pe(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_scll(timings.scll); reg.set_sclh(timings.sclh); @@ -40,16 +40,17 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { reg.set_scldel(timings.scldel); }); - T::regs().cr1().modify(|reg| { + self.info.regs.cr1().modify(|reg| { reg.set_pe(true); }); } 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( + info: &'static Info, address: u8, length: usize, stop: Stop, @@ -63,7 +64,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { // Wait for any previous address sequence to end // automatically. This could be up to 50% of a bus // cycle (ie. up to 0.5/freq) - while T::regs().cr2().read().start() { + while info.regs.cr2().read().start() { timeout.check()?; } } @@ -78,7 +79,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { i2c::vals::Reload::COMPLETED }; - T::regs().cr2().modify(|w| { + info.regs.cr2().modify(|w| { w.set_sadd((address << 1 | 0) as u16); w.set_add10(i2c::vals::Addmode::BIT7); w.set_dir(i2c::vals::Dir::READ); @@ -91,13 +92,20 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { 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); // Wait for any previous address sequence to end // automatically. This could be up to 50% of a bus // cycle (ie. up to 0.5/freq) - while T::regs().cr2().read().start() { + while info.regs.cr2().read().start() { timeout.check()?; } @@ -110,7 +118,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { // Set START and prepare to send `bytes`. The // START bit can be set even if the bus is BUSY or // 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_add10(i2c::vals::Addmode::BIT7); w.set_dir(i2c::vals::Dir::WRITE); @@ -123,10 +131,10 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { 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); - while !T::regs().isr().read().tcr() { + while !info.regs.isr().read().tcr() { timeout.check()?; } @@ -136,7 +144,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { i2c::vals::Reload::COMPLETED }; - T::regs().cr2().modify(|w| { + info.regs.cr2().modify(|w| { w.set_nbytes(length as u8); w.set_reload(reload); }); @@ -145,27 +153,27 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { } fn flush_txdr(&self) { - if T::regs().isr().read().txis() { - T::regs().txdr().write(|w| w.set_txdata(0)); + if self.info.regs.isr().read().txis() { + self.info.regs.txdr().write(|w| w.set_txdata(0)); } - if !T::regs().isr().read().txe() { - T::regs().isr().modify(|w| w.set_txe(true)) + if !self.info.regs.isr().read().txe() { + self.info.regs.isr().modify(|w| w.set_txe(true)) } } fn wait_txe(&self, timeout: Timeout) -> Result<(), Error> { loop { - let isr = T::regs().isr().read(); + let isr = self.info.regs.isr().read(); if isr.txe() { return Ok(()); } 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); } 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); } 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(); 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> { loop { - let isr = T::regs().isr().read(); + let isr = self.info.regs.isr().read(); if isr.rxne() { return Ok(()); } 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); } 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); } 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(); 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> { loop { - let isr = T::regs().isr().read(); + let isr = self.info.regs.isr().read(); if isr.tc() { return Ok(()); } 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); } 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); } 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(); 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); Self::master_read( + self.info, address, read.len().min(255), 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() { 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 { // Wait until we have received something self.wait_rxne(timeout)?; - *byte = T::regs().rxdr().read().rxdata(); + *byte = self.info.regs.rxdr().read().rxdata(); } } Ok(()) @@ -262,6 +271,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { // // ST SAD+W if let Err(err) = Self::master_write( + self.info, address, write.len().min(255), Stop::Software, @@ -276,7 +286,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { for (number, chunk) in write.chunks(255).enumerate() { 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 { @@ -290,7 +300,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { 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 @@ -348,6 +358,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { let last_slice_index = write.len() - 1; if let Err(err) = Self::master_write( + self.info, address, first_length.min(255), Stop::Software, @@ -370,6 +381,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { if idx != 0 { if let Err(err) = Self::master_continue( + self.info, slice_len.min(255), (idx != last_slice_index) || (slice_len > 255), timeout, @@ -382,6 +394,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { for (number, chunk) in slice.chunks(255).enumerate() { if number != 0 { if let Err(err) = Self::master_continue( + self.info, chunk.len(), (number != last_chunk_idx) || (idx != last_slice_index), timeout, @@ -402,7 +415,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { // Put byte on the wire //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( &mut self, address: u8, @@ -425,7 +438,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { let total_len = write.len(); let dma_transfer = unsafe { - let regs = T::regs(); + let regs = self.info.regs; regs.cr1().modify(|w| { w.set_txdmaen(true); 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()) }; - let state = T::state(); let mut remaining_len = total_len; let on_drop = OnDrop::new(|| { - let regs = T::regs(); + let regs = self.info.regs; regs.cr1().modify(|w| { if last_slice { w.set_txdmaen(false); @@ -451,12 +463,13 @@ impl<'d, T: Instance> I2c<'d, T, Async> { }); 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 first_slice { Self::master_write( + self.info, address, total_len.min(255), Stop::Software, @@ -464,8 +477,8 @@ impl<'d, T: Instance> I2c<'d, T, Async> { timeout, )?; } else { - Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, timeout)?; - T::regs().cr1().modify(|w| w.set_tcie(true)); + Self::master_continue(self.info, total_len.min(255), (total_len > 255) || !last_slice, timeout)?; + self.info.regs.cr1().modify(|w| w.set_tcie(true)); } } else if !(isr.tcr() || isr.tc()) { // poll_fn was woken without an interrupt present @@ -475,10 +488,10 @@ impl<'d, T: Instance> I2c<'d, T, Async> { } else { 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)); } - 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); @@ -509,7 +522,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { let total_len = buffer.len(); let dma_transfer = unsafe { - let regs = T::regs(); + let regs = self.info.regs; regs.cr1().modify(|w| { w.set_rxdmaen(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()) }; - let state = T::state(); let mut remaining_len = total_len; let on_drop = OnDrop::new(|| { - let regs = T::regs(); + let regs = self.info.regs; regs.cr1().modify(|w| { w.set_rxdmaen(false); w.set_tcie(false); @@ -531,11 +543,12 @@ impl<'d, T: Instance> I2c<'d, T, Async> { }); 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 { Self::master_read( + self.info, address, total_len.min(255), Stop::Software, @@ -551,10 +564,10 @@ impl<'d, T: Instance> I2c<'d, T, Async> { } else { 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)); } - 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); @@ -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) { - 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 ConfigError = (); fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { - let timings = Timings::new(T::frequency(), *config); - T::regs().timingr().write(|reg| { + let timings = Timings::new(self.kernel_clock, *config); + self.info.regs.timingr().write(|reg| { reg.set_presc(timings.prescale); reg.set_scll(timings.scll); reg.set_sclh(timings.sclh); diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs index 6a5691181..7f8076043 100644 --- a/embassy-stm32/src/macros.rs +++ b/embassy-stm32/src/macros.rs @@ -1,7 +1,9 @@ #![macro_use] macro_rules! peri_trait { - () => { + ( + $(irqs: [$($irq:ident),*],)? + ) => { #[allow(private_interfaces)] pub(crate) trait SealedInstance { #[allow(unused)] @@ -10,9 +12,14 @@ macro_rules! peri_trait { fn state() -> &'static State; } - /// SPI instance trait. + /// Peripheral instance trait. #[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; + )*)? + } }; } diff --git a/examples/stm32h7/src/bin/i2c_shared.rs b/examples/stm32h7/src/bin/i2c_shared.rs index 79d213ae4..6f4815582 100644 --- a/examples/stm32h7/src/bin/i2c_shared.rs +++ b/examples/stm32h7/src/bin/i2c_shared.rs @@ -6,11 +6,10 @@ use core::cell::RefCell; use defmt::*; use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice; use embassy_executor::Spawner; -use embassy_stm32::bind_interrupts; use embassy_stm32::i2c::{self, I2c}; use embassy_stm32::mode::Async; -use embassy_stm32::peripherals::{self, I2C1}; use embassy_stm32::time::Hertz; +use embassy_stm32::{bind_interrupts, peripherals}; use embassy_sync::blocking_mutex::NoopMutex; use embassy_time::{Duration, Timer}; 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_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 { I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>; diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index 985ac8171..33149144c 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs @@ -60,7 +60,7 @@ pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>; pub type SpeInt = exti::ExtiInput<'static>; pub type SpeRst = Output<'static>; 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);