stm32f3xx_hal/
i2c.rs

1//! # Inter-Integrated Circuit (I2C) bus
2//!
3//! ## Examples
4//!
5//! A usage example of the i2c peripheral can be found at [examples/i2c_scanner.rs]
6//!
7//! [examples/i2c_scanner.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/i2c_scanner.rs
8
9use 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/// I2C error
34#[derive(Debug)]
35#[non_exhaustive]
36pub enum Error {
37    /// Arbitration loss
38    Arbitration,
39    /// Bus error
40    Bus,
41    /// Bus busy
42    Busy,
43    /// Not Acknowledge received
44    Nack,
45    // Overrun, // slave mode only
46    // Pec, // SMBUS mode only
47    // Timeout, // SMBUS mode only
48    // Alert, // SMBUS mode only
49}
50
51/// SCL pin
52pub trait SclPin<I2C>: crate::private::Sealed {}
53
54/// SDA pin
55pub 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
85/// I2C peripheral operating in master mode
86pub 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    /// Configures the I2C peripheral to work in master mode
117    ///
118    /// # Panics
119    ///
120    /// Panics if frequency `freq` can not be configured for the periphery.
121    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        // TODO review compliance with the timing requirements of I2C
139        // t_I2CCLK = 1 / PCLK1
140        // t_PRESC  = (PRESC + 1) * t_I2CCLK
141        // t_SCLL   = (SCLL + 1) * t_PRESC
142        // t_SCLH   = (SCLH + 1) * t_PRESC
143        //
144        // t_SYNC1 + t_SYNC2 > 4 * t_I2CCLK
145        // t_SCL ~= t_SYNC1 + t_SYNC2 + t_SCLL + t_SCLH
146        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            // fast-mode or fast-mode plus
150            // here we pick SCLL + 1 = 2 * (SCLH + 1)
151            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                // fast-mode plus
158                let sdadel = 0;
159                let scldel = i2cclk / 4_000_000 / (presc + 1) - 1;
160
161                (sdadel, scldel)
162            } else {
163                // fast-mode
164                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            // standard-mode
173            // here we pick SCLL = SCLH
174            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        // Configure for "fast mode" (400 KHz)
192        // NOTE(write): writes all non-reserved bits.
193        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        // Enable the peripheral
207        i2c.cr1.modify(|_, w| w.pe().set_bit());
208
209        Self { i2c, pins }
210    }
211
212    /// Get access to the underlying register block.
213    ///
214    /// # Safety
215    ///
216    /// This function is not _memory_ unsafe per se, but does not guarantee
217    /// anything about assumptions of invariants made in this implementation.
218    ///
219    /// Changing specific options can lead to un-expected behavior and nothing
220    /// is guaranteed.
221    pub unsafe fn peripheral(&mut self) -> &mut I2C {
222        &mut self.i2c
223    }
224
225    /// Releases the I2C peripheral and associated pins
226    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        // Detect Bus busy
241        if self.i2c.isr.read().busy().is_busy() {
242            return Err(Error::Busy);
243        }
244
245        let end = buffer.len() / 0xFF;
246
247        // Process 255 bytes at a time
248        for (i, buffer) in buffer.chunks_mut(0xFF).enumerate() {
249            // Prepare to receive `bytes`
250            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                // Wait until we have received something
268                busy_wait!(self.i2c, rxne, is_not_empty);
269
270                *byte = self.i2c.rxdr.read().rxdata().bits();
271            }
272
273            if i != end {
274                // Wait until the last transmission is finished
275                busy_wait!(self.i2c, tcr, is_complete);
276            }
277        }
278
279        // automatic STOP
280        // Wait until the last transmission is finished
281        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        // Detect Bus busy
297        if self.i2c.isr.read().busy().is_busy() {
298            return Err(Error::Busy);
299        }
300
301        if bytes.is_empty() {
302            // 0 byte write
303            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            // Process 255 bytes at a time
317            for (i, bytes) in bytes.chunks(0xFF).enumerate() {
318                // Prepare to send `bytes`
319                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                    // Wait until we are allowed to send data
337                    // (START has been ACKed or last byte went through)
338                    busy_wait!(self.i2c, txis, is_empty);
339
340                    // Put byte on the wire
341                    // NOTE(write): Writes all non-reserved bits.
342                    self.i2c.txdr.write(|w| w.txdata().bits(*byte));
343                }
344
345                if i != end {
346                    // Wait until the last transmission is finished
347                    busy_wait!(self.i2c, tcr, is_complete);
348                }
349            }
350        }
351
352        // automatic STOP
353        // Wait until the last transmission is finished
354        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        // Detect Bus busy
372        if self.i2c.isr.read().busy().is_busy() {
373            return Err(Error::Busy);
374        }
375
376        let end = bytes.len() / 0xFF;
377
378        // Process 255 bytes at a time
379        for (i, bytes) in bytes.chunks(0xFF).enumerate() {
380            // Prepare to send `bytes`
381            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                // Wait until we are allowed to send data
399                // (START has been ACKed or last byte went through)
400                busy_wait!(self.i2c, txis, is_empty);
401
402                // Put byte on the wire
403                // NOTE(write): Writes all non-reserved bits.
404                self.i2c.txdr.write(|w| w.txdata().bits(*byte));
405            }
406
407            if i != end {
408                // Wait until the last transmission is finished
409                busy_wait!(self.i2c, tcr, is_complete);
410            }
411        }
412
413        // Wait until the last transmission is finished
414        busy_wait!(self.i2c, tc, is_complete);
415
416        // restart
417
418        let end = buffer.len() / 0xFF;
419
420        // Process 255 bytes at a time
421        for (i, buffer) in buffer.chunks_mut(0xFF).enumerate() {
422            // Prepare to receive `bytes`
423            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                // Wait until we have received something
441                busy_wait!(self.i2c, rxne, is_not_empty);
442
443                *byte = self.i2c.rxdr.read().rxdata().bits();
444            }
445
446            if i != end {
447                // Wait until the last transmission is finished
448                busy_wait!(self.i2c, tcr, is_complete);
449            }
450        }
451
452        // automatic STOP
453        // Wait until the last transmission is finished
454        busy_wait!(self.i2c, stopf, is_stop);
455
456        self.i2c.icr.write(|w| w.stopcf().clear());
457
458        Ok(())
459    }
460}
461
462/// I2C instance
463pub 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                    // SAFETY: atomic read of valid pointer with no side effects
476                    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]);