From 5e3221bcc47bc1ce30eaf8d347377d652dbba7e2 Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Fri, 8 Aug 2025 23:01:11 +0800 Subject: i2c --- embassy-stm32/src/i2c/config.rs | 14 ++++++++++---- embassy-stm32/src/i2c/mod.rs | 11 +++-------- embassy-stm32/src/i2c/v1.rs | 18 +++++++++--------- embassy-stm32/src/i2c/v2.rs | 4 ++-- 4 files changed, 24 insertions(+), 23 deletions(-) (limited to 'embassy-stm32') diff --git a/embassy-stm32/src/i2c/config.rs b/embassy-stm32/src/i2c/config.rs index daae43bcd..0b4e091b8 100644 --- a/embassy-stm32/src/i2c/config.rs +++ b/embassy-stm32/src/i2c/config.rs @@ -109,6 +109,10 @@ impl SlaveAddrConfig { #[non_exhaustive] #[derive(Copy, Clone)] pub struct Config { + /// Frequency + pub frequency: Hertz, + /// GPIO Speed + pub gpio_speed: Speed, /// Enable internal pullup on SDA. /// /// Using external pullup resistors is recommended for I2C. If you do @@ -129,6 +133,8 @@ pub struct Config { impl Default for Config { fn default() -> Self { Self { + frequency: Hertz::khz(100), + gpio_speed: Speed::Medium, #[cfg(gpio_v2)] sda_pullup: false, #[cfg(gpio_v2)] @@ -142,11 +148,11 @@ impl Default for Config { impl Config { pub(super) fn scl_af(&self) -> AfType { #[cfg(gpio_v1)] - return AfType::output(OutputType::OpenDrain, Speed::Medium); + return AfType::output(OutputType::OpenDrain, self.gpio_speed); #[cfg(gpio_v2)] return AfType::output_pull( OutputType::OpenDrain, - Speed::Medium, + self.gpio_speed, match self.scl_pullup { true => Pull::Up, false => Pull::Down, @@ -156,11 +162,11 @@ impl Config { pub(super) fn sda_af(&self) -> AfType { #[cfg(gpio_v1)] - return AfType::output(OutputType::OpenDrain, Speed::Medium); + return AfType::output(OutputType::OpenDrain, self.gpio_speed); #[cfg(gpio_v2)] return AfType::output_pull( OutputType::OpenDrain, - Speed::Medium, + self.gpio_speed, match self.sda_pullup { true => Pull::Up, false => Pull::Down, diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 825dd240c..5fb49f943 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -158,7 +158,6 @@ impl<'d> I2c<'d, Async, Master> { + 'd, tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, - freq: Hertz, config: Config, ) -> Self { Self::new_inner( @@ -167,7 +166,6 @@ impl<'d> I2c<'d, Async, Master> { new_pin!(sda, config.sda_af()), new_dma!(tx_dma), new_dma!(rx_dma), - freq, config, ) } @@ -179,7 +177,6 @@ impl<'d> I2c<'d, Blocking, Master> { peri: Peri<'d, T>, scl: Peri<'d, impl SclPin>, sda: Peri<'d, impl SdaPin>, - freq: Hertz, config: Config, ) -> Self { Self::new_inner( @@ -188,7 +185,6 @@ impl<'d> I2c<'d, Blocking, Master> { new_pin!(sda, config.sda_af()), None, None, - freq, config, ) } @@ -202,7 +198,6 @@ impl<'d, M: Mode> I2c<'d, M, Master> { sda: Option>, tx_dma: Option>, rx_dma: Option>, - freq: Hertz, config: Config, ) -> Self { unsafe { T::EventInterrupt::enable() }; @@ -224,14 +219,14 @@ impl<'d, M: Mode> I2c<'d, M, Master> { sda, }, }; - this.enable_and_init(freq, config); + this.enable_and_init(config); this } - fn enable_and_init(&mut self, freq: Hertz, config: Config) { + fn enable_and_init(&mut self, config: Config) { self.info.rcc.enable_and_reset(); - self.init(freq, config); + self.init(config); } } diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index 35f13ab46..081eb1191 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -43,7 +43,7 @@ pub unsafe fn on_interrupt() { } impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> { - pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { + pub(crate) fn init(&mut self, config: Config) { self.info.regs.cr1().modify(|reg| { reg.set_pe(false); //reg.set_anfoff(false); @@ -75,7 +75,7 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> { reg.set_swrst(false); }); - let timings = Timings::new(self.kernel_clock, freq); + let timings = Timings::new(self.kernel_clock, config.frequency); self.info.regs.cr2().modify(|reg| { reg.set_freq(timings.freq); @@ -738,15 +738,15 @@ struct Timings { } impl Timings { - fn new(i2cclk: Hertz, speed: Hertz) -> Self { + fn new(i2cclk: Hertz, frequency: Hertz) -> Self { // Calculate settings for I2C speed modes - let speed = speed.0; + let frequency = frequency.0; let clock = i2cclk.0; let freq = clock / 1_000_000; assert!((2..=50).contains(&freq)); // Configure bus frequency into I2C peripheral - let trise = if speed <= 100_000 { + let trise = if frequency <= 100_000 { freq + 1 } else { (freq * 300) / 1000 + 1 @@ -757,11 +757,11 @@ impl Timings { let mode; // I2C clock control calculation - if speed <= 100_000 { + if frequency <= 100_000 { duty = Duty::Duty2_1; mode = Mode::Standard; ccr = { - let ccr = clock / (speed * 2); + let ccr = clock / (frequency * 2); if ccr < 4 { 4 } else { @@ -773,13 +773,13 @@ impl Timings { mode = Mode::Fast; if DUTYCYCLE == 0 { duty = Duty::Duty2_1; - ccr = clock / (speed * 3); + ccr = clock / (frequency * 3); ccr = if ccr < 1 { 1 } else { ccr }; // Set clock to fast mode with appropriate parameters for selected speed (2:1 duty cycle) } else { duty = Duty::Duty16_9; - ccr = clock / (speed * 25); + ccr = clock / (frequency * 25); ccr = if ccr < 1 { 1 } else { ccr }; // Set clock to fast mode with appropriate parameters for selected speed (16:9 duty cycle) diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index e24cce5c6..76f0d25dc 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -93,13 +93,13 @@ pub(crate) unsafe fn on_interrupt() { } impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { - pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { + pub(crate) fn init(&mut self, config: Config) { self.info.regs.cr1().modify(|reg| { reg.set_pe(false); reg.set_anfoff(false); }); - let timings = Timings::new(self.kernel_clock, freq.into()); + let timings = Timings::new(self.kernel_clock, config.frequency.into()); self.info.regs.timingr().write(|reg| { reg.set_presc(timings.prescale); -- cgit