1use crate::gpio::{self, Alternate, OpenDrain};
7use crate::hal::blocking::i2c::{Read, Write, WriteRead};
8use crate::pac::{DWT, I2C1, I2C2, I2C3};
9use crate::rcc::{BusClock, Clocks, Enable, RccBus, Reset};
10use fugit::HertzU32 as Hertz;
11use nb::Error::{Other, WouldBlock};
12use nb::{Error as NbError, Result as NbResult};
13
14use cast::u16;
15
16#[derive(Debug, Eq, PartialEq)]
18#[non_exhaustive]
19pub enum Error {
20 Bus,
22 Arbitration,
24 Acknowledge,
26 Overrun,
28 Busy,
30 }
34
35#[derive(Debug, PartialEq)]
38pub enum Mode {
39 Standard { frequency: Hertz },
40 Fast { frequency: Hertz },
41 FastPlus { frequency: Hertz },
42 Custom { timing_r: u32 },
43}
44
45impl Mode {
46 pub fn standard(frequency: Hertz) -> Self {
47 Mode::Standard { frequency }
48 }
49
50 pub fn fast(frequency: Hertz) -> Self {
51 Mode::Fast { frequency }
52 }
53
54 pub fn fast_plus(frequency: Hertz) -> Self {
55 Mode::FastPlus { frequency }
56 }
57}
58
59pub trait PinScl<I2C> {}
61
62pub trait PinSda<I2C> {}
64
65impl PinScl<I2C1> for gpio::PB6<Alternate<4, OpenDrain>> {}
66impl PinScl<I2C1> for gpio::PB8<Alternate<4, OpenDrain>> {}
67impl PinScl<I2C2> for gpio::PB10<Alternate<4, OpenDrain>> {}
68impl PinScl<I2C2> for gpio::PF1<Alternate<4, OpenDrain>> {}
69impl PinScl<I2C2> for gpio::PH4<Alternate<4, OpenDrain>> {}
70impl PinScl<I2C3> for gpio::PA8<Alternate<4, OpenDrain>> {}
71impl PinScl<I2C3> for gpio::PH7<Alternate<4, OpenDrain>> {}
72
73impl PinSda<I2C1> for gpio::PB7<Alternate<4, OpenDrain>> {}
74impl PinSda<I2C1> for gpio::PB9<Alternate<4, OpenDrain>> {}
75impl PinSda<I2C2> for gpio::PB11<Alternate<4, OpenDrain>> {}
76impl PinSda<I2C2> for gpio::PF0<Alternate<4, OpenDrain>> {}
77impl PinSda<I2C2> for gpio::PH5<Alternate<4, OpenDrain>> {}
78impl PinSda<I2C3> for gpio::PC9<Alternate<4, OpenDrain>> {}
79impl PinSda<I2C3> for gpio::PH8<Alternate<4, OpenDrain>> {}
80
81pub struct I2c<I2C, SCL, SDA> {
83 i2c: I2C,
84 pins: (SCL, SDA),
85 mode: Mode,
86 pclk: Hertz,
87}
88
89pub struct BlockingI2c<I2C, SCL, SDA> {
91 nb: I2c<I2C, SCL, SDA>,
92 data_timeout: u32,
93}
94
95impl<SCL, SDA> I2c<I2C1, SCL, SDA> {
96 pub fn i2c1(
98 i2c: I2C1,
99 pins: (SCL, SDA),
100 mode: Mode,
101 clocks: &Clocks,
102 apb: &mut <I2C1 as RccBus>::Bus,
103 ) -> Self
104 where
105 SCL: PinScl<I2C1>,
106 SDA: PinSda<I2C1>,
107 {
108 I2c::_i2c1(i2c, pins, mode, clocks, apb)
109 }
110}
111
112impl<SCL, SDA> BlockingI2c<I2C1, SCL, SDA> {
113 pub fn i2c1(
115 i2c: I2C1,
116 pins: (SCL, SDA),
117 mode: Mode,
118 clocks: &Clocks,
119 apb: &mut <I2C1 as RccBus>::Bus,
120 data_timeout_us: u32,
121 ) -> Self
122 where
123 SCL: PinScl<I2C1>,
124 SDA: PinSda<I2C1>,
125 {
126 BlockingI2c::_i2c1(i2c, pins, mode, clocks, apb, data_timeout_us)
127 }
128}
129
130impl<SCL, SDA> I2c<I2C2, SCL, SDA> {
131 pub fn i2c2(
133 i2c: I2C2,
134 pins: (SCL, SDA),
135 mode: Mode,
136 clocks: &Clocks,
137 apb: &mut <I2C2 as RccBus>::Bus,
138 ) -> Self
139 where
140 SCL: PinScl<I2C2>,
141 SDA: PinSda<I2C2>,
142 {
143 I2c::_i2c2(i2c, pins, mode, clocks, apb)
144 }
145}
146
147impl<SCL, SDA> BlockingI2c<I2C2, SCL, SDA> {
148 pub fn i2c2(
150 i2c: I2C2,
151 pins: (SCL, SDA),
152 mode: Mode,
153 clocks: &Clocks,
154 apb: &mut <I2C2 as RccBus>::Bus,
155 data_timeout_us: u32,
156 ) -> Self
157 where
158 SCL: PinScl<I2C2>,
159 SDA: PinSda<I2C2>,
160 {
161 BlockingI2c::_i2c2(i2c, pins, mode, clocks, apb, data_timeout_us)
162 }
163}
164
165impl<SCL, SDA> I2c<I2C3, SCL, SDA> {
166 pub fn i2c3(
168 i2c: I2C3,
169 pins: (SCL, SDA),
170 mode: Mode,
171 clocks: &Clocks,
172 apb: &mut <I2C3 as RccBus>::Bus,
173 ) -> Self
174 where
175 SCL: PinScl<I2C3>,
176 SDA: PinSda<I2C3>,
177 {
178 I2c::_i2c3(i2c, pins, mode, clocks, apb)
179 }
180}
181
182impl<SCL, SDA> BlockingI2c<I2C3, SCL, SDA> {
183 pub fn i2c3(
185 i2c: I2C3,
186 pins: (SCL, SDA),
187 mode: Mode,
188 clocks: &Clocks,
189 apb: &mut <I2C3 as RccBus>::Bus,
190 data_timeout_us: u32,
191 ) -> Self
192 where
193 SCL: PinScl<I2C3>,
194 SDA: PinSda<I2C3>,
195 {
196 BlockingI2c::_i2c3(i2c, pins, mode, clocks, apb, data_timeout_us)
197 }
198}
199
200fn blocking_i2c<I2C, SCL, SDA>(
202 i2c: I2c<I2C, SCL, SDA>,
203 clocks: &Clocks,
204 data_timeout_us: u32,
205) -> BlockingI2c<I2C, SCL, SDA> {
206 let sysclk_mhz = clocks.sysclk().to_MHz();
207 BlockingI2c {
208 nb: i2c,
209 data_timeout: data_timeout_us * sysclk_mhz,
210 }
211}
212
213struct I2cSpec {
216 freq_max: u32,
217 sudat_min: u32,
218 _lscl_min: u32,
219 _hscl_min: u32,
220 trise_max: u32, _tfall_max: u32,
222}
223
224#[derive(Debug)]
225struct I2cTiming {
226 presc: u8,
227 scldel: u8,
228 sdadel: u8,
229 sclh: u8,
230 scll: u8,
231}
232
233const I2C_STANDARD_MODE_SPEC: I2cSpec = I2cSpec {
235 freq_max: 102400,
236 sudat_min: 250,
237 _lscl_min: 4700,
238 _hscl_min: 4000,
239 trise_max: 640,
240 _tfall_max: 20,
241};
242const I2C_FAST_MODE_SPEC: I2cSpec = I2cSpec {
243 freq_max: 409600,
244 sudat_min: 100,
245 _lscl_min: 1300,
246 _hscl_min: 600,
247 trise_max: 250,
248 _tfall_max: 100,
249};
250
251const I2C_FAST_PLUS_MODE_SPEC: I2cSpec = I2cSpec {
252 freq_max: 1024000,
253 sudat_min: 50,
254 _lscl_min: 500,
255 _hscl_min: 260,
256 trise_max: 60,
257 _tfall_max: 100,
258};
259
260fn calculate_timing(
261 spec: I2cSpec,
262 i2c_freq: u32,
263 scl_freq: u32,
264 an_filter: bool,
265 dnf: u8,
266) -> I2cTiming {
267 #[cfg(not(test))]
270 use micromath::F32Ext as _;
271
272 assert!(scl_freq <= spec.freq_max);
274 let t_dnf = (dnf) as f32 / i2c_freq as f32;
278 let t_af: f32 = if an_filter {
280 40.0 / 1_000_000_000f32
281 } else {
282 0.0
283 };
284 let t_sync = 2.0 / (i2c_freq as f32);
286 let t_fall: f32 = 50f32 / 1_000_000_000f32;
288 let t_rise: f32 = 60f32 / 1_000_000_000f32;
289 let t_delay = t_fall + t_rise + 2.0 * (t_dnf + t_af + t_sync);
290 let product: f32 = (1.0 - t_delay * (scl_freq as f32)) * (i2c_freq / scl_freq) as f32;
296 let scl_l: u8;
297 let scl_h: u8;
298 let mut presc: u8;
299 if product > 8192_f32 {
302 scl_l = 0x7fu8;
304 scl_h = 0x7fu8;
305 presc = 0xfu8;
306 } else {
307 let mut min_deviation = 16f32;
310 let presc_start = (product / 512.0).ceil() as u8;
312 presc = presc_start;
313 for tmp_presc in presc_start..17 {
314 let deviation = product % tmp_presc as f32;
315 if min_deviation > deviation {
316 min_deviation = deviation;
317 presc = tmp_presc as u8;
318 }
319 }
320 let scl_width = (product / presc as f32) as u16; scl_h = (scl_width / 2 - 1) as u8;
324 scl_l = (scl_width - scl_h as u16 - 1) as u8; presc -= 1;
326 }
327 let scldel: u8 = (((spec.trise_max + spec.sudat_min) as f32 / 1_000_000_000.0)
328 / ((presc + 1) as f32 / i2c_freq as f32)
329 - 1.0)
330 .ceil() as u8;
331 I2cTiming {
332 presc,
333 scldel,
334 sdadel: 0,
335 sclh: scl_h,
336 scll: scl_l,
337 }
338}
339
340macro_rules! check_status_flag {
341 ($i2c:expr, $flag:ident, $status:ident) => {{
342 let isr = $i2c.isr.read();
343
344 if isr.berr().bit_is_set() {
345 $i2c.icr.write(|w| w.berrcf().set_bit());
346 Err(Other(Error::Bus))
347 } else if isr.arlo().bit_is_set() {
348 $i2c.icr.write(|w| w.arlocf().set_bit());
349 Err(Other(Error::Arbitration))
350 } else if isr.nackf().bit_is_set() {
351 $i2c.icr.write(|w| w.stopcf().set_bit().nackcf().set_bit());
352 Err(Other(Error::Acknowledge))
353 } else if isr.ovr().bit_is_set() {
354 $i2c.icr.write(|w| w.stopcf().set_bit().ovrcf().set_bit());
355 Err(Other(Error::Overrun))
356 } else if isr.$flag().$status() {
357 Ok(())
358 } else {
359 Err(WouldBlock)
360 }
361 }};
362}
363
364macro_rules! busy_wait {
365 ($nb_expr:expr, $exit_cond:expr) => {{
366 loop {
367 let res = $nb_expr;
368 if res != Err(WouldBlock) {
369 break res;
370 }
371 if $exit_cond {
372 break res;
373 }
374 }
375 }};
376}
377
378macro_rules! busy_wait_cycles {
379 ($nb_expr:expr, $cycles:expr) => {{
380 let started = DWT::cycle_count();
381 let cycles = $cycles;
382 busy_wait!($nb_expr, DWT::cycle_count().wrapping_sub(started) >= cycles)
383 }};
384}
385
386macro_rules! hal {
388 ($($I2CX:ident: ($i2cX:ident),)+) => {
389 $(
390 impl<SCL, SDA> I2c<$I2CX, SCL, SDA> {
391 fn $i2cX(
393 i2c: $I2CX,
394 pins: (SCL, SDA),
395 mode: Mode,
396 clocks: &Clocks,
397 apb: &mut <I2C1 as RccBus>::Bus
398 ) -> Self {
399 $I2CX::enable(apb);
400 $I2CX::reset(apb);
401
402 let pclk = <$I2CX>::clock(clocks);
403
404 let mut i2c = I2c { i2c, pins, mode, pclk };
405 i2c.init();
406 i2c
407 }
408
409 fn init(&mut self) {
414 self.i2c.cr1.write(|w| w.pe().disabled());
420
421 let an_filter:bool = self.i2c.cr1.read().anfoff().is_enabled();
422 let dnf = self.i2c.cr1.read().dnf().bits();
423
424 let i2c_timingr: I2cTiming = match self.mode {
425 Mode::Standard{ frequency } => calculate_timing(I2C_STANDARD_MODE_SPEC, self.pclk.raw(), frequency.raw(), an_filter, dnf ),
426 Mode::Fast{ frequency } => calculate_timing(I2C_FAST_MODE_SPEC, self.pclk.raw(), frequency.raw(), an_filter, dnf),
427 Mode::FastPlus{ frequency } => calculate_timing(I2C_FAST_PLUS_MODE_SPEC, self.pclk.raw(), frequency.raw(), an_filter, dnf ),
428 Mode::Custom{ timing_r } => {
429 I2cTiming{
430 presc: ((timing_r & 0xf000_0000) >> 28 ) as u8,
431 scldel: ((timing_r & 0x00f0_0000) >> 20 ) as u8 ,
432 sdadel: ((timing_r & 0x000f_0000) >> 16 ) as u8,
433 sclh: ((timing_r & 0x0000_ff00) >> 8 ) as u8,
434 scll: ((timing_r & 0x0000_00ff) >> 0 ) as u8,
435 }
436 }
437 };
438 self.i2c.timingr.write(|w|
439 w.presc()
440 .bits(i2c_timingr.presc)
441 .scll()
442 .bits(i2c_timingr.scll)
443 .sclh()
444 .bits(i2c_timingr.sclh)
445 .sdadel()
446 .bits(i2c_timingr.sdadel)
447 .scldel()
448 .bits(i2c_timingr.scldel)
449 );
450
451 self.i2c.cr1.modify(|_, w| w.pe().enabled());
452 }
453
454 #[allow(dead_code)]
456 fn reset(&mut self) {
457 self.i2c.cr1.write(|w| w.pe().disabled());
458 while self.i2c.cr1.read().pe().is_enabled() {}
460
461 self.i2c.cr1.write(|w| w.pe().enabled());
463 }
464
465 fn start(&self, addr: u8, n_bytes: u8, read: bool, auto_stop: bool) {
475 self.i2c.cr2.write(|mut w| {
476 w = w.sadd()
478 .bits(u16(addr << 1 | 0))
479 .add10().clear_bit()
480 .nbytes()
481 .bits(n_bytes as u8)
482 .start()
483 .set_bit();
484
485 w = match read {
487 true => w.rd_wrn().read(),
488 false => w.rd_wrn().write()
489 };
490
491 match auto_stop {
493 true => w.autoend().automatic(),
494 false => w.autoend().software(),
495 }
496 });
497 }
498
499 pub fn free(self) -> ($I2CX, (SCL, SDA)) {
501 (self.i2c, self.pins)
502 }
503 }
504
505 impl<SCL, SDA> BlockingI2c<$I2CX, SCL, SDA> {
506 fn $i2cX(
507 i2c: $I2CX,
508 pins: (SCL, SDA),
509 mode: Mode,
510 clocks: &Clocks,
511 apb: &mut <$I2CX as RccBus>::Bus,
512 data_timeout_us: u32
513 ) -> Self {
514 blocking_i2c(I2c::$i2cX(i2c, pins, mode, clocks, apb),
515 clocks, data_timeout_us)
516 }
517
518 fn wait_byte_read(&self) -> NbResult<u8, Error> {
521 busy_wait_cycles!(
523 check_status_flag!(self.nb.i2c, rxne, is_not_empty),
524 self.data_timeout
525 )?;
526
527 Ok(self.nb.i2c.rxdr.read().rxdata().bits())
528 }
529
530 fn wait_byte_write(&self, byte: u8) -> NbResult<(), Error> {
533 busy_wait_cycles!(
536 check_status_flag!(self.nb.i2c, txis, is_empty),
537 self.data_timeout
538 )?;
539
540 self.nb.i2c.txdr.write(|w| w.txdata().bits(byte));
542
543 Ok(())
544 }
545
546 fn wait_start(&self) {
548 while self.nb.i2c.cr2.read().start().bit_is_set() {};
549 }
550 }
551
552 impl<SCL, SDA> Write for BlockingI2c<$I2CX, SCL, SDA> {
553 type Error = NbError<Error>;
554
555 fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> {
558 assert!(bytes.len() < 256 && bytes.len() > 0);
560
561 self.wait_start();
565
566 self.nb.start(addr, bytes.len() as u8, false, true);
570
571 for byte in bytes {
572 self.wait_byte_write(*byte)?;
573 }
574 Ok(())
577 }
578 }
579
580 impl<SCL, SDA> Read for BlockingI2c<$I2CX, SCL, SDA> {
581 type Error = NbError<Error>;
582
583 fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
585 assert!(buffer.len() < 256 && buffer.len() > 0);
587
588 self.wait_start();
592
593 self.nb.start(addr, buffer.len() as u8, true, true);
597
598 for byte in buffer {
599 *byte = self.wait_byte_read()?;
600 }
601
602 Ok(())
605 }
606 }
607
608 impl<SCL, SDA> WriteRead for BlockingI2c<$I2CX, SCL, SDA> {
609 type Error = NbError<Error>;
610
611 fn write_read(
612 &mut self,
613 addr: u8,
614 bytes: &[u8],
615 buffer: &mut [u8],
616 ) -> Result<(), Self::Error> {
617 assert!(bytes.len() < 256 && bytes.len() > 0);
619 assert!(buffer.len() < 256 && buffer.len() > 0);
620
621 self.wait_start();
623 self.nb.start(addr, bytes.len() as u8, false, false);
624
625 for byte in bytes {
626 self.wait_byte_write(*byte)?;
627 }
628
629 busy_wait_cycles!(
632 check_status_flag!(self.nb.i2c, tc, is_complete),
633 self.data_timeout
634 )?;
635
636 self.nb.start(addr, buffer.len() as u8, true, true);
638
639 for byte in buffer {
640 *byte = self.wait_byte_read()?;
641 }
642 Ok(())
645 }
646 }
647 )+
648 }
649}
650
651hal! {
652 I2C1: (_i2c1),
653 I2C2: (_i2c2),
654 I2C3: (_i2c3),
655}