aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--examples/stm32g4/src/bin/i2c_slave.rs149
-rw-r--r--examples/stm32h7/src/bin/i2c_shared.rs6
-rw-r--r--examples/stm32l4/src/bin/spe_adin1110_http_server.rs2
7 files changed, 867 insertions, 131 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}
diff --git a/examples/stm32g4/src/bin/i2c_slave.rs b/examples/stm32g4/src/bin/i2c_slave.rs
new file mode 100644
index 000000000..a723a0e18
--- /dev/null
+++ b/examples/stm32g4/src/bin/i2c_slave.rs
@@ -0,0 +1,149 @@
1//! This example shows how to use an stm32 as both a master and a slave.
2#![no_std]
3#![no_main]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_stm32::i2c::{Address, OwnAddresses, SlaveCommandKind};
8use embassy_stm32::mode::Async;
9use embassy_stm32::time::Hertz;
10use embassy_stm32::{bind_interrupts, i2c, peripherals};
11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _};
13
14bind_interrupts!(struct Irqs {
15 I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>;
16 I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
17 I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
18 I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
19});
20
21const DEV_ADDR: u8 = 0x42;
22
23#[embassy_executor::task]
24async fn device_task(mut dev: i2c::I2c<'static, Async, i2c::MultiMaster>) -> ! {
25 info!("Device start");
26
27 let mut state = 0;
28
29 loop {
30 let mut buf = [0u8; 128];
31 match dev.listen().await {
32 Ok(i2c::SlaveCommand {
33 kind: SlaveCommandKind::Read,
34 address: Address::SevenBit(DEV_ADDR),
35 }) => match dev.respond_to_read(&[state]).await {
36 Ok(i2c::SendStatus::LeftoverBytes(x)) => info!("tried to write {} extra bytes", x),
37 Ok(i2c::SendStatus::Done) => {}
38 Err(e) => error!("error while responding {}", e),
39 },
40 Ok(i2c::SlaveCommand {
41 kind: SlaveCommandKind::Write,
42 address: Address::SevenBit(DEV_ADDR),
43 }) => match dev.respond_to_write(&mut buf).await {
44 Ok(len) => {
45 info!("Device received write: {}", buf[..len]);
46
47 if match buf[0] {
48 // Set the state
49 0xC2 => {
50 state = buf[1];
51 true
52 }
53 // Reset State
54 0xC8 => {
55 state = 0;
56 true
57 }
58 x => {
59 error!("Invalid Write Read {:x}", x);
60 false
61 }
62 } {
63 match dev.respond_to_read(&[state]).await {
64 Ok(read_status) => info!(
65 "This read is part of a write/read transaction. The response read status {}",
66 read_status
67 ),
68 Err(i2c::Error::Timeout) => {
69 info!("The device only performed a write and it not also do a read")
70 }
71 Err(e) => error!("error while responding {}", e),
72 }
73 }
74 }
75 Err(e) => error!("error while receiving {}", e),
76 },
77 Ok(i2c::SlaveCommand { address, .. }) => {
78 defmt::unreachable!(
79 "The slave matched address: {}, which it was not configured for",
80 address
81 );
82 }
83 Err(e) => error!("{}", e),
84 }
85 }
86}
87
88#[embassy_executor::task]
89async fn controller_task(mut con: i2c::I2c<'static, Async, i2c::Master>) {
90 info!("Controller start");
91
92 loop {
93 let mut resp_buff = [0u8; 1];
94 for i in 0..10 {
95 match con.write_read(DEV_ADDR, &[0xC2, i], &mut resp_buff).await {
96 Ok(_) => {
97 info!("write_read response: {}", resp_buff);
98 defmt::assert_eq!(resp_buff[0], i);
99 }
100 Err(e) => error!("Error writing {}", e),
101 }
102
103 Timer::after_millis(100).await;
104 }
105 match con.read(DEV_ADDR, &mut resp_buff).await {
106 Ok(_) => {
107 info!("read response: {}", resp_buff);
108 // assert that the state is the last index that was written
109 defmt::assert_eq!(resp_buff[0], 9);
110 }
111 Err(e) => error!("Error writing {}", e),
112 }
113 match con.write_read(DEV_ADDR, &[0xC8], &mut resp_buff).await {
114 Ok(_) => {
115 info!("write_read response: {}", resp_buff);
116 // assert that the state has been reset
117 defmt::assert_eq!(resp_buff[0], 0);
118 }
119 Err(e) => error!("Error writing {}", e),
120 }
121 Timer::after_millis(100).await;
122 }
123}
124
125#[embassy_executor::main]
126async fn main(spawner: Spawner) {
127 let p = embassy_stm32::init(Default::default());
128 info!("Hello World!");
129
130 let speed = Hertz::khz(400);
131 let config = i2c::Config::default();
132
133 let d_addr_config = i2c::SlaveAddrConfig {
134 addr: OwnAddresses::OA1(Address::SevenBit(DEV_ADDR)),
135 general_call: false,
136 };
137 let d_sda = p.PA8;
138 let d_scl = p.PA9;
139 let device = i2c::I2c::new(p.I2C2, d_scl, d_sda, Irqs, p.DMA1_CH1, p.DMA1_CH2, speed, config)
140 .into_slave_multimaster(d_addr_config);
141
142 unwrap!(spawner.spawn(device_task(device)));
143
144 let c_sda = p.PB8;
145 let c_scl = p.PB7;
146 let controller = i2c::I2c::new(p.I2C1, c_sda, c_scl, Irqs, p.DMA1_CH3, p.DMA1_CH4, speed, config);
147
148 unwrap!(spawner.spawn(controller_task(controller)));
149}
diff --git a/examples/stm32h7/src/bin/i2c_shared.rs b/examples/stm32h7/src/bin/i2c_shared.rs
index 136b91eeb..655ff901f 100644
--- a/examples/stm32h7/src/bin/i2c_shared.rs
+++ b/examples/stm32h7/src/bin/i2c_shared.rs
@@ -25,7 +25,7 @@ const SHTC3_WAKEUP: [u8; 2] = [0x35, 0x17];
25const SHTC3_MEASURE_RH_FIRST: [u8; 2] = [0x5c, 0x24]; 25const SHTC3_MEASURE_RH_FIRST: [u8; 2] = [0x5c, 0x24];
26const SHTC3_SLEEP: [u8; 2] = [0xb0, 0x98]; 26const SHTC3_SLEEP: [u8; 2] = [0xb0, 0x98];
27 27
28static I2C_BUS: StaticCell<NoopMutex<RefCell<I2c<'static, Async>>>> = StaticCell::new(); 28static I2C_BUS: StaticCell<NoopMutex<RefCell<I2c<'static, Async, i2c::Master>>>> = StaticCell::new();
29 29
30bind_interrupts!(struct Irqs { 30bind_interrupts!(struct Irqs {
31 I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>; 31 I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
@@ -33,7 +33,7 @@ bind_interrupts!(struct Irqs {
33}); 33});
34 34
35#[embassy_executor::task] 35#[embassy_executor::task]
36async fn temperature(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async>>) { 36async fn temperature(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async, i2c::Master>>) {
37 let mut data = [0u8; 2]; 37 let mut data = [0u8; 2];
38 38
39 loop { 39 loop {
@@ -50,7 +50,7 @@ async fn temperature(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Asyn
50} 50}
51 51
52#[embassy_executor::task] 52#[embassy_executor::task]
53async fn humidity(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async>>) { 53async fn humidity(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async, i2c::Master>>) {
54 let mut data = [0u8; 6]; 54 let mut data = [0u8; 6];
55 55
56 loop { 56 loop {
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
index 354ac90b2..dc90a3b85 100644
--- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
+++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
@@ -59,7 +59,7 @@ pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>;
59pub type SpeInt = exti::ExtiInput<'static>; 59pub type SpeInt = exti::ExtiInput<'static>;
60pub type SpeRst = Output<'static>; 60pub type SpeRst = Output<'static>;
61pub type Adin1110T = ADIN1110<SpeSpiCs>; 61pub type Adin1110T = ADIN1110<SpeSpiCs>;
62pub type TempSensI2c = I2c<'static, Async>; 62pub type TempSensI2c = I2c<'static, Async, i2c::Master>;
63 63
64static TEMP: AtomicI32 = AtomicI32::new(0); 64static TEMP: AtomicI32 = AtomicI32::new(0);
65 65