stm32f0xx_hal/
i2c.rs

1use core::ops::Deref;
2
3use embedded_hal::blocking::i2c::{Read, Write, WriteRead};
4
5use crate::{
6    gpio::*,
7    rcc::Rcc,
8    time::{KiloHertz, U32Ext},
9};
10
11/// I2C abstraction
12pub struct I2c<I2C, SCLPIN, SDAPIN> {
13    i2c: I2C,
14    pins: (SCLPIN, SDAPIN),
15}
16
17pub trait SclPin<I2C> {}
18pub trait SdaPin<I2C> {}
19
20macro_rules! i2c_pins {
21    ($($I2C:ident => {
22        scl => [$($scl:ty),+ $(,)*],
23        sda => [$($sda:ty),+ $(,)*],
24    })+) => {
25        $(
26            $(
27                impl SclPin<crate::pac::$I2C> for $scl {}
28            )+
29            $(
30                impl SdaPin<crate::pac::$I2C> for $sda {}
31            )+
32        )+
33    }
34}
35
36#[cfg(any(
37    feature = "stm32f030",
38    feature = "stm32f031",
39    feature = "stm32f038",
40    feature = "stm32f042",
41    feature = "stm32f048",
42    feature = "stm32f051",
43    feature = "stm32f058",
44    feature = "stm32f070",
45    feature = "stm32f071",
46    feature = "stm32f072",
47    feature = "stm32f078",
48    feature = "stm32f091",
49    feature = "stm32f098",
50))]
51i2c_pins! {
52    I2C1 => {
53        scl => [gpiob::PB6<Alternate<AF1>>, gpiob::PB8<Alternate<AF1>>],
54        sda => [gpiob::PB7<Alternate<AF1>>, gpiob::PB9<Alternate<AF1>>],
55    }
56}
57#[cfg(any(
58    feature = "stm32f030x4",
59    feature = "stm32f030x6",
60    feature = "stm32f030xc",
61    feature = "stm32f031",
62    feature = "stm32f038",
63    feature = "stm32f042",
64    feature = "stm32f048",
65    feature = "stm32f070x6",
66    feature = "stm32f091",
67    feature = "stm32f098",
68))]
69i2c_pins! {
70    I2C1 => {
71        scl => [gpioa::PA9<Alternate<AF4>>],
72        sda => [gpioa::PA10<Alternate<AF4>>],
73    }
74}
75#[cfg(any(feature = "stm32f042", feature = "stm32f048"))]
76i2c_pins! {
77    I2C1 => {
78        scl => [gpioa::PA11<Alternate<AF5>>],
79        sda => [gpioa::PA12<Alternate<AF5>>],
80    }
81}
82#[cfg(any(
83    feature = "stm32f030x4",
84    feature = "stm32f030x6",
85    feature = "stm32f031",
86    feature = "stm32f038",
87    feature = "stm32f042",
88    feature = "stm32f048",
89))]
90i2c_pins! {
91    I2C1 => {
92        scl => [gpiob::PB10<Alternate<AF1>>],
93        sda => [gpiob::PB11<Alternate<AF1>>],
94    }
95}
96#[cfg(any(feature = "stm32f030xc", feature = "stm32f042", feature = "stm32f048"))]
97i2c_pins! {
98    I2C1 => {
99        scl => [gpiob::PB13<Alternate<AF5>>],
100        sda => [gpiob::PB14<Alternate<AF5>>],
101    }
102}
103#[cfg(any(
104    feature = "stm32f030xc",
105    feature = "stm32f042",
106    feature = "stm32f048",
107    feature = "stm32f070x6",
108    feature = "stm32f091",
109    feature = "stm32f098",
110))]
111i2c_pins! {
112    I2C1 => {
113        scl => [gpiof::PF1<Alternate<AF1>>],
114        sda => [gpiof::PF0<Alternate<AF1>>],
115    }
116}
117
118#[cfg(any(feature = "stm32f030x8", feature = "stm32f051", feature = "stm32f058"))]
119i2c_pins! {
120    I2C2 => {
121        scl => [gpiob::PB10<Alternate<AF1>>],
122        sda => [gpiob::PB11<Alternate<AF1>>],
123    }
124}
125#[cfg(any(
126    feature = "stm32f030xc",
127    feature = "stm32f070xb",
128    feature = "stm32f071",
129    feature = "stm32f072",
130    feature = "stm32f078",
131    feature = "stm32f091",
132    feature = "stm32f098",
133))]
134i2c_pins! {
135    I2C2 => {
136        scl => [gpiob::PB10<Alternate<AF1>>, gpiob::PB13<Alternate<AF5>>],
137        sda => [gpiob::PB11<Alternate<AF1>>, gpiob::PB14<Alternate<AF5>>],
138    }
139}
140#[cfg(any(feature = "stm32f091", feature = "stm32f098"))]
141i2c_pins! {
142    I2C2 => {
143        scl => [gpioa::PA11<Alternate<AF5>>],
144        sda => [gpioa::PA12<Alternate<AF5>>],
145    }
146}
147
148#[derive(Debug)]
149pub enum Error {
150    OVERRUN,
151    NACK,
152    BUS,
153}
154
155macro_rules! i2c {
156    ($($I2C:ident: ($i2c:ident, $i2cXen:ident, $i2cXrst:ident, $apbenr:ident, $apbrstr:ident),)+) => {
157        $(
158            use crate::pac::$I2C;
159            impl<SCLPIN, SDAPIN> I2c<$I2C, SCLPIN, SDAPIN> {
160                pub fn $i2c(i2c: $I2C, pins: (SCLPIN, SDAPIN), speed: KiloHertz, rcc: &mut Rcc) -> Self
161                where
162                    SCLPIN: SclPin<$I2C>,
163                    SDAPIN: SdaPin<$I2C>,
164                {
165                    // Enable clock for I2C
166                    rcc.regs.$apbenr.modify(|_, w| w.$i2cXen().set_bit());
167
168                    // Reset I2C
169                    rcc.regs.$apbrstr.modify(|_, w| w.$i2cXrst().set_bit());
170                    rcc.regs.$apbrstr.modify(|_, w| w.$i2cXrst().clear_bit());
171                    I2c { i2c, pins }.i2c_init(speed)
172                }
173            }
174        )+
175    }
176}
177
178i2c! {
179    I2C1: (i2c1, i2c1en, i2c1rst, apb1enr, apb1rstr),
180}
181
182#[cfg(any(
183    feature = "stm32f030x8",
184    feature = "stm32f030xc",
185    feature = "stm32f051",
186    feature = "stm32f058",
187    feature = "stm32f070xb",
188    feature = "stm32f071",
189    feature = "stm32f072",
190    feature = "stm32f078",
191    feature = "stm32f091",
192    feature = "stm32f098",
193))]
194i2c! {
195    I2C2: (i2c2, i2c2en, i2c2rst, apb1enr, apb1rstr),
196}
197
198// It's s needed for the impls, but rustc doesn't recognize that
199#[allow(dead_code)]
200type I2cRegisterBlock = crate::pac::i2c1::RegisterBlock;
201
202impl<I2C, SCLPIN, SDAPIN> I2c<I2C, SCLPIN, SDAPIN>
203where
204    I2C: Deref<Target = I2cRegisterBlock>,
205{
206    fn i2c_init(self, speed: KiloHertz) -> Self {
207        use core::cmp;
208
209        // Make sure the I2C unit is disabled so we can configure it
210        self.i2c.cr1.modify(|_, w| w.pe().clear_bit());
211
212        // Calculate settings for I2C speed modes
213        let presc;
214        let scldel;
215        let sdadel;
216        let sclh;
217        let scll;
218
219        // We're using HSI here which runs at a fixed 8MHz
220        const FREQ: u32 = 8_000_000;
221
222        // Normal I2C speeds use a different scaling than fast mode below
223        if speed <= 100_u32.khz() {
224            presc = 1;
225            scll = cmp::max((((FREQ >> presc) >> 1) / speed.0) - 1, 255) as u8;
226            sclh = scll - 4;
227            sdadel = 2;
228            scldel = 4;
229        } else {
230            presc = 0;
231            scll = cmp::max((((FREQ >> presc) >> 1) / speed.0) - 1, 255) as u8;
232            sclh = scll - 6;
233            sdadel = 1;
234            scldel = 3;
235        }
236
237        // Enable I2C signal generator, and configure I2C for configured speed
238        self.i2c.timingr.write(|w| {
239            w.presc()
240                .bits(presc)
241                .scldel()
242                .bits(scldel)
243                .sdadel()
244                .bits(sdadel)
245                .sclh()
246                .bits(sclh)
247                .scll()
248                .bits(scll)
249        });
250
251        // Enable the I2C processing
252        self.i2c.cr1.modify(|_, w| w.pe().set_bit());
253
254        self
255    }
256
257    pub fn release(self) -> (I2C, (SCLPIN, SDAPIN)) {
258        (self.i2c, self.pins)
259    }
260
261    fn check_and_clear_error_flags(&self, isr: &crate::stm32::i2c1::isr::R) -> Result<(), Error> {
262        // If we have a set overrun flag, clear it and return an OVERRUN error
263        if isr.ovr().bit_is_set() {
264            self.i2c.icr.write(|w| w.ovrcf().set_bit());
265            return Err(Error::OVERRUN);
266        }
267
268        // If we have a set arbitration error or bus error flag, clear it and return an BUS error
269        if isr.arlo().bit_is_set() | isr.berr().bit_is_set() {
270            self.i2c
271                .icr
272                .write(|w| w.arlocf().set_bit().berrcf().set_bit());
273            return Err(Error::BUS);
274        }
275
276        // If we received a NACK, then signal as a NACK error
277        if isr.nackf().bit_is_set() {
278            self.i2c
279                .icr
280                .write(|w| w.stopcf().set_bit().nackcf().set_bit());
281            return Err(Error::NACK);
282        }
283
284        Ok(())
285    }
286
287    fn send_byte(&self, byte: u8) -> Result<(), Error> {
288        // Wait until we're ready for sending
289        loop {
290            let isr = self.i2c.isr.read();
291            self.check_and_clear_error_flags(&isr)?;
292            if isr.txis().bit_is_set() {
293                break;
294            }
295        }
296
297        // Push out a byte of data
298        self.i2c.txdr.write(|w| unsafe { w.bits(u32::from(byte)) });
299
300        self.check_and_clear_error_flags(&self.i2c.isr.read())?;
301        Ok(())
302    }
303
304    fn recv_byte(&self) -> Result<u8, Error> {
305        loop {
306            let isr = self.i2c.isr.read();
307            self.check_and_clear_error_flags(&isr)?;
308            if isr.rxne().bit_is_set() {
309                break;
310            }
311        }
312
313        let value = self.i2c.rxdr.read().bits() as u8;
314        Ok(value)
315    }
316}
317
318impl<I2C, SCLPIN, SDAPIN> WriteRead for I2c<I2C, SCLPIN, SDAPIN>
319where
320    I2C: Deref<Target = I2cRegisterBlock>,
321{
322    type Error = Error;
323
324    fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
325        // Set up current slave address for writing and disable autoending
326        self.i2c.cr2.modify(|_, w| {
327            w.sadd()
328                .bits(u16::from(addr) << 1)
329                .nbytes()
330                .bits(bytes.len() as u8)
331                .rd_wrn()
332                .clear_bit()
333                .autoend()
334                .clear_bit()
335        });
336
337        // Send a START condition
338        self.i2c.cr2.modify(|_, w| w.start().set_bit());
339
340        // Wait until the transmit buffer is empty and there hasn't been any error condition
341        loop {
342            let isr = self.i2c.isr.read();
343            self.check_and_clear_error_flags(&isr)?;
344            if isr.txis().bit_is_set() || isr.tc().bit_is_set() {
345                break;
346            }
347        }
348
349        // Send out all individual bytes
350        for c in bytes {
351            self.send_byte(*c)?;
352        }
353
354        // Wait until data was sent
355        loop {
356            let isr = self.i2c.isr.read();
357            self.check_and_clear_error_flags(&isr)?;
358            if isr.tc().bit_is_set() {
359                break;
360            }
361        }
362
363        // Set up current address for reading
364        self.i2c.cr2.modify(|_, w| {
365            w.sadd()
366                .bits(u16::from(addr) << 1)
367                .nbytes()
368                .bits(buffer.len() as u8)
369                .rd_wrn()
370                .set_bit()
371        });
372
373        // Send another START condition
374        self.i2c.cr2.modify(|_, w| w.start().set_bit());
375
376        // Send the autoend after setting the start to get a restart
377        self.i2c.cr2.modify(|_, w| w.autoend().set_bit());
378
379        // Now read in all bytes
380        for c in buffer.iter_mut() {
381            *c = self.recv_byte()?;
382        }
383
384        // Check and clear flags if they somehow ended up set
385        self.check_and_clear_error_flags(&self.i2c.isr.read())?;
386
387        Ok(())
388    }
389}
390
391impl<I2C, SCLPIN, SDAPIN> Read for I2c<I2C, SCLPIN, SDAPIN>
392where
393    I2C: Deref<Target = I2cRegisterBlock>,
394{
395    type Error = Error;
396
397    fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> {
398        // Set up current address for reading
399        self.i2c.cr2.modify(|_, w| {
400            w.sadd()
401                .bits(u16::from(addr) << 1)
402                .nbytes()
403                .bits(buffer.len() as u8)
404                .rd_wrn()
405                .set_bit()
406        });
407
408        // Send a START condition
409        self.i2c.cr2.modify(|_, w| w.start().set_bit());
410
411        // Send the autoend after setting the start to get a restart
412        self.i2c.cr2.modify(|_, w| w.autoend().set_bit());
413
414        // Now read in all bytes
415        for c in buffer.iter_mut() {
416            *c = self.recv_byte()?;
417        }
418
419        // Check and clear flags if they somehow ended up set
420        self.check_and_clear_error_flags(&self.i2c.isr.read())?;
421
422        Ok(())
423    }
424}
425
426impl<I2C, SCLPIN, SDAPIN> Write for I2c<I2C, SCLPIN, SDAPIN>
427where
428    I2C: Deref<Target = I2cRegisterBlock>,
429{
430    type Error = Error;
431
432    fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
433        // Set up current slave address for writing and enable autoending
434        self.i2c.cr2.modify(|_, w| {
435            w.sadd()
436                .bits(u16::from(addr) << 1)
437                .nbytes()
438                .bits(bytes.len() as u8)
439                .rd_wrn()
440                .clear_bit()
441                .autoend()
442                .set_bit()
443        });
444
445        // Send a START condition
446        self.i2c.cr2.modify(|_, w| w.start().set_bit());
447
448        // Send out all individual bytes
449        for c in bytes {
450            self.send_byte(*c)?;
451        }
452
453        // Check and clear flags if they somehow ended up set
454        self.check_and_clear_error_flags(&self.i2c.isr.read())?;
455
456        Ok(())
457    }
458}