stm32f7x7_hal/
i2c.rs

1//! Inter-Integrated Circuit (I2C) bus
2use core::ops::Deref;
3
4use crate::stm32::i2c1;
5
6use core::cmp;
7
8use crate::stm32::{I2C1, I2C2, I2C3, RCC};
9
10use crate::hal::blocking::i2c::{Read, Write, WriteRead};
11
12use crate::gpio::{
13    gpioa::{PA8},
14    gpiob::{PB3, PB4, PB6, PB7, PB8, PB9, PB10, PB11},
15    gpioc::{PC9, PC12},
16    gpiof::{PF0, PF1},
17    gpioh::{PH4, PH5, PH7, PH8}
18};
19use crate::gpio::{Alternate, AF4, AF9};
20
21use crate::rcc::Clocks;
22use crate::time::{Hertz, KiloHertz, U32Ext};
23
24/// I2C abstraction
25pub struct I2c<I2C, PINS> {
26    i2c: I2C,
27    pins: PINS,
28}
29
30pub trait Pins<I2c> {}
31pub trait PinScl<I2c> {}
32pub trait PinSda<I2c> {}
33
34impl<I2c, SCL, SDA> Pins<I2c> for (SCL, SDA)
35where
36    SCL: PinScl<I2c>,
37    SDA: PinSda<I2c>,
38{}
39
40impl PinScl<I2C1> for PB6<Alternate<AF4>> {}
41impl PinSda<I2C1> for PB7<Alternate<AF4>> {}
42impl PinScl<I2C1> for PB8<Alternate<AF4>> {}
43impl PinSda<I2C1> for PB9<Alternate<AF4>> {}
44impl PinSda<I2C2> for PB3<Alternate<AF4>> {}
45impl PinSda<I2C2> for PB3<Alternate<AF9>> {}
46impl PinSda<I2C2> for PB9<Alternate<AF9>> {}
47impl PinScl<I2C2> for PB10<Alternate<AF4>> {}
48impl PinSda<I2C2> for PB11<Alternate<AF4>> {}
49impl PinSda<I2C2> for PC12<Alternate<AF4>> {}
50impl PinScl<I2C2> for PF1<Alternate<AF4>> {}
51impl PinSda<I2C2> for PF0<Alternate<AF4>> {}
52impl PinScl<I2C2> for PH4<Alternate<AF4>> {}
53impl PinSda<I2C2> for PH5<Alternate<AF4>> {}
54impl PinScl<I2C3> for PA8<Alternate<AF4>> {}
55impl PinSda<I2C3> for PB4<Alternate<AF4>> {}
56impl PinSda<I2C3> for PB4<Alternate<AF9>> {}
57impl PinSda<I2C3> for PB8<Alternate<AF9>> {}
58impl PinSda<I2C3> for PC9<Alternate<AF4>> {}
59impl PinScl<I2C3> for PH7<Alternate<AF4>> {}
60impl PinSda<I2C3> for PH8<Alternate<AF4>> {}
61
62#[derive(Debug)]
63pub enum Error {
64    OVERRUN,
65    NACK,
66}
67
68impl<PINS> I2c<I2C1, PINS> {
69    pub fn i2c1(i2c: I2C1, pins: PINS, speed: KiloHertz, clocks: Clocks) -> Self
70    where
71        PINS: Pins<I2C1>,
72    {
73        // NOTE(unsafe) This executes only during initialisation
74        let rcc = unsafe { &(*RCC::ptr()) };
75
76        // Enable clock for I2C1
77        rcc.apb1enr.modify(|_, w| w.i2c1en().set_bit());
78
79        // Reset I2C1
80        rcc.apb1rstr.modify(|_, w| w.i2c1rst().set_bit());
81        rcc.apb1rstr.modify(|_, w| w.i2c1rst().clear_bit());
82
83        let i2c = I2c { i2c, pins };
84        i2c.i2c_init(speed, clocks.pclk1());
85        i2c
86    }
87}
88
89impl<PINS> I2c<I2C2, PINS> {
90    pub fn i2c2(i2c: I2C2, pins: PINS, speed: KiloHertz, clocks: Clocks) -> Self
91    where
92        PINS: Pins<I2C2>,
93    {
94        // NOTE(unsafe) This executes only during initialisation
95        let rcc = unsafe { &(*RCC::ptr()) };
96
97        // Enable clock for I2C2
98        rcc.apb1enr.modify(|_, w| w.i2c2en().set_bit());
99
100        // Reset I2C2
101        rcc.apb1rstr.modify(|_, w| w.i2c2rst().set_bit());
102        rcc.apb1rstr.modify(|_, w| w.i2c2rst().clear_bit());
103
104        let i2c = I2c { i2c, pins };
105        i2c.i2c_init(speed, clocks.pclk1());
106        i2c
107    }
108}
109
110impl<PINS> I2c<I2C3, PINS> {
111    pub fn i2c3(i2c: I2C3, pins: PINS, speed: KiloHertz, clocks: Clocks) -> Self
112    where
113        PINS: Pins<I2C3>,
114    {
115        // NOTE(unsafe) This executes only during initialisation
116        let rcc = unsafe { &(*RCC::ptr()) };
117
118        // Enable clock for I2C3
119        rcc.apb1enr.modify(|_, w| w.i2c3en().set_bit());
120
121        // Reset I2C3
122        rcc.apb1rstr.modify(|_, w| w.i2c3rst().set_bit());
123        rcc.apb1rstr.modify(|_, w| w.i2c3rst().clear_bit());
124
125        let i2c = I2c { i2c, pins };
126        i2c.i2c_init(speed, clocks.pclk1());
127        i2c
128    }
129}
130
131impl<I2C, PINS> I2c<I2C, PINS>
132where
133    I2C: Deref<Target = i2c1::RegisterBlock>,
134{
135    fn i2c_init(&self, speed: KiloHertz, pclk: Hertz) {
136        // TODO: update to STM32F7 family
137        /*let speed: Hertz = speed.into();
138
139        // Make sure the I2C unit is disabled so we can configure it
140        self.i2c.cr1.modify(|_, w| w.pe().clear_bit());
141
142        // Calculate settings for I2C speed modes
143        let clock = pclk.0;
144        let freq = clock / 1_000_000;
145        assert!(freq >= 2 && freq <= 50);
146
147        // Configure bus frequency into I2C peripheral
148        /*self.i2c.cr2.write(|w| unsafe { w.freq().bits(freq as u8) });
149
150        let trise = if speed <= 100.khz().into() {
151            freq + 1
152        } else {
153            (freq * 300) / 1000 + 1
154        };
155
156        // Configure correct rise times
157        self.i2c.trise.write(|w| w.trise().bits(trise as u8));*/
158
159        // I2C clock control calculation
160        if speed <= 100.khz().into() {
161            let ccr = {
162                let ccr = clock / (speed.0 * 2);
163                if ccr < 4 {
164                    4
165                } else {
166                    ccr
167                }
168            };
169
170            // Set clock to standard mode with appropriate parameters for selected speed
171            self.i2c.ccr.write(|w| unsafe {
172                w.f_s()
173                    .clear_bit()
174                    .duty()
175                    .clear_bit()
176                    .ccr()
177                    .bits(ccr as u16)
178            });
179        } else {
180            const DUTYCYCLE: u8 = 0;
181            if DUTYCYCLE == 0 {
182                let ccr = clock / (speed.0 * 3);
183                let ccr = if ccr < 1 { 1 } else { ccr };
184
185                // Set clock to fast mode with appropriate parameters for selected speed (2:1 duty cycle)
186                self.i2c.ccr.write(|w| unsafe {
187                    w.f_s().set_bit().duty().clear_bit().ccr().bits(ccr as u16)
188                });
189            } else {
190                let ccr = clock / (speed.0 * 25);
191                let ccr = if ccr < 1 { 1 } else { ccr };
192
193                // Set clock to fast mode with appropriate parameters for selected speed (16:9 duty cycle)
194                self.i2c.ccr.write(|w| unsafe {
195                    w.f_s().set_bit().duty().set_bit().ccr().bits(ccr as u16)
196                });
197            }
198        }
199
200        // Enable the I2C processing
201        self.i2c.cr1.modify(|_, w| w.pe().set_bit());
202        */
203    }
204
205    pub fn release(self) -> (I2C, PINS) {
206        (self.i2c, self.pins)
207    }
208}
209
210trait I2cCommon {
211    fn send_byte(&self, byte: u8) -> Result<(), Error>;
212
213    fn recv_byte(&self) -> Result<u8, Error>;
214}
215
216impl<I2C, PINS> I2cCommon for I2c<I2C, PINS>
217where
218    I2C: Deref<Target = i2c1::RegisterBlock>,
219{
220    fn send_byte(&self, byte: u8) -> Result<(), Error> {
221        /* Wait until we're ready for sending */
222        while self.i2c.isr.read().txis().bit_is_clear() {}
223
224        /* Push out a byte of data */
225        self.i2c.txdr.write(|w| unsafe { w.bits(u32::from(byte)) });
226
227        /* If we received a NACK, then this is an error */
228        if self.i2c.isr.read().nackf().bit_is_set() {
229            self.i2c
230                .icr
231                .write(|w| w.stopcf().set_bit().nackcf().set_bit());
232            return Err(Error::NACK);
233        }
234
235        Ok(())
236    }
237
238    fn recv_byte(&self) -> Result<u8, Error> {
239        while self.i2c.isr.read().rxne().bit_is_clear() {}
240        let value = self.i2c.rxdr.read().bits() as u8;
241        Ok(value)
242    }
243}
244
245impl<I2C, PINS> WriteRead for I2c<I2C, PINS>
246where
247    I2C: Deref<Target = i2c1::RegisterBlock>,
248{
249    type Error = Error;
250
251    fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> {
252        self.write(addr, bytes)?;
253        self.read(addr, buffer)?;
254
255        Ok(())
256    }
257}
258
259impl<I2C, PINS> Write for I2c<I2C, PINS>
260where
261    I2C: Deref<Target = i2c1::RegisterBlock>,
262{
263    type Error = Error;
264
265    fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
266        /* Set up current address, we're trying a "read" command and not going to set anything
267         * and make sure we end a non-NACKed read (i.e. if we found a device) properly */
268        self.i2c.cr2.modify(|_, w| {
269            w.sadd()
270                .bits(addr.into())
271                .nbytes()
272                .bits(bytes.len() as u8)
273                .rd_wrn()
274                .clear_bit()
275                .autoend()
276                .set_bit()
277        });
278
279        /* Send a START condition */
280        self.i2c.cr2.modify(|_, w| w.start().set_bit());
281
282        for c in bytes {
283            self.send_byte(*c)?;
284        }
285
286        /* Fallthrough is success */
287        self.i2c
288            .icr
289            .write(|w| w.stopcf().set_bit().nackcf().set_bit());
290        Ok(())
291    }
292}
293
294impl<I2C, PINS> Read for I2c<I2C, PINS>
295where
296    I2C: Deref<Target = i2c1::RegisterBlock>,
297{
298    type Error = Error;
299
300    fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
301        if let Some((last, buffer)) = buffer.split_last_mut() {
302            // TODO: update to STM32F7 family
303            /*
304            // Send a START condition and set ACK bit
305            self.i2c.cr1.modify(|_, w| w.start().set_bit().ack().set_bit());
306
307            // Wait until START condition was generated
308            while self.i2c.isr.read().sb().bit_is_clear() {}
309
310            // Also wait until signalled we're master and everything is waiting for us
311            while {
312                let sr2 = self.i2c.sr2.read();
313                sr2.msl().bit_is_clear() && sr2.busy().bit_is_clear()
314            } {}
315
316            // Set up current address, we're trying to talk to
317            self.i2c.txdr.write(|w| unsafe { w.bits((u32::from(addr) << 1) + 1) });
318
319            // Wait until address was sent
320            while self.i2c.isr.read().addr().bit_is_clear() {}
321
322            // Clear condition by reading SR2
323            self.i2c.sr2.read();
324
325            // Receive bytes into buffer
326            for c in buffer {
327                *c = self.recv_byte()?;
328            }
329
330            // Prepare to send NACK then STOP after next byte
331            self.i2c.cr1.modify(|_, w| w.ack().clear_bit().stop().set_bit());
332
333            // Receive last byte
334            *last = self.recv_byte()?;
335            */
336
337            // Fallthrough is success
338            Ok(())
339        } else {
340            Err(Error::OVERRUN)
341        }
342    }
343}