1use core::{convert::TryFrom, ops::Deref};
10
11use crate::{
12 gpio::{gpioa, gpiob, OpenDrain, AF4},
13 hal::blocking::i2c::{Read, Write, WriteRead},
14 pac::{i2c1::RegisterBlock, rcc::cfgr3::I2C1SW_A, I2C1, RCC},
15 rcc::{self, Clocks},
16 time::{
17 fixed_point::FixedPoint,
18 rate::{Extensions, Hertz},
19 },
20};
21
22#[cfg(not(feature = "gpio-f333"))]
23use crate::{gpio::gpiof, pac::I2C2};
24
25#[cfg(any(feature = "gpio-f302", feature = "gpio-f303e"))]
26use crate::{
27 gpio::{gpioc, AF3, AF8},
28 pac::I2C3,
29};
30
31use cfg_if::cfg_if;
32
33#[derive(Debug)]
35#[non_exhaustive]
36pub enum Error {
37 Arbitration,
39 Bus,
41 Busy,
43 Nack,
45 }
50
51pub trait SclPin<I2C>: crate::private::Sealed {}
53
54pub trait SdaPin<I2C>: crate::private::Sealed {}
56
57impl SclPin<I2C1> for gpioa::PA15<AF4<OpenDrain>> {}
58impl SclPin<I2C1> for gpiob::PB6<AF4<OpenDrain>> {}
59impl SclPin<I2C1> for gpiob::PB8<AF4<OpenDrain>> {}
60impl SdaPin<I2C1> for gpioa::PA14<AF4<OpenDrain>> {}
61impl SdaPin<I2C1> for gpiob::PB7<AF4<OpenDrain>> {}
62impl SdaPin<I2C1> for gpiob::PB9<AF4<OpenDrain>> {}
63
64cfg_if! {
65 if #[cfg(not(feature = "gpio-f333"))] {
66 impl SclPin<I2C2> for gpioa::PA9<AF4<OpenDrain>> {}
67 impl SclPin<I2C2> for gpiof::PF1<AF4<OpenDrain>> {}
68 #[cfg(any(feature = "gpio-f303", feature = "gpio-f303e", feature = "gpio-f373"))]
69 impl SclPin<I2C2> for gpiof::PF6<AF4<OpenDrain>> {}
70 impl SdaPin<I2C2> for gpioa::PA10<AF4<OpenDrain>> {}
71 impl SdaPin<I2C2> for gpiof::PF0<AF4<OpenDrain>> {}
72 #[cfg(feature = "gpio-f373")]
73 impl SdaPin<I2C2> for gpiof::PF7<AF4<OpenDrain>> {}
74 }
75}
76
77cfg_if! {
78 if #[cfg(any(feature = "gpio-f302", feature = "gpio-f303e"))] {
79 impl SclPin<I2C3> for gpioa::PA8<AF3<OpenDrain>> {}
80 impl SdaPin<I2C3> for gpiob::PB5<AF8<OpenDrain>> {}
81 impl SdaPin<I2C3> for gpioc::PC9<AF3<OpenDrain>> {}
82 }
83}
84
85pub struct I2c<I2C, PINS> {
87 i2c: I2C,
88 pins: PINS,
89}
90
91macro_rules! busy_wait {
92 ($i2c:expr, $flag:ident, $variant:ident) => {
93 loop {
94 let isr = $i2c.isr.read();
95 let icr = &$i2c.icr;
96
97 if isr.arlo().is_lost() {
98 icr.write(|w| w.arlocf().clear());
99 return Err(Error::Arbitration);
100 } else if isr.berr().is_error() {
101 icr.write(|w| w.berrcf().clear());
102 return Err(Error::Bus);
103 } else if isr.nackf().is_nack() {
104 while $i2c.isr.read().stopf().is_no_stop() {}
105 icr.write(|w| w.nackcf().clear());
106 icr.write(|w| w.stopcf().clear());
107 return Err(Error::Nack);
108 } else if isr.$flag().$variant() {
109 break;
110 }
111 }
112 };
113}
114
115impl<I2C, SCL, SDA> I2c<I2C, (SCL, SDA)> {
116 pub fn new(
122 i2c: I2C,
123 pins: (SCL, SDA),
124 freq: Hertz,
125 clocks: Clocks,
126 bus: &mut <I2C as rcc::RccBus>::Bus,
127 ) -> Self
128 where
129 I2C: Instance,
130 SCL: SclPin<I2C>,
131 SDA: SdaPin<I2C>,
132 {
133 crate::assert!(freq.integer() <= 1_000_000);
134
135 I2C::enable(bus);
136 I2C::reset(bus);
137
138 let i2cclk = I2C::clock(&clocks).0;
147 let ratio = i2cclk / freq.integer() - 4;
148 let (presc, scl_low, scl_high, sdadel, scldel) = if freq >= 100.kHz() {
149 let presc = ratio / 387;
152
153 let scl_high = ((ratio / (presc + 1)) - 3) / 3;
154 let scl_low = 2 * (scl_high + 1) - 1;
155
156 let (sdadel, scldel) = if freq > 400.kHz() {
157 let sdadel = 0;
159 let scldel = i2cclk / 4_000_000 / (presc + 1) - 1;
160
161 (sdadel, scldel)
162 } else {
163 let sdadel = i2cclk / 8_000_000 / (presc + 1);
165 let scldel = i2cclk / 2_000_000 / (presc + 1) - 1;
166
167 (sdadel, scldel)
168 };
169
170 (presc, scl_low, scl_high, sdadel, scldel)
171 } else {
172 let presc = ratio / 514;
175
176 let scl_high = ((ratio / (presc + 1)) - 2) / 2;
177 let scl_low = scl_high;
178
179 let sdadel = i2cclk / 2_000_000 / (presc + 1);
180 let scldel = i2cclk / 800_000 / (presc + 1) - 1;
181
182 (presc, scl_low, scl_high, sdadel, scldel)
183 };
184
185 crate::assert!(presc < 16);
186 crate::assert!(scldel < 16);
187 crate::assert!(sdadel < 16);
188 let scl_high = crate::unwrap!(u8::try_from(scl_high).ok());
189 let scl_low = crate::unwrap!(u8::try_from(scl_low).ok());
190
191 i2c.timingr.write(|w| {
194 w.presc()
195 .bits(crate::unwrap!(u8::try_from(presc)))
196 .sdadel()
197 .bits(crate::unwrap!(u8::try_from(sdadel)))
198 .scldel()
199 .bits(crate::unwrap!(u8::try_from(scldel)))
200 .scll()
201 .bits(scl_low)
202 .sclh()
203 .bits(scl_high)
204 });
205
206 i2c.cr1.modify(|_, w| w.pe().set_bit());
208
209 Self { i2c, pins }
210 }
211
212 pub unsafe fn peripheral(&mut self) -> &mut I2C {
222 &mut self.i2c
223 }
224
225 pub fn free(self) -> (I2C, (SCL, SDA)) {
227 (self.i2c, self.pins)
228 }
229}
230
231impl<I2C, PINS> Read for I2c<I2C, PINS>
232where
233 I2C: Instance,
234{
235 type Error = Error;
236
237 fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
238 crate::assert!(!buffer.is_empty());
239
240 if self.i2c.isr.read().busy().is_busy() {
242 return Err(Error::Busy);
243 }
244
245 let end = buffer.len() / 0xFF;
246
247 for (i, buffer) in buffer.chunks_mut(0xFF).enumerate() {
249 self.i2c.cr2.modify(|_, w| {
251 if i == 0 {
252 w.add10().bit7();
253 w.sadd()
254 .bits(u16::from(crate::unwrap!(addr.checked_shl(1))));
255 w.rd_wrn().read();
256 w.start().start();
257 }
258 w.nbytes().bits(crate::unwrap!(u8::try_from(buffer.len())));
259 if i == end {
260 w.reload().completed().autoend().automatic()
261 } else {
262 w.reload().not_completed()
263 }
264 });
265
266 for byte in buffer {
267 busy_wait!(self.i2c, rxne, is_not_empty);
269
270 *byte = self.i2c.rxdr.read().rxdata().bits();
271 }
272
273 if i != end {
274 busy_wait!(self.i2c, tcr, is_complete);
276 }
277 }
278
279 busy_wait!(self.i2c, stopf, is_stop);
282
283 self.i2c.icr.write(|w| w.stopcf().clear());
284
285 Ok(())
286 }
287}
288
289impl<I2C, PINS> Write for I2c<I2C, PINS>
290where
291 I2C: Instance,
292{
293 type Error = Error;
294
295 fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
296 if self.i2c.isr.read().busy().is_busy() {
298 return Err(Error::Busy);
299 }
300
301 if bytes.is_empty() {
302 self.i2c.cr2.modify(|_, w| {
304 w.add10().bit7();
305 w.sadd()
306 .bits(u16::from(crate::unwrap!(addr.checked_shl(1))));
307 w.rd_wrn().write();
308 w.nbytes().bits(0);
309 w.reload().completed();
310 w.autoend().automatic();
311 w.start().start()
312 });
313 } else {
314 let end = bytes.len() / 0xFF;
315
316 for (i, bytes) in bytes.chunks(0xFF).enumerate() {
318 self.i2c.cr2.modify(|_, w| {
320 if i == 0 {
321 w.add10().bit7();
322 w.sadd()
323 .bits(u16::from(crate::unwrap!(addr.checked_shl(1))));
324 w.rd_wrn().write();
325 w.start().start();
326 }
327 w.nbytes().bits(crate::unwrap!(u8::try_from(bytes.len())));
328 if i == end {
329 w.reload().completed().autoend().automatic()
330 } else {
331 w.reload().not_completed()
332 }
333 });
334
335 for byte in bytes {
336 busy_wait!(self.i2c, txis, is_empty);
339
340 self.i2c.txdr.write(|w| w.txdata().bits(*byte));
343 }
344
345 if i != end {
346 busy_wait!(self.i2c, tcr, is_complete);
348 }
349 }
350 }
351
352 busy_wait!(self.i2c, stopf, is_stop);
355
356 self.i2c.icr.write(|w| w.stopcf().clear());
357
358 Ok(())
359 }
360}
361
362impl<I2C, PINS> WriteRead for I2c<I2C, PINS>
363where
364 I2C: Instance,
365{
366 type Error = Error;
367
368 fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
369 crate::assert!(!bytes.is_empty() && !buffer.is_empty());
370
371 if self.i2c.isr.read().busy().is_busy() {
373 return Err(Error::Busy);
374 }
375
376 let end = bytes.len() / 0xFF;
377
378 for (i, bytes) in bytes.chunks(0xFF).enumerate() {
380 self.i2c.cr2.modify(|_, w| {
382 if i == 0 {
383 w.add10().bit7();
384 w.sadd()
385 .bits(u16::from(crate::unwrap!(addr.checked_shl(1))));
386 w.rd_wrn().write();
387 w.start().start();
388 }
389 w.nbytes().bits(crate::unwrap!(u8::try_from(bytes.len())));
390 if i == end {
391 w.reload().completed().autoend().software()
392 } else {
393 w.reload().not_completed()
394 }
395 });
396
397 for byte in bytes {
398 busy_wait!(self.i2c, txis, is_empty);
401
402 self.i2c.txdr.write(|w| w.txdata().bits(*byte));
405 }
406
407 if i != end {
408 busy_wait!(self.i2c, tcr, is_complete);
410 }
411 }
412
413 busy_wait!(self.i2c, tc, is_complete);
415
416 let end = buffer.len() / 0xFF;
419
420 for (i, buffer) in buffer.chunks_mut(0xFF).enumerate() {
422 self.i2c.cr2.modify(|_, w| {
424 if i == 0 {
425 w.add10().bit7();
426 w.sadd()
427 .bits(u16::from(crate::unwrap!(addr.checked_shl(1))));
428 w.rd_wrn().read();
429 w.start().start();
430 }
431 w.nbytes().bits(crate::unwrap!(u8::try_from(buffer.len())));
432 if i == end {
433 w.reload().completed().autoend().automatic()
434 } else {
435 w.reload().not_completed()
436 }
437 });
438
439 for byte in buffer {
440 busy_wait!(self.i2c, rxne, is_not_empty);
442
443 *byte = self.i2c.rxdr.read().rxdata().bits();
444 }
445
446 if i != end {
447 busy_wait!(self.i2c, tcr, is_complete);
449 }
450 }
451
452 busy_wait!(self.i2c, stopf, is_stop);
455
456 self.i2c.icr.write(|w| w.stopcf().clear());
457
458 Ok(())
459 }
460}
461
462pub trait Instance:
464 Deref<Target = RegisterBlock> + crate::private::Sealed + rcc::Enable + rcc::Reset
465{
466 #[doc(hidden)]
467 fn clock(clocks: &Clocks) -> Hertz;
468}
469
470macro_rules! i2c {
471 ($($I2CX:ident: ($i2cXsw:ident),)+) => {
472 $(
473 impl Instance for $I2CX {
474 fn clock(clocks: &Clocks) -> Hertz {
475 match unsafe { (*RCC::ptr()).cfgr3.read().$i2cXsw().variant() } {
477 I2C1SW_A::Hsi => crate::rcc::HSI,
478 I2C1SW_A::Sysclk => clocks.sysclk(),
479 }
480 }
481 }
482 )+
483 };
484
485 ([ $($X:literal),+ ]) => {
486 paste::paste! {
487 i2c!(
488 $([<I2C $X>]: ([<i2c $X sw>]),)+
489 );
490 }
491 };
492}
493
494#[cfg(feature = "gpio-f333")]
495i2c!([1]);
496
497#[cfg(any(feature = "gpio-f303", feature = "gpio-f373"))]
498i2c!([1, 2]);
499
500#[cfg(any(feature = "gpio-f302", feature = "gpio-f303e"))]
501i2c!([1, 2, 3]);