aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/i2c/mod.rs33
-rw-r--r--embassy-stm32/src/i2c/v2.rs11
2 files changed, 28 insertions, 16 deletions
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index 3303b9f4b..82e28b3ff 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -162,19 +162,32 @@ pub enum SendStatus {
162 LeftoverBytes(usize), 162 LeftoverBytes(usize),
163} 163}
164 164
165struct I2CDropGuard<'d> {
166 info: &'static Info,
167 scl: Option<PeripheralRef<'d, AnyPin>>,
168 sda: Option<PeripheralRef<'d, AnyPin>>,
169}
170impl<'d> Drop for I2CDropGuard<'d> {
171 fn drop(&mut self) {
172 self.scl.as_ref().map(|x| x.set_as_disconnected());
173 self.sda.as_ref().map(|x| x.set_as_disconnected());
174
175 self.info.rcc.disable();
176 }
177}
178
165/// I2C driver. 179/// I2C driver.
166pub struct I2c<'d, M: Mode, IM: MasterMode> { 180pub struct I2c<'d, M: Mode, IM: MasterMode> {
167 info: &'static Info, 181 info: &'static Info,
168 state: &'static State, 182 state: &'static State,
169 kernel_clock: Hertz, 183 kernel_clock: Hertz,
170 scl: Option<PeripheralRef<'d, AnyPin>>,
171 sda: Option<PeripheralRef<'d, AnyPin>>,
172 tx_dma: Option<ChannelAndRequest<'d>>, 184 tx_dma: Option<ChannelAndRequest<'d>>,
173 rx_dma: Option<ChannelAndRequest<'d>>, 185 rx_dma: Option<ChannelAndRequest<'d>>,
174 #[cfg(feature = "time")] 186 #[cfg(feature = "time")]
175 timeout: Duration, 187 timeout: Duration,
176 _phantom: PhantomData<M>, 188 _phantom: PhantomData<M>,
177 _phantom2: PhantomData<IM>, 189 _phantom2: PhantomData<IM>,
190 drop_guard: I2CDropGuard<'d>,
178} 191}
179 192
180impl<'d> I2c<'d, Async, Master> { 193impl<'d> I2c<'d, Async, Master> {
@@ -242,14 +255,17 @@ impl<'d, M: Mode> I2c<'d, M, Master> {
242 info: T::info(), 255 info: T::info(),
243 state: T::state(), 256 state: T::state(),
244 kernel_clock: T::frequency(), 257 kernel_clock: T::frequency(),
245 scl,
246 sda,
247 tx_dma, 258 tx_dma,
248 rx_dma, 259 rx_dma,
249 #[cfg(feature = "time")] 260 #[cfg(feature = "time")]
250 timeout: config.timeout, 261 timeout: config.timeout,
251 _phantom: PhantomData, 262 _phantom: PhantomData,
252 _phantom2: PhantomData, 263 _phantom2: PhantomData,
264 drop_guard: I2CDropGuard {
265 info: T::info(),
266 scl,
267 sda,
268 },
253 }; 269 };
254 this.enable_and_init(freq, config); 270 this.enable_and_init(freq, config);
255 271
@@ -271,15 +287,6 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
271 } 287 }
272} 288}
273 289
274impl<'d, M: Mode, IM: MasterMode> Drop for I2c<'d, M, IM> {
275 fn drop(&mut self) {
276 self.scl.as_ref().map(|x| x.set_as_disconnected());
277 self.sda.as_ref().map(|x| x.set_as_disconnected());
278
279 self.info.rcc.disable()
280 }
281}
282
283#[derive(Copy, Clone)] 290#[derive(Copy, Clone)]
284struct Timeout { 291struct Timeout {
285 #[cfg(feature = "time")] 292 #[cfg(feature = "time")]
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 531358efa..a90bdd551 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -47,6 +47,8 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() {
47 critical_section::with(|_| { 47 critical_section::with(|_| {
48 regs.cr1().modify(|w| { 48 regs.cr1().modify(|w| {
49 w.set_addrie(false); 49 w.set_addrie(false);
50 w.set_stopie(false);
51 w.set_tcie(false);
50 // The flag can only be cleared by writting to nbytes, we won't do that here, so disable 52 // The flag can only be cleared by writting to nbytes, we won't do that here, so disable
51 // the interrupt 53 // the interrupt
52 w.set_tcie(false); 54 w.set_tcie(false);
@@ -725,14 +727,13 @@ impl<'d, M: Mode> I2c<'d, M, Master> {
725 info: self.info, 727 info: self.info,
726 state: self.state, 728 state: self.state,
727 kernel_clock: self.kernel_clock, 729 kernel_clock: self.kernel_clock,
728 scl: self.scl.take(),
729 sda: self.sda.take(),
730 tx_dma: self.tx_dma.take(), 730 tx_dma: self.tx_dma.take(),
731 rx_dma: self.rx_dma.take(), 731 rx_dma: self.rx_dma.take(),
732 #[cfg(feature = "time")] 732 #[cfg(feature = "time")]
733 timeout: self.timeout, 733 timeout: self.timeout,
734 _phantom: PhantomData, 734 _phantom: PhantomData,
735 _phantom2: PhantomData, 735 _phantom2: PhantomData,
736 drop_guard: self.drop_guard,
736 }; 737 };
737 slave.init_slave(slave_addr_config); 738 slave.init_slave(slave_addr_config);
738 slave 739 slave
@@ -930,6 +931,8 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
930 931
931impl<'d> I2c<'d, Async, MultiMaster> { 932impl<'d> I2c<'d, Async, MultiMaster> {
932 /// Respond to a receive command. 933 /// Respond to a receive command.
934 ///
935 /// Returns the total number of bytes received.
933 pub async fn respond_to_receive(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { 936 pub async fn respond_to_receive(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
934 let timeout = self.timeout(); 937 let timeout = self.timeout();
935 timeout.with(self.read_dma_internal_slave(buffer, timeout)).await 938 timeout.with(self.read_dma_internal_slave(buffer, timeout)).await
@@ -942,6 +945,8 @@ impl<'d> I2c<'d, Async, MultiMaster> {
942 } 945 }
943 946
944 // for data reception in slave mode 947 // for data reception in slave mode
948 //
949 // returns the total number of bytes received
945 async fn read_dma_internal_slave(&mut self, buffer: &mut [u8], timeout: Timeout) -> Result<usize, Error> { 950 async fn read_dma_internal_slave(&mut self, buffer: &mut [u8], timeout: Timeout) -> Result<usize, Error> {
946 let total_len = buffer.len(); 951 let total_len = buffer.len();
947 let mut remaining_len = total_len; 952 let mut remaining_len = total_len;
@@ -988,7 +993,7 @@ impl<'d> I2c<'d, Async, MultiMaster> {
988 Poll::Pending 993 Poll::Pending
989 } else if isr.stopf() { 994 } else if isr.stopf() {
990 regs.icr().write(|reg| reg.set_stopcf(true)); 995 regs.icr().write(|reg| reg.set_stopcf(true));
991 let poll = Poll::Ready(Ok(remaining_len)); 996 let poll = Poll::Ready(Ok(total_len - remaining_len));
992 poll 997 poll
993 } else { 998 } else {
994 Poll::Pending 999 Poll::Pending