stm32f072_hal/
i2c.rs

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