aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHybridChild <[email protected]>2025-07-27 12:25:03 +0200
committerHybridChild <[email protected]>2025-08-23 08:50:49 +0200
commit593fb963b84741bb05d1cae1dbacafb92b4828c6 (patch)
treebe0fffbc371ceec9d94ec1d62626bfeb175309e5
parentb690a0314f0f2e42137ad4b3e867e056c1d3c14e (diff)
stm32/i2c: Add temporary trait for version-specific initialization during v1 rework
-rw-r--r--embassy-stm32/src/i2c/mod.rs22
-rw-r--r--embassy-stm32/src/i2c/v1.rs38
-rw-r--r--embassy-stm32/src/i2c/v2.rs4
3 files changed, 55 insertions, 9 deletions
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index 58225d937..660b8144a 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -29,6 +29,21 @@ use crate::rcc::{RccInfo, SealedRccPeripheral};
29use crate::time::Hertz; 29use crate::time::Hertz;
30use crate::{interrupt, peripherals}; 30use crate::{interrupt, peripherals};
31 31
32/// Temporary trait for version-specific initialization during I2C v1 async rework.
33///
34/// This trait allows the shared constructor in mod.rs to call version-specific
35/// initialization while we incrementally migrate v1 async operations to use
36/// the new event-driven interrupt pattern. Will be removed once the rework
37/// is complete and both blocking/async modes use unified initialization.
38pub trait VersionSpecificInit {
39 /// Performs version and mode-specific initialization.
40 ///
41 /// For v1: Sets interrupt pattern flag based on blocking vs async mode.
42 /// For v2: No-op, does nothing.
43 fn version_specific_init(&mut self);
44}
45
46
32/// I2C error. 47/// I2C error.
33#[derive(Debug, PartialEq, Eq, Copy, Clone)] 48#[derive(Debug, PartialEq, Eq, Copy, Clone)]
34#[cfg_attr(feature = "defmt", derive(defmt::Format))] 49#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -192,7 +207,10 @@ impl<'d> I2c<'d, Blocking, Master> {
192 } 207 }
193} 208}
194 209
195impl<'d, M: Mode> I2c<'d, M, Master> { 210impl<'d, M: Mode> I2c<'d, M, Master>
211where
212 Self: VersionSpecificInit
213{
196 /// Create a new I2C driver. 214 /// Create a new I2C driver.
197 fn new_inner<T: Instance>( 215 fn new_inner<T: Instance>(
198 _peri: Peri<'d, T>, 216 _peri: Peri<'d, T>,
@@ -221,7 +239,9 @@ impl<'d, M: Mode> I2c<'d, M, Master> {
221 sda, 239 sda,
222 }, 240 },
223 }; 241 };
242
224 this.enable_and_init(config); 243 this.enable_and_init(config);
244 this.version_specific_init();
225 245
226 this 246 this
227 } 247 }
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index 78abb85ea..eaf787334 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -6,6 +6,7 @@
6 6
7use core::future::poll_fn; 7use core::future::poll_fn;
8use core::task::Poll; 8use core::task::Poll;
9use core::sync::atomic::{AtomicBool, Ordering};
9 10
10use embassy_embedded_hal::SetConfig; 11use embassy_embedded_hal::SetConfig;
11use embassy_futures::select::{select, Either}; 12use embassy_futures::select::{select, Either};
@@ -22,12 +23,14 @@ use embassy_sync::waitqueue::AtomicWaker;
22/// I2C v2 peripheral state 23/// I2C v2 peripheral state
23pub(crate) struct State { 24pub(crate) struct State {
24 pub(crate) waker: AtomicWaker, 25 pub(crate) waker: AtomicWaker,
26 pub use_new_interrupt_pattern: AtomicBool,
25} 27}
26 28
27impl State { 29impl State {
28 pub(crate) const fn new() -> Self { 30 pub(crate) const fn new() -> Self {
29 Self { 31 Self {
30 waker: AtomicWaker::new(), 32 waker: AtomicWaker::new(),
33 use_new_interrupt_pattern: AtomicBool::new(false),
31 } 34 }
32 } 35 }
33} 36}
@@ -44,17 +47,25 @@ impl State {
44// There's some more details there, and we might have a fix for you. But please let us know if you 47// There's some more details there, and we might have a fix for you. But please let us know if you
45// hit a case like this! 48// hit a case like this!
46pub unsafe fn on_interrupt<T: Instance>() { 49pub unsafe fn on_interrupt<T: Instance>() {
47 let regs = T::info().regs;
48 // i2c v2 only woke the task on transfer complete interrupts. v1 uses interrupts for a bunch of 50 // i2c v2 only woke the task on transfer complete interrupts. v1 uses interrupts for a bunch of
49 // other stuff, so we wake the task on every interrupt. 51 // other stuff, so we wake the task on every interrupt.
50 T::state().waker.wake(); 52
51 critical_section::with(|_| { 53 let regs = T::info().regs;
52 // Clear event interrupt flag. 54 let state = T::state();
53 regs.cr2().modify(|w| { 55
54 w.set_itevten(false); 56 if state.use_new_interrupt_pattern.load(Ordering::Relaxed) {
55 w.set_iterren(false); 57
58 } else {
59 critical_section::with(|_| {
60 // Clear event interrupt flag.
61 regs.cr2().modify(|w| {
62 w.set_itevten(false);
63 w.set_iterren(false);
64 });
56 }); 65 });
57 }); 66 }
67
68 state.waker.wake();
58} 69}
59 70
60impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { 71impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
@@ -716,6 +727,17 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
716 } 727 }
717} 728}
718 729
730impl<'d> VersionSpecificInit for I2c<'d, Blocking, Master> {
731 fn version_specific_init(&mut self) {
732 self.state.use_new_interrupt_pattern.store(false, Ordering::Relaxed);
733 }
734}
735
736impl<'d> VersionSpecificInit for I2c<'d, Async, Master> {
737 fn version_specific_init(&mut self) {
738 self.state.use_new_interrupt_pattern.store(true, Ordering::Relaxed);
739 }
740}
719 741
720/// Timing configuration for I2C v1 hardware 742/// Timing configuration for I2C v1 hardware
721/// 743///
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 72a7d05ab..f23c58c9e 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -107,6 +107,10 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() {
107 }); 107 });
108} 108}
109 109
110impl<'d, M: Mode> VersionSpecificInit for I2c<'d, M, Master> {
111 fn version_specific_init(&mut self) {}
112}
113
110impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { 114impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
111 pub(crate) fn init(&mut self, config: Config) { 115 pub(crate) fn init(&mut self, config: Config) {
112 self.info.regs.cr1().modify(|reg| { 116 self.info.regs.cr1().modify(|reg| {