aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2025-06-11 05:09:08 +0000
committerGitHub <[email protected]>2025-06-11 05:09:08 +0000
commit56572ef0adffd6258adc10fb424e37a8b4ddc19c (patch)
tree5cacb71ceca12180e95031791c93c53e83bca307 /embassy-stm32
parent6186d111a5c150946ee5b7e9e68d987a38c1a463 (diff)
parent4efb3b4f3f0178b98ea25f3957393ab6977c89de (diff)
Merge pull request #2909 from jrmoulton/i2c-slave-new
stm32 i2c slave
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/src/i2c/config.rs170
-rw-r--r--embassy-stm32/src/i2c/mod.rs173
-rw-r--r--embassy-stm32/src/i2c/v1.rs7
-rw-r--r--embassy-stm32/src/i2c/v2.rs491
4 files changed, 714 insertions, 127 deletions
diff --git a/embassy-stm32/src/i2c/config.rs b/embassy-stm32/src/i2c/config.rs
new file mode 100644
index 000000000..daae43bcd
--- /dev/null
+++ b/embassy-stm32/src/i2c/config.rs
@@ -0,0 +1,170 @@
1#[cfg(gpio_v2)]
2use crate::gpio::Pull;
3use crate::gpio::{AfType, OutputType, Speed};
4
5#[repr(u8)]
6#[derive(Copy, Clone)]
7#[cfg_attr(feature = "defmt", derive(defmt::Format))]
8/// Bits of the I2C OA2 register to mask out.
9pub enum AddrMask {
10 /// No mask
11 NOMASK,
12 /// OA2\[1\] is masked and don’t care. Only OA2\[7:2\] are compared.
13 MASK1,
14 /// OA2\[2:1\] are masked and don’t care. Only OA2\[7:3\] are compared.
15 MASK2,
16 /// OA2\[3:1\] are masked and don’t care. Only OA2\[7:4\] are compared.
17 MASK3,
18 /// OA2\[4:1\] are masked and don’t care. Only OA2\[7:5\] are compared.
19 MASK4,
20 /// OA2\[5:1\] are masked and don’t care. Only OA2\[7:6\] are compared.
21 MASK5,
22 /// OA2\[6:1\] are masked and don’t care. Only OA2\[7:6\] are compared.
23 MASK6,
24 /// OA2\[7:1\] are masked and don’t care. No comparison is done, and all (except reserved) 7-bit received addresses are acknowledged
25 MASK7,
26}
27
28#[derive(Debug, Copy, Clone, PartialEq, Eq)]
29#[cfg_attr(feature = "defmt", derive(defmt::Format))]
30/// An I2C address. Either 7 or 10 bit.
31pub enum Address {
32 /// A 7 bit address
33 SevenBit(u8),
34 /// A 10 bit address.
35 ///
36 /// When using an address to configure the Own Address, only the OA1 register can be set to a 10-bit address.
37 TenBit(u16),
38}
39impl From<u8> for Address {
40 fn from(value: u8) -> Self {
41 Address::SevenBit(value)
42 }
43}
44impl From<u16> for Address {
45 fn from(value: u16) -> Self {
46 assert!(value < 0x400, "Ten bit address must be less than 0x400");
47 Address::TenBit(value)
48 }
49}
50impl Address {
51 /// Get the inner address as a u16.
52 ///
53 /// For 7 bit addresses, the u8 that was used to store the address is returned as a u16.
54 pub fn addr(&self) -> u16 {
55 match self {
56 Address::SevenBit(addr) => *addr as u16,
57 Address::TenBit(addr) => *addr,
58 }
59 }
60}
61
62#[derive(Copy, Clone)]
63#[cfg_attr(feature = "defmt", derive(defmt::Format))]
64/// The second Own Address register.
65pub struct OA2 {
66 /// The address.
67 pub addr: u8,
68 /// The bit mask that will affect how the own address 2 register is compared.
69 pub mask: AddrMask,
70}
71
72#[derive(Copy, Clone)]
73#[cfg_attr(feature = "defmt", derive(defmt::Format))]
74/// The Own Address(es) of the I2C peripheral.
75pub enum OwnAddresses {
76 /// Configuration for only the OA1 register.
77 OA1(Address),
78 /// Configuration for only the OA2 register.
79 OA2(OA2),
80 /// Configuration for both the OA1 and OA2 registers.
81 Both {
82 /// The [Address] for the OA1 register.
83 oa1: Address,
84 /// The [OA2] configuration.
85 oa2: OA2,
86 },
87}
88
89/// Slave Configuration
90#[derive(Copy, Clone)]
91#[cfg_attr(feature = "defmt", derive(defmt::Format))]
92pub struct SlaveAddrConfig {
93 /// Target Address(es)
94 pub addr: OwnAddresses,
95 /// Control if the peripheral should respond to the general call address
96 pub general_call: bool,
97}
98impl SlaveAddrConfig {
99 /// Create a new slave address configuration with only the OA1 register set in 7 bit mode and the general call disabled.
100 pub fn basic(addr: u8) -> Self {
101 Self {
102 addr: OwnAddresses::OA1(Address::SevenBit(addr)),
103 general_call: false,
104 }
105 }
106}
107
108/// I2C config
109#[non_exhaustive]
110#[derive(Copy, Clone)]
111pub struct Config {
112 /// Enable internal pullup on SDA.
113 ///
114 /// Using external pullup resistors is recommended for I2C. If you do
115 /// have external pullups you should not enable this.
116 #[cfg(gpio_v2)]
117 pub sda_pullup: bool,
118 /// Enable internal pullup on SCL.
119 ///
120 /// Using external pullup resistors is recommended for I2C. If you do
121 /// have external pullups you should not enable this.
122 #[cfg(gpio_v2)]
123 pub scl_pullup: bool,
124 /// Timeout.
125 #[cfg(feature = "time")]
126 pub timeout: embassy_time::Duration,
127}
128
129impl Default for Config {
130 fn default() -> Self {
131 Self {
132 #[cfg(gpio_v2)]
133 sda_pullup: false,
134 #[cfg(gpio_v2)]
135 scl_pullup: false,
136 #[cfg(feature = "time")]
137 timeout: embassy_time::Duration::from_millis(1000),
138 }
139 }
140}
141
142impl Config {
143 pub(super) fn scl_af(&self) -> AfType {
144 #[cfg(gpio_v1)]
145 return AfType::output(OutputType::OpenDrain, Speed::Medium);
146 #[cfg(gpio_v2)]
147 return AfType::output_pull(
148 OutputType::OpenDrain,
149 Speed::Medium,
150 match self.scl_pullup {
151 true => Pull::Up,
152 false => Pull::Down,
153 },
154 );
155 }
156
157 pub(super) fn sda_af(&self) -> AfType {
158 #[cfg(gpio_v1)]
159 return AfType::output(OutputType::OpenDrain, Speed::Medium);
160 #[cfg(gpio_v2)]
161 return AfType::output_pull(
162 OutputType::OpenDrain,
163 Speed::Medium,
164 match self.sda_pullup {
165 true => Pull::Up,
166 false => Pull::Down,
167 },
168 );
169 }
170}
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index 1689fdb84..825dd240c 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -5,19 +5,22 @@
5#[cfg_attr(any(i2c_v2, i2c_v3), path = "v2.rs")] 5#[cfg_attr(any(i2c_v2, i2c_v3), path = "v2.rs")]
6mod _version; 6mod _version;
7 7
8mod config;
9
8use core::future::Future; 10use core::future::Future;
9use core::iter; 11use core::iter;
10use core::marker::PhantomData; 12use core::marker::PhantomData;
11 13
14pub use config::*;
12use embassy_hal_internal::Peri; 15use embassy_hal_internal::Peri;
13use embassy_sync::waitqueue::AtomicWaker; 16use embassy_sync::waitqueue::AtomicWaker;
14#[cfg(feature = "time")] 17#[cfg(feature = "time")]
15use embassy_time::{Duration, Instant}; 18use embassy_time::{Duration, Instant};
19use mode::MasterMode;
20pub use mode::{Master, MultiMaster};
16 21
17use crate::dma::ChannelAndRequest; 22use crate::dma::ChannelAndRequest;
18#[cfg(gpio_v2)] 23use crate::gpio::{AnyPin, SealedPin as _};
19use crate::gpio::Pull;
20use crate::gpio::{AfType, AnyPin, OutputType, SealedPin as _, Speed};
21use crate::interrupt::typelevel::Interrupt; 24use crate::interrupt::typelevel::Interrupt;
22use crate::mode::{Async, Blocking, Mode}; 25use crate::mode::{Async, Blocking, Mode};
23use crate::rcc::{RccInfo, SealedRccPeripheral}; 26use crate::rcc::{RccInfo, SealedRccPeripheral};
@@ -62,85 +65,89 @@ impl core::fmt::Display for Error {
62 65
63impl core::error::Error for Error {} 66impl core::error::Error for Error {}
64 67
65/// I2C config 68/// I2C modes
66#[non_exhaustive] 69pub mod mode {
67#[derive(Copy, Clone)] 70 trait SealedMode {}
68pub struct Config { 71
69 /// Enable internal pullup on SDA. 72 /// Trait for I2C master operations.
70 /// 73 #[allow(private_bounds)]
71 /// Using external pullup resistors is recommended for I2C. If you do 74 pub trait MasterMode: SealedMode {}
72 /// have external pullups you should not enable this. 75
73 #[cfg(gpio_v2)] 76 /// Mode allowing for I2C master operations.
74 pub sda_pullup: bool, 77 pub struct Master;
75 /// Enable internal pullup on SCL. 78 /// Mode allowing for I2C master and slave operations.
76 /// 79 pub struct MultiMaster;
77 /// Using external pullup resistors is recommended for I2C. If you do 80
78 /// have external pullups you should not enable this. 81 impl SealedMode for Master {}
79 #[cfg(gpio_v2)] 82 impl MasterMode for Master {}
80 pub scl_pullup: bool, 83
81 /// Timeout. 84 impl SealedMode for MultiMaster {}
82 #[cfg(feature = "time")] 85 impl MasterMode for MultiMaster {}
83 pub timeout: embassy_time::Duration,
84} 86}
85 87
86impl Default for Config { 88#[derive(Debug, Clone, PartialEq, Eq)]
87 fn default() -> Self { 89#[cfg_attr(feature = "defmt", derive(defmt::Format))]
88 Self { 90/// The command kind to the slave from the master
89 #[cfg(gpio_v2)] 91pub enum SlaveCommandKind {
90 sda_pullup: false, 92 /// Write to the slave
91 #[cfg(gpio_v2)] 93 Write,
92 scl_pullup: false, 94 /// Read from the slave
93 #[cfg(feature = "time")] 95 Read,
94 timeout: embassy_time::Duration::from_millis(1000),
95 }
96 }
97} 96}
98 97
99impl Config { 98#[derive(Debug, Clone, PartialEq, Eq)]
100 fn scl_af(&self) -> AfType { 99#[cfg_attr(feature = "defmt", derive(defmt::Format))]
101 #[cfg(gpio_v1)] 100/// The command kind to the slave from the master and the address that the slave matched
102 return AfType::output(OutputType::OpenDrain, Speed::Medium); 101pub struct SlaveCommand {
103 #[cfg(gpio_v2)] 102 /// The kind of command
104 return AfType::output_pull( 103 pub kind: SlaveCommandKind,
105 OutputType::OpenDrain, 104 /// The address that the slave matched
106 Speed::Medium, 105 pub address: Address,
107 match self.scl_pullup { 106}
108 true => Pull::Up,
109 false => Pull::None,
110 },
111 );
112 }
113 107
114 fn sda_af(&self) -> AfType { 108#[derive(Debug, Clone, PartialEq, Eq)]
115 #[cfg(gpio_v1)] 109#[cfg_attr(feature = "defmt", derive(defmt::Format))]
116 return AfType::output(OutputType::OpenDrain, Speed::Medium); 110/// The status of the slave send operation
117 #[cfg(gpio_v2)] 111pub enum SendStatus {
118 return AfType::output_pull( 112 /// The slave send operation is done, all bytes have been sent and the master is not requesting more
119 OutputType::OpenDrain, 113 Done,
120 Speed::Medium, 114 /// The slave send operation is done, but there are leftover bytes that the master did not read
121 match self.sda_pullup { 115 LeftoverBytes(usize),
122 true => Pull::Up, 116}
123 false => Pull::None, 117
124 }, 118struct I2CDropGuard<'d> {
125 ); 119 info: &'static Info,
120 scl: Option<Peri<'d, AnyPin>>,
121 sda: Option<Peri<'d, AnyPin>>,
122}
123impl<'d> Drop for I2CDropGuard<'d> {
124 fn drop(&mut self) {
125 if let Some(x) = self.scl.as_ref() {
126 x.set_as_disconnected()
127 }
128 if let Some(x) = self.sda.as_ref() {
129 x.set_as_disconnected()
130 }
131
132 self.info.rcc.disable();
126 } 133 }
127} 134}
128 135
129/// I2C driver. 136/// I2C driver.
130pub struct I2c<'d, M: Mode> { 137pub struct I2c<'d, M: Mode, IM: MasterMode> {
131 info: &'static Info, 138 info: &'static Info,
132 state: &'static State, 139 state: &'static State,
133 kernel_clock: Hertz, 140 kernel_clock: Hertz,
134 scl: Option<Peri<'d, AnyPin>>,
135 sda: Option<Peri<'d, AnyPin>>,
136 tx_dma: Option<ChannelAndRequest<'d>>, 141 tx_dma: Option<ChannelAndRequest<'d>>,
137 rx_dma: Option<ChannelAndRequest<'d>>, 142 rx_dma: Option<ChannelAndRequest<'d>>,
138 #[cfg(feature = "time")] 143 #[cfg(feature = "time")]
139 timeout: Duration, 144 timeout: Duration,
140 _phantom: PhantomData<M>, 145 _phantom: PhantomData<M>,
146 _phantom2: PhantomData<IM>,
147 _drop_guard: I2CDropGuard<'d>,
141} 148}
142 149
143impl<'d> I2c<'d, Async> { 150impl<'d> I2c<'d, Async, Master> {
144 /// Create a new I2C driver. 151 /// Create a new I2C driver.
145 pub fn new<T: Instance>( 152 pub fn new<T: Instance>(
146 peri: Peri<'d, T>, 153 peri: Peri<'d, T>,
@@ -166,7 +173,7 @@ impl<'d> I2c<'d, Async> {
166 } 173 }
167} 174}
168 175
169impl<'d> I2c<'d, Blocking> { 176impl<'d> I2c<'d, Blocking, Master> {
170 /// Create a new blocking I2C driver. 177 /// Create a new blocking I2C driver.
171 pub fn new_blocking<T: Instance>( 178 pub fn new_blocking<T: Instance>(
172 peri: Peri<'d, T>, 179 peri: Peri<'d, T>,
@@ -187,7 +194,7 @@ impl<'d> I2c<'d, Blocking> {
187 } 194 }
188} 195}
189 196
190impl<'d, M: Mode> I2c<'d, M> { 197impl<'d, M: Mode> I2c<'d, M, Master> {
191 /// Create a new I2C driver. 198 /// Create a new I2C driver.
192 fn new_inner<T: Instance>( 199 fn new_inner<T: Instance>(
193 _peri: Peri<'d, T>, 200 _peri: Peri<'d, T>,
@@ -205,15 +212,20 @@ impl<'d, M: Mode> I2c<'d, M> {
205 info: T::info(), 212 info: T::info(),
206 state: T::state(), 213 state: T::state(),
207 kernel_clock: T::frequency(), 214 kernel_clock: T::frequency(),
208 scl,
209 sda,
210 tx_dma, 215 tx_dma,
211 rx_dma, 216 rx_dma,
212 #[cfg(feature = "time")] 217 #[cfg(feature = "time")]
213 timeout: config.timeout, 218 timeout: config.timeout,
214 _phantom: PhantomData, 219 _phantom: PhantomData,
220 _phantom2: PhantomData,
221 _drop_guard: I2CDropGuard {
222 info: T::info(),
223 scl,
224 sda,
225 },
215 }; 226 };
216 this.enable_and_init(freq, config); 227 this.enable_and_init(freq, config);
228
217 this 229 this
218 } 230 }
219 231
@@ -221,7 +233,9 @@ impl<'d, M: Mode> I2c<'d, M> {
221 self.info.rcc.enable_and_reset(); 233 self.info.rcc.enable_and_reset();
222 self.init(freq, config); 234 self.init(freq, config);
223 } 235 }
236}
224 237
238impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
225 fn timeout(&self) -> Timeout { 239 fn timeout(&self) -> Timeout {
226 Timeout { 240 Timeout {
227 #[cfg(feature = "time")] 241 #[cfg(feature = "time")]
@@ -230,15 +244,6 @@ impl<'d, M: Mode> I2c<'d, M> {
230 } 244 }
231} 245}
232 246
233impl<'d, M: Mode> Drop for I2c<'d, M> {
234 fn drop(&mut self) {
235 self.scl.as_ref().map(|x| x.set_as_disconnected());
236 self.sda.as_ref().map(|x| x.set_as_disconnected());
237
238 self.info.rcc.disable()
239 }
240}
241
242#[derive(Copy, Clone)] 247#[derive(Copy, Clone)]
243struct Timeout { 248struct Timeout {
244 #[cfg(feature = "time")] 249 #[cfg(feature = "time")]
@@ -347,7 +352,7 @@ foreach_peripheral!(
347 }; 352 };
348); 353);
349 354
350impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, M> { 355impl<'d, M: Mode, IM: MasterMode> embedded_hal_02::blocking::i2c::Read for I2c<'d, M, IM> {
351 type Error = Error; 356 type Error = Error;
352 357
353 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { 358 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
@@ -355,7 +360,7 @@ impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, M> {
355 } 360 }
356} 361}
357 362
358impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, M> { 363impl<'d, M: Mode, IM: MasterMode> embedded_hal_02::blocking::i2c::Write for I2c<'d, M, IM> {
359 type Error = Error; 364 type Error = Error;
360 365
361 fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { 366 fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
@@ -363,7 +368,7 @@ impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, M> {
363 } 368 }
364} 369}
365 370
366impl<'d, M: Mode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M> { 371impl<'d, M: Mode, IM: MasterMode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M, IM> {
367 type Error = Error; 372 type Error = Error;
368 373
369 fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { 374 fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
@@ -387,11 +392,11 @@ impl embedded_hal_1::i2c::Error for Error {
387 } 392 }
388} 393}
389 394
390impl<'d, M: Mode> embedded_hal_1::i2c::ErrorType for I2c<'d, M> { 395impl<'d, M: Mode, IM: MasterMode> embedded_hal_1::i2c::ErrorType for I2c<'d, M, IM> {
391 type Error = Error; 396 type Error = Error;
392} 397}
393 398
394impl<'d, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, M> { 399impl<'d, M: Mode, IM: MasterMode> embedded_hal_1::i2c::I2c for I2c<'d, M, IM> {
395 fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { 400 fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
396 self.blocking_read(address, read) 401 self.blocking_read(address, read)
397 } 402 }
@@ -413,7 +418,7 @@ impl<'d, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, M> {
413 } 418 }
414} 419}
415 420
416impl<'d> embedded_hal_async::i2c::I2c for I2c<'d, Async> { 421impl<'d, IM: MasterMode> embedded_hal_async::i2c::I2c for I2c<'d, Async, IM> {
417 async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { 422 async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
418 self.read(address, read).await 423 self.read(address, read).await
419 } 424 }
@@ -529,9 +534,7 @@ fn operation_frames<'a, 'b: 'a>(
529 let mut next_first_frame = true; 534 let mut next_first_frame = true;
530 535
531 Ok(iter::from_fn(move || { 536 Ok(iter::from_fn(move || {
532 let Some(op) = operations.next() else { 537 let op = operations.next()?;
533 return None;
534 };
535 538
536 // Is `op` first frame of its type? 539 // Is `op` first frame of its type?
537 let first_frame = next_first_frame; 540 let first_frame = next_first_frame;
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index 28026f83c..35f13ab46 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -11,6 +11,7 @@ use embassy_embedded_hal::SetConfig;
11use embassy_futures::select::{select, Either}; 11use embassy_futures::select::{select, Either};
12use embassy_hal_internal::drop::OnDrop; 12use embassy_hal_internal::drop::OnDrop;
13use embedded_hal_1::i2c::Operation; 13use embedded_hal_1::i2c::Operation;
14use mode::Master;
14 15
15use super::*; 16use super::*;
16use crate::mode::Mode as PeriMode; 17use crate::mode::Mode as PeriMode;
@@ -41,7 +42,7 @@ pub unsafe fn on_interrupt<T: Instance>() {
41 }); 42 });
42} 43}
43 44
44impl<'d, M: PeriMode> I2c<'d, M> { 45impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
45 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { 46 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
46 self.info.regs.cr1().modify(|reg| { 47 self.info.regs.cr1().modify(|reg| {
47 reg.set_pe(false); 48 reg.set_pe(false);
@@ -354,7 +355,7 @@ impl<'d, M: PeriMode> I2c<'d, M> {
354 } 355 }
355} 356}
356 357
357impl<'d> I2c<'d, Async> { 358impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
358 async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error> { 359 async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error> {
359 self.info.regs.cr2().modify(|w| { 360 self.info.regs.cr2().modify(|w| {
360 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for 361 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
@@ -800,7 +801,7 @@ impl Timings {
800 } 801 }
801} 802}
802 803
803impl<'d, M: PeriMode> SetConfig for I2c<'d, M> { 804impl<'d, M: PeriMode> SetConfig for I2c<'d, M, Master> {
804 type Config = Hertz; 805 type Config = Hertz;
805 type ConfigError = (); 806 type ConfigError = ();
806 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { 807 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 50a25754e..35dc91c86 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -2,22 +2,52 @@ use core::cmp;
2use core::future::poll_fn; 2use core::future::poll_fn;
3use core::task::Poll; 3use core::task::Poll;
4 4
5use config::{Address, OwnAddresses, OA2};
5use embassy_embedded_hal::SetConfig; 6use embassy_embedded_hal::SetConfig;
6use embassy_hal_internal::drop::OnDrop; 7use embassy_hal_internal::drop::OnDrop;
7use embedded_hal_1::i2c::Operation; 8use embedded_hal_1::i2c::Operation;
9use mode::{Master, MultiMaster};
10use stm32_metapac::i2c::vals::{Addmode, Oamsk};
8 11
9use super::*; 12use super::*;
10use crate::pac::i2c; 13use crate::pac::i2c;
11 14
15impl From<AddrMask> for Oamsk {
16 fn from(value: AddrMask) -> Self {
17 match value {
18 AddrMask::NOMASK => Oamsk::NO_MASK,
19 AddrMask::MASK1 => Oamsk::MASK1,
20 AddrMask::MASK2 => Oamsk::MASK2,
21 AddrMask::MASK3 => Oamsk::MASK3,
22 AddrMask::MASK4 => Oamsk::MASK4,
23 AddrMask::MASK5 => Oamsk::MASK5,
24 AddrMask::MASK6 => Oamsk::MASK6,
25 AddrMask::MASK7 => Oamsk::MASK7,
26 }
27 }
28}
29
30impl Address {
31 pub(super) fn add_mode(&self) -> stm32_metapac::i2c::vals::Addmode {
32 match self {
33 Address::SevenBit(_) => stm32_metapac::i2c::vals::Addmode::BIT7,
34 Address::TenBit(_) => stm32_metapac::i2c::vals::Addmode::BIT10,
35 }
36 }
37}
38
12pub(crate) unsafe fn on_interrupt<T: Instance>() { 39pub(crate) unsafe fn on_interrupt<T: Instance>() {
13 let regs = T::info().regs; 40 let regs = T::info().regs;
14 let isr = regs.isr().read(); 41 let isr = regs.isr().read();
15 42
16 if isr.tcr() || isr.tc() || isr.nackf() || isr.berr() || isr.arlo() || isr.ovr() { 43 if isr.tcr() || isr.tc() || isr.addr() || isr.stopf() || isr.nackf() || isr.berr() || isr.arlo() || isr.ovr() {
17 T::state().waker.wake(); 44 T::state().waker.wake();
18 } 45 }
46
19 critical_section::with(|_| { 47 critical_section::with(|_| {
20 regs.cr1().modify(|w| { 48 regs.cr1().modify(|w| {
49 w.set_addrie(false);
50 w.set_stopie(false);
21 // The flag can only be cleared by writting to nbytes, we won't do that here 51 // The flag can only be cleared by writting to nbytes, we won't do that here
22 w.set_tcie(false); 52 w.set_tcie(false);
23 // Error flags are to be read in the routines, so we also don't clear them here 53 // Error flags are to be read in the routines, so we also don't clear them here
@@ -27,7 +57,7 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() {
27 }); 57 });
28} 58}
29 59
30impl<'d, M: Mode> I2c<'d, M> { 60impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
31 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { 61 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
32 self.info.regs.cr1().modify(|reg| { 62 self.info.regs.cr1().modify(|reg| {
33 reg.set_pe(false); 63 reg.set_pe(false);
@@ -55,7 +85,7 @@ impl<'d, M: Mode> I2c<'d, M> {
55 85
56 fn master_read( 86 fn master_read(
57 info: &'static Info, 87 info: &'static Info,
58 address: u8, 88 address: Address,
59 length: usize, 89 length: usize,
60 stop: Stop, 90 stop: Stop,
61 reload: bool, 91 reload: bool,
@@ -84,8 +114,8 @@ impl<'d, M: Mode> I2c<'d, M> {
84 }; 114 };
85 115
86 info.regs.cr2().modify(|w| { 116 info.regs.cr2().modify(|w| {
87 w.set_sadd((address << 1 | 0) as u16); 117 w.set_sadd(address.addr() << 1);
88 w.set_add10(i2c::vals::Addmode::BIT7); 118 w.set_add10(address.add_mode());
89 w.set_dir(i2c::vals::Dir::READ); 119 w.set_dir(i2c::vals::Dir::READ);
90 w.set_nbytes(length as u8); 120 w.set_nbytes(length as u8);
91 w.set_start(true); 121 w.set_start(true);
@@ -98,7 +128,7 @@ impl<'d, M: Mode> I2c<'d, M> {
98 128
99 fn master_write( 129 fn master_write(
100 info: &'static Info, 130 info: &'static Info,
101 address: u8, 131 address: Address,
102 length: usize, 132 length: usize,
103 stop: Stop, 133 stop: Stop,
104 reload: bool, 134 reload: bool,
@@ -128,8 +158,8 @@ impl<'d, M: Mode> I2c<'d, M> {
128 // START bit can be set even if the bus is BUSY or 158 // START bit can be set even if the bus is BUSY or
129 // I2C is in slave mode. 159 // I2C is in slave mode.
130 info.regs.cr2().modify(|w| { 160 info.regs.cr2().modify(|w| {
131 w.set_sadd((address << 1 | 0) as u16); 161 w.set_sadd(address.addr() << 1);
132 w.set_add10(i2c::vals::Addmode::BIT7); 162 w.set_add10(address.add_mode());
133 w.set_dir(i2c::vals::Dir::WRITE); 163 w.set_dir(i2c::vals::Dir::WRITE);
134 w.set_nbytes(length as u8); 164 w.set_nbytes(length as u8);
135 w.set_start(true); 165 w.set_start(true);
@@ -140,14 +170,14 @@ impl<'d, M: Mode> I2c<'d, M> {
140 Ok(()) 170 Ok(())
141 } 171 }
142 172
143 fn master_continue(info: &'static Info, length: usize, reload: bool, timeout: Timeout) -> Result<(), Error> { 173 fn reload(info: &'static Info, length: usize, will_reload: bool, timeout: Timeout) -> Result<(), Error> {
144 assert!(length < 256 && length > 0); 174 assert!(length < 256 && length > 0);
145 175
146 while !info.regs.isr().read().tcr() { 176 while !info.regs.isr().read().tcr() {
147 timeout.check()?; 177 timeout.check()?;
148 } 178 }
149 179
150 let reload = if reload { 180 let will_reload = if will_reload {
151 i2c::vals::Reload::NOT_COMPLETED 181 i2c::vals::Reload::NOT_COMPLETED
152 } else { 182 } else {
153 i2c::vals::Reload::COMPLETED 183 i2c::vals::Reload::COMPLETED
@@ -155,7 +185,7 @@ impl<'d, M: Mode> I2c<'d, M> {
155 185
156 info.regs.cr2().modify(|w| { 186 info.regs.cr2().modify(|w| {
157 w.set_nbytes(length as u8); 187 w.set_nbytes(length as u8);
158 w.set_reload(reload); 188 w.set_reload(will_reload);
159 }); 189 });
160 190
161 Ok(()) 191 Ok(())
@@ -233,7 +263,13 @@ impl<'d, M: Mode> I2c<'d, M> {
233 } 263 }
234 } 264 }
235 265
236 fn read_internal(&mut self, address: u8, read: &mut [u8], restart: bool, timeout: Timeout) -> Result<(), Error> { 266 fn read_internal(
267 &mut self,
268 address: Address,
269 read: &mut [u8],
270 restart: bool,
271 timeout: Timeout,
272 ) -> Result<(), Error> {
237 let completed_chunks = read.len() / 255; 273 let completed_chunks = read.len() / 255;
238 let total_chunks = if completed_chunks * 255 == read.len() { 274 let total_chunks = if completed_chunks * 255 == read.len() {
239 completed_chunks 275 completed_chunks
@@ -254,7 +290,7 @@ impl<'d, M: Mode> I2c<'d, M> {
254 290
255 for (number, chunk) in read.chunks_mut(255).enumerate() { 291 for (number, chunk) in read.chunks_mut(255).enumerate() {
256 if number != 0 { 292 if number != 0 {
257 Self::master_continue(self.info, chunk.len(), number != last_chunk_idx, timeout)?; 293 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
258 } 294 }
259 295
260 for byte in chunk { 296 for byte in chunk {
@@ -267,7 +303,13 @@ impl<'d, M: Mode> I2c<'d, M> {
267 Ok(()) 303 Ok(())
268 } 304 }
269 305
270 fn write_internal(&mut self, address: u8, write: &[u8], send_stop: bool, timeout: Timeout) -> Result<(), Error> { 306 fn write_internal(
307 &mut self,
308 address: Address,
309 write: &[u8],
310 send_stop: bool,
311 timeout: Timeout,
312 ) -> Result<(), Error> {
271 let completed_chunks = write.len() / 255; 313 let completed_chunks = write.len() / 255;
272 let total_chunks = if completed_chunks * 255 == write.len() { 314 let total_chunks = if completed_chunks * 255 == write.len() {
273 completed_chunks 315 completed_chunks
@@ -295,7 +337,7 @@ impl<'d, M: Mode> I2c<'d, M> {
295 337
296 for (number, chunk) in write.chunks(255).enumerate() { 338 for (number, chunk) in write.chunks(255).enumerate() {
297 if number != 0 { 339 if number != 0 {
298 Self::master_continue(self.info, chunk.len(), number != last_chunk_idx, timeout)?; 340 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
299 } 341 }
300 342
301 for byte in chunk { 343 for byte in chunk {
@@ -325,20 +367,20 @@ impl<'d, M: Mode> I2c<'d, M> {
325 367
326 /// Blocking read. 368 /// Blocking read.
327 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { 369 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
328 self.read_internal(address, read, false, self.timeout()) 370 self.read_internal(address.into(), read, false, self.timeout())
329 // Automatic Stop 371 // Automatic Stop
330 } 372 }
331 373
332 /// Blocking write. 374 /// Blocking write.
333 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { 375 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
334 self.write_internal(address, write, true, self.timeout()) 376 self.write_internal(address.into(), write, true, self.timeout())
335 } 377 }
336 378
337 /// Blocking write, restart, read. 379 /// Blocking write, restart, read.
338 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { 380 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
339 let timeout = self.timeout(); 381 let timeout = self.timeout();
340 self.write_internal(address, write, false, timeout)?; 382 self.write_internal(address.into(), write, false, timeout)?;
341 self.read_internal(address, read, true, timeout) 383 self.read_internal(address.into(), read, true, timeout)
342 // Automatic Stop 384 // Automatic Stop
343 } 385 }
344 386
@@ -368,7 +410,7 @@ impl<'d, M: Mode> I2c<'d, M> {
368 410
369 if let Err(err) = Self::master_write( 411 if let Err(err) = Self::master_write(
370 self.info, 412 self.info,
371 address, 413 address.into(),
372 first_length.min(255), 414 first_length.min(255),
373 Stop::Software, 415 Stop::Software,
374 (first_length > 255) || (last_slice_index != 0), 416 (first_length > 255) || (last_slice_index != 0),
@@ -389,7 +431,7 @@ impl<'d, M: Mode> I2c<'d, M> {
389 let last_chunk_idx = total_chunks.saturating_sub(1); 431 let last_chunk_idx = total_chunks.saturating_sub(1);
390 432
391 if idx != 0 { 433 if idx != 0 {
392 if let Err(err) = Self::master_continue( 434 if let Err(err) = Self::reload(
393 self.info, 435 self.info,
394 slice_len.min(255), 436 slice_len.min(255),
395 (idx != last_slice_index) || (slice_len > 255), 437 (idx != last_slice_index) || (slice_len > 255),
@@ -402,7 +444,7 @@ impl<'d, M: Mode> I2c<'d, M> {
402 444
403 for (number, chunk) in slice.chunks(255).enumerate() { 445 for (number, chunk) in slice.chunks(255).enumerate() {
404 if number != 0 { 446 if number != 0 {
405 if let Err(err) = Self::master_continue( 447 if let Err(err) = Self::reload(
406 self.info, 448 self.info,
407 chunk.len(), 449 chunk.len(),
408 (number != last_chunk_idx) || (idx != last_slice_index), 450 (number != last_chunk_idx) || (idx != last_slice_index),
@@ -435,10 +477,10 @@ impl<'d, M: Mode> I2c<'d, M> {
435 } 477 }
436} 478}
437 479
438impl<'d> I2c<'d, Async> { 480impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
439 async fn write_dma_internal( 481 async fn write_dma_internal(
440 &mut self, 482 &mut self,
441 address: u8, 483 address: Address,
442 write: &[u8], 484 write: &[u8],
443 first_slice: bool, 485 first_slice: bool,
444 last_slice: bool, 486 last_slice: bool,
@@ -512,7 +554,7 @@ impl<'d> I2c<'d, Async> {
512 timeout, 554 timeout,
513 )?; 555 )?;
514 } else { 556 } else {
515 Self::master_continue(self.info, total_len.min(255), (total_len > 255) || !last_slice, timeout)?; 557 Self::reload(self.info, total_len.min(255), (total_len > 255) || !last_slice, timeout)?;
516 self.info.regs.cr1().modify(|w| w.set_tcie(true)); 558 self.info.regs.cr1().modify(|w| w.set_tcie(true));
517 } 559 }
518 } else if !(isr.tcr() || isr.tc()) { 560 } else if !(isr.tcr() || isr.tc()) {
@@ -523,7 +565,7 @@ impl<'d> I2c<'d, Async> {
523 } else { 565 } else {
524 let last_piece = (remaining_len <= 255) && last_slice; 566 let last_piece = (remaining_len <= 255) && last_slice;
525 567
526 if let Err(e) = Self::master_continue(self.info, remaining_len.min(255), !last_piece, timeout) { 568 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !last_piece, timeout) {
527 return Poll::Ready(Err(e)); 569 return Poll::Ready(Err(e));
528 } 570 }
529 self.info.regs.cr1().modify(|w| w.set_tcie(true)); 571 self.info.regs.cr1().modify(|w| w.set_tcie(true));
@@ -551,7 +593,7 @@ impl<'d> I2c<'d, Async> {
551 593
552 async fn read_dma_internal( 594 async fn read_dma_internal(
553 &mut self, 595 &mut self,
554 address: u8, 596 address: Address,
555 buffer: &mut [u8], 597 buffer: &mut [u8],
556 restart: bool, 598 restart: bool,
557 timeout: Timeout, 599 timeout: Timeout,
@@ -626,7 +668,7 @@ impl<'d> I2c<'d, Async> {
626 } else { 668 } else {
627 let last_piece = remaining_len <= 255; 669 let last_piece = remaining_len <= 255;
628 670
629 if let Err(e) = Self::master_continue(self.info, remaining_len.min(255), !last_piece, timeout) { 671 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !last_piece, timeout) {
630 return Poll::Ready(Err(e)); 672 return Poll::Ready(Err(e));
631 } 673 }
632 // Return here if we are on last chunk, 674 // Return here if we are on last chunk,
@@ -647,7 +689,6 @@ impl<'d> I2c<'d, Async> {
647 689
648 Ok(()) 690 Ok(())
649 } 691 }
650
651 // ========================= 692 // =========================
652 // Async public API 693 // Async public API
653 694
@@ -655,10 +696,10 @@ impl<'d> I2c<'d, Async> {
655 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { 696 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
656 let timeout = self.timeout(); 697 let timeout = self.timeout();
657 if write.is_empty() { 698 if write.is_empty() {
658 self.write_internal(address, write, true, timeout) 699 self.write_internal(address.into(), write, true, timeout)
659 } else { 700 } else {
660 timeout 701 timeout
661 .with(self.write_dma_internal(address, write, true, true, true, timeout)) 702 .with(self.write_dma_internal(address.into(), write, true, true, true, timeout))
662 .await 703 .await
663 } 704 }
664 } 705 }
@@ -666,7 +707,7 @@ impl<'d> I2c<'d, Async> {
666 /// Write multiple buffers. 707 /// Write multiple buffers.
667 /// 708 ///
668 /// The buffers are concatenated in a single write transaction. 709 /// The buffers are concatenated in a single write transaction.
669 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { 710 pub async fn write_vectored(&mut self, address: Address, write: &[&[u8]]) -> Result<(), Error> {
670 let timeout = self.timeout(); 711 let timeout = self.timeout();
671 712
672 if write.is_empty() { 713 if write.is_empty() {
@@ -693,9 +734,9 @@ impl<'d> I2c<'d, Async> {
693 let timeout = self.timeout(); 734 let timeout = self.timeout();
694 735
695 if buffer.is_empty() { 736 if buffer.is_empty() {
696 self.read_internal(address, buffer, false, timeout) 737 self.read_internal(address.into(), buffer, false, timeout)
697 } else { 738 } else {
698 let fut = self.read_dma_internal(address, buffer, false, timeout); 739 let fut = self.read_dma_internal(address.into(), buffer, false, timeout);
699 timeout.with(fut).await 740 timeout.with(fut).await
700 } 741 }
701 } 742 }
@@ -705,16 +746,16 @@ impl<'d> I2c<'d, Async> {
705 let timeout = self.timeout(); 746 let timeout = self.timeout();
706 747
707 if write.is_empty() { 748 if write.is_empty() {
708 self.write_internal(address, write, false, timeout)?; 749 self.write_internal(address.into(), write, false, timeout)?;
709 } else { 750 } else {
710 let fut = self.write_dma_internal(address, write, true, true, false, timeout); 751 let fut = self.write_dma_internal(address.into(), write, true, true, false, timeout);
711 timeout.with(fut).await?; 752 timeout.with(fut).await?;
712 } 753 }
713 754
714 if read.is_empty() { 755 if read.is_empty() {
715 self.read_internal(address, read, true, timeout)?; 756 self.read_internal(address.into(), read, true, timeout)?;
716 } else { 757 } else {
717 let fut = self.read_dma_internal(address, read, true, timeout); 758 let fut = self.read_dma_internal(address.into(), read, true, timeout);
718 timeout.with(fut).await?; 759 timeout.with(fut).await?;
719 } 760 }
720 761
@@ -733,6 +774,360 @@ impl<'d> I2c<'d, Async> {
733 } 774 }
734} 775}
735 776
777impl<'d, M: Mode> I2c<'d, M, Master> {
778 /// Configure the I2C driver for slave operations, allowing for the driver to be used as a slave and a master (multimaster)
779 pub fn into_slave_multimaster(mut self, slave_addr_config: SlaveAddrConfig) -> I2c<'d, M, MultiMaster> {
780 let mut slave = I2c {
781 info: self.info,
782 state: self.state,
783 kernel_clock: self.kernel_clock,
784 tx_dma: self.tx_dma.take(),
785 rx_dma: self.rx_dma.take(),
786 #[cfg(feature = "time")]
787 timeout: self.timeout,
788 _phantom: PhantomData,
789 _phantom2: PhantomData,
790 _drop_guard: self._drop_guard,
791 };
792 slave.init_slave(slave_addr_config);
793 slave
794 }
795}
796
797impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
798 pub(crate) fn init_slave(&mut self, config: SlaveAddrConfig) {
799 self.info.regs.cr1().modify(|reg| {
800 reg.set_pe(false);
801 });
802
803 self.info.regs.cr1().modify(|reg| {
804 reg.set_nostretch(false);
805 reg.set_gcen(config.general_call);
806 reg.set_sbc(true);
807 reg.set_pe(true);
808 });
809
810 self.reconfigure_addresses(config.addr);
811 }
812
813 /// Configure the slave address.
814 pub fn reconfigure_addresses(&mut self, addresses: OwnAddresses) {
815 match addresses {
816 OwnAddresses::OA1(oa1) => self.configure_oa1(oa1),
817 OwnAddresses::OA2(oa2) => self.configure_oa2(oa2),
818 OwnAddresses::Both { oa1, oa2 } => {
819 self.configure_oa1(oa1);
820 self.configure_oa2(oa2);
821 }
822 }
823 }
824
825 fn configure_oa1(&mut self, oa1: Address) {
826 match oa1 {
827 Address::SevenBit(addr) => self.info.regs.oar1().write(|reg| {
828 reg.set_oa1en(false);
829 reg.set_oa1((addr << 1) as u16);
830 reg.set_oa1mode(Addmode::BIT7);
831 reg.set_oa1en(true);
832 }),
833 Address::TenBit(addr) => self.info.regs.oar1().write(|reg| {
834 reg.set_oa1en(false);
835 reg.set_oa1(addr);
836 reg.set_oa1mode(Addmode::BIT10);
837 reg.set_oa1en(true);
838 }),
839 }
840 }
841
842 fn configure_oa2(&mut self, oa2: OA2) {
843 self.info.regs.oar2().write(|reg| {
844 reg.set_oa2en(false);
845 reg.set_oa2msk(oa2.mask.into());
846 reg.set_oa2(oa2.addr << 1);
847 reg.set_oa2en(true);
848 });
849 }
850
851 fn determine_matched_address(&self) -> Result<Address, Error> {
852 let matched = self.info.regs.isr().read().addcode();
853
854 if matched >> 3 == 0b11110 {
855 // is 10-bit address and we need to get the other 8 bits from the rxdr
856 // we do this by doing a blocking read of 1 byte
857 let mut buffer = [0];
858 self.slave_read_internal(&mut buffer, self.timeout())?;
859 Ok(Address::TenBit((matched as u16) << 6 | buffer[0] as u16))
860 } else {
861 Ok(Address::SevenBit(matched))
862 }
863 }
864}
865
866impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
867 /// # Safety
868 /// This function will clear the address flag which will stop the clock stretching.
869 /// This should only be done after the dma transfer has been set up.
870 fn slave_start(info: &'static Info, length: usize, reload: bool) {
871 assert!(length < 256);
872
873 let reload = if reload {
874 i2c::vals::Reload::NOT_COMPLETED
875 } else {
876 i2c::vals::Reload::COMPLETED
877 };
878
879 info.regs.cr2().modify(|w| {
880 w.set_nbytes(length as u8);
881 w.set_reload(reload);
882 });
883
884 // clear the address flag, will stop the clock stretching.
885 // this should only be done after the dma transfer has been set up.
886 info.regs.icr().modify(|reg| reg.set_addrcf(true));
887 }
888
889 // A blocking read operation
890 fn slave_read_internal(&self, read: &mut [u8], timeout: Timeout) -> Result<(), Error> {
891 let completed_chunks = read.len() / 255;
892 let total_chunks = if completed_chunks * 255 == read.len() {
893 completed_chunks
894 } else {
895 completed_chunks + 1
896 };
897 let last_chunk_idx = total_chunks.saturating_sub(1);
898 for (number, chunk) in read.chunks_mut(255).enumerate() {
899 if number != 0 {
900 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
901 }
902
903 for byte in chunk {
904 // Wait until we have received something
905 self.wait_rxne(timeout)?;
906
907 *byte = self.info.regs.rxdr().read().rxdata();
908 }
909 }
910
911 Ok(())
912 }
913
914 // A blocking write operation
915 fn slave_write_internal(&mut self, write: &[u8], timeout: Timeout) -> Result<(), Error> {
916 let completed_chunks = write.len() / 255;
917 let total_chunks = if completed_chunks * 255 == write.len() {
918 completed_chunks
919 } else {
920 completed_chunks + 1
921 };
922 let last_chunk_idx = total_chunks.saturating_sub(1);
923
924 for (number, chunk) in write.chunks(255).enumerate() {
925 if number != 0 {
926 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
927 }
928
929 for byte in chunk {
930 // Wait until we are allowed to send data
931 // (START has been ACKed or last byte when
932 // through)
933 self.wait_txe(timeout)?;
934
935 self.info.regs.txdr().write(|w| w.set_txdata(*byte));
936 }
937 }
938 Ok(())
939 }
940
941 /// Listen for incoming I2C messages.
942 ///
943 /// The listen method is an asynchronous method but it does not require DMA to be asynchronous.
944 pub async fn listen(&mut self) -> Result<SlaveCommand, Error> {
945 let state = self.state;
946 self.info.regs.cr1().modify(|reg| {
947 reg.set_addrie(true);
948 });
949
950 poll_fn(|cx| {
951 state.waker.register(cx.waker());
952 let isr = self.info.regs.isr().read();
953 if !isr.addr() {
954 Poll::Pending
955 } else {
956 // we do not clear the address flag here as it will be cleared by the dma read/write
957 // if we clear it here the clock stretching will stop and the master will read in data before the slave is ready to send it
958 match isr.dir() {
959 i2c::vals::Dir::WRITE => Poll::Ready(Ok(SlaveCommand {
960 kind: SlaveCommandKind::Write,
961 address: self.determine_matched_address()?,
962 })),
963 i2c::vals::Dir::READ => Poll::Ready(Ok(SlaveCommand {
964 kind: SlaveCommandKind::Read,
965 address: self.determine_matched_address()?,
966 })),
967 }
968 }
969 })
970 .await
971 }
972
973 /// Respond to a write command.
974 pub fn blocking_respond_to_write(&self, read: &mut [u8]) -> Result<(), Error> {
975 let timeout = self.timeout();
976 self.slave_read_internal(read, timeout)
977 }
978
979 /// Respond to a read command.
980 pub fn blocking_respond_to_read(&mut self, write: &[u8]) -> Result<(), Error> {
981 let timeout = self.timeout();
982 self.slave_write_internal(write, timeout)
983 }
984}
985
986impl<'d> I2c<'d, Async, MultiMaster> {
987 /// Respond to a write command.
988 ///
989 /// Returns the total number of bytes received.
990 pub async fn respond_to_write(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
991 let timeout = self.timeout();
992 timeout.with(self.read_dma_internal_slave(buffer, timeout)).await
993 }
994
995 /// Respond to a read request from an I2C master.
996 pub async fn respond_to_read(&mut self, write: &[u8]) -> Result<SendStatus, Error> {
997 let timeout = self.timeout();
998 timeout.with(self.write_dma_internal_slave(write, timeout)).await
999 }
1000
1001 // for data reception in slave mode
1002 //
1003 // returns the total number of bytes received
1004 async fn read_dma_internal_slave(&mut self, buffer: &mut [u8], timeout: Timeout) -> Result<usize, Error> {
1005 let total_len = buffer.len();
1006 let mut remaining_len = total_len;
1007
1008 let regs = self.info.regs;
1009
1010 let dma_transfer = unsafe {
1011 regs.cr1().modify(|w| {
1012 w.set_rxdmaen(true);
1013 w.set_stopie(true);
1014 w.set_tcie(true);
1015 });
1016 let src = regs.rxdr().as_ptr() as *mut u8;
1017
1018 self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
1019 };
1020
1021 let state = self.state;
1022
1023 let on_drop = OnDrop::new(|| {
1024 regs.cr1().modify(|w| {
1025 w.set_rxdmaen(false);
1026 w.set_stopie(false);
1027 w.set_tcie(false);
1028 })
1029 });
1030
1031 let total_received = poll_fn(|cx| {
1032 state.waker.register(cx.waker());
1033
1034 let isr = regs.isr().read();
1035
1036 if remaining_len == total_len {
1037 Self::slave_start(self.info, total_len.min(255), total_len > 255);
1038 remaining_len = remaining_len.saturating_sub(255);
1039 Poll::Pending
1040 } else if isr.tcr() {
1041 let is_last_slice = remaining_len <= 255;
1042 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !is_last_slice, timeout) {
1043 return Poll::Ready(Err(e));
1044 }
1045 remaining_len = remaining_len.saturating_sub(255);
1046 regs.cr1().modify(|w| w.set_tcie(true));
1047 Poll::Pending
1048 } else if isr.stopf() {
1049 regs.icr().write(|reg| reg.set_stopcf(true));
1050 let poll = Poll::Ready(Ok(total_len - remaining_len));
1051 poll
1052 } else {
1053 Poll::Pending
1054 }
1055 })
1056 .await?;
1057
1058 dma_transfer.await;
1059
1060 drop(on_drop);
1061
1062 Ok(total_received)
1063 }
1064
1065 async fn write_dma_internal_slave(&mut self, buffer: &[u8], timeout: Timeout) -> Result<SendStatus, Error> {
1066 let total_len = buffer.len();
1067 let mut remaining_len = total_len;
1068
1069 let mut dma_transfer = unsafe {
1070 let regs = self.info.regs;
1071 regs.cr1().modify(|w| {
1072 w.set_txdmaen(true);
1073 w.set_stopie(true);
1074 w.set_tcie(true);
1075 });
1076 let dst = regs.txdr().as_ptr() as *mut u8;
1077
1078 self.tx_dma.as_mut().unwrap().write(buffer, dst, Default::default())
1079 };
1080
1081 let on_drop = OnDrop::new(|| {
1082 let regs = self.info.regs;
1083 regs.cr1().modify(|w| {
1084 w.set_txdmaen(false);
1085 w.set_stopie(false);
1086 w.set_tcie(false);
1087 })
1088 });
1089
1090 let state = self.state;
1091
1092 let size = poll_fn(|cx| {
1093 state.waker.register(cx.waker());
1094
1095 let isr = self.info.regs.isr().read();
1096
1097 if remaining_len == total_len {
1098 Self::slave_start(self.info, total_len.min(255), total_len > 255);
1099 remaining_len = remaining_len.saturating_sub(255);
1100 Poll::Pending
1101 } else if isr.tcr() {
1102 let is_last_slice = remaining_len <= 255;
1103 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !is_last_slice, timeout) {
1104 return Poll::Ready(Err(e));
1105 }
1106 remaining_len = remaining_len.saturating_sub(255);
1107 self.info.regs.cr1().modify(|w| w.set_tcie(true));
1108 Poll::Pending
1109 } else if isr.stopf() {
1110 self.info.regs.icr().write(|reg| reg.set_stopcf(true));
1111 if remaining_len > 0 {
1112 dma_transfer.request_stop();
1113 Poll::Ready(Ok(SendStatus::LeftoverBytes(remaining_len as usize)))
1114 } else {
1115 Poll::Ready(Ok(SendStatus::Done))
1116 }
1117 } else {
1118 Poll::Pending
1119 }
1120 })
1121 .await?;
1122
1123 dma_transfer.await;
1124
1125 drop(on_drop);
1126
1127 Ok(size)
1128 }
1129}
1130
736/// I2C Stop Configuration 1131/// I2C Stop Configuration
737/// 1132///
738/// Peripheral options for generating the STOP condition 1133/// Peripheral options for generating the STOP condition
@@ -857,7 +1252,7 @@ impl Timings {
857 } 1252 }
858} 1253}
859 1254
860impl<'d, M: Mode> SetConfig for I2c<'d, M> { 1255impl<'d, M: Mode> SetConfig for I2c<'d, M, Master> {
861 type Config = Hertz; 1256 type Config = Hertz;
862 type ConfigError = (); 1257 type ConfigError = ();
863 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { 1258 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
@@ -882,3 +1277,21 @@ impl<'d, M: Mode> SetConfig for I2c<'d, M> {
882 Ok(()) 1277 Ok(())
883 } 1278 }
884} 1279}
1280
1281impl<'d, M: Mode> SetConfig for I2c<'d, M, MultiMaster> {
1282 type Config = (Hertz, SlaveAddrConfig);
1283 type ConfigError = ();
1284 fn set_config(&mut self, (config, addr_config): &Self::Config) -> Result<(), ()> {
1285 let timings = Timings::new(self.kernel_clock, *config);
1286 self.info.regs.timingr().write(|reg| {
1287 reg.set_presc(timings.prescale);
1288 reg.set_scll(timings.scll);
1289 reg.set_sclh(timings.sclh);
1290 reg.set_sdadel(timings.sdadel);
1291 reg.set_scldel(timings.scldel);
1292 });
1293 self.init_slave(*addr_config);
1294
1295 Ok(())
1296 }
1297}