stm32f429_hal/
i2c.rs

1//! Inter-Integrated Circuit (I2C) bus
2
3use cast::{u8, u16, u32};
4use stm32f429::{I2C1, I2C2, I2C3};
5
6use gpio::gpioa::PA8;
7use gpio::gpiob::{PB6, PB7, PB8, PB9, PB10, PB11};
8use gpio::gpioc::{PC9};
9use gpio::gpiof::{PF0, PF1};
10use gpio::gpioh::{PH4, PH5, PH7, PH8};
11use gpio::AF4;
12use hal::blocking::i2c::{Read, Write};
13use rcc::{APB1, Clocks};
14use time::{KiloHertz, MegaHertz};
15
16
17/// I2C error
18#[derive(Debug)]
19pub enum Error {
20    /// Bus error
21    Bus,
22    /// Arbitration loss
23    Arbitration,
24    /// No acknowledge returned
25    Acknowledge,
26    /// Overrun/Underrun, slave mode only
27    Overrun,
28    /// Packet Error Checking corruption, SMBUS mode only
29    Pec,
30    /// SMBUS mode only
31    Timeout,
32    /// SMBUS mode only
33    Alert,
34    #[doc(hidden)] _Extensible,
35}
36
37// FIXME these should be "closed" traits
38/// SCL pin -- DO NOT IMPLEMENT THIS TRAIT
39pub unsafe trait SclPin<I2C> {}
40
41/// SDA pin -- DO NOT IMPLEMENT THIS TRAIT
42pub unsafe trait SdaPin<I2C> {}
43
44unsafe impl SclPin<I2C1> for PB6<AF4> {}
45unsafe impl SclPin<I2C1> for PB8<AF4> {}
46
47unsafe impl SclPin<I2C2> for PB10<AF4> {}
48unsafe impl SclPin<I2C2> for PF1<AF4> {}
49unsafe impl SclPin<I2C2> for PH4<AF4> {}
50
51unsafe impl SclPin<I2C3> for PA8<AF4> {}
52unsafe impl SclPin<I2C3> for PH7<AF4> {}
53
54unsafe impl SdaPin<I2C1> for PB7<AF4> {}
55unsafe impl SdaPin<I2C1> for PB9<AF4> {}
56
57unsafe impl SdaPin<I2C2> for PB11<AF4> {}
58unsafe impl SdaPin<I2C2> for PF0<AF4> {}
59unsafe impl SdaPin<I2C2> for PH5<AF4> {}
60
61unsafe impl SdaPin<I2C3> for PC9<AF4> {}
62unsafe impl SdaPin<I2C3> for PH8<AF4> {}
63
64/// I2C peripheral operating in master mode
65#[allow(unused)]
66pub struct I2c<I2C, SCL, SDA> {
67    i2c: I2C,
68    scl: SCL,
69    sda: SDA,
70}
71
72macro_rules! busy_wait {
73    ($i2c:expr, $flag:ident) => {
74        loop {
75            let isr = $i2c.sr1.read();
76
77            if isr.$flag().bit_is_set() {
78                break;
79            } else if isr.berr().bit_is_set() {
80                return Err(Error::Bus);
81            } else if isr.arlo().bit_is_set() {
82                return Err(Error::Arbitration);
83            } else if isr.af().bit_is_set() {
84                return Err(Error::Acknowledge);
85            } else if isr.ovr().bit_is_set() {
86                return Err(Error::Overrun);
87            } else if isr.pecerr().bit_is_set() {
88                return Err(Error::Pec);
89            } else if isr.timeout().bit_is_set() {
90                return Err(Error::Timeout);
91            } else if isr.smbalert().bit_is_set() {
92                return Err(Error::Alert);
93            } else {
94                $i2c.sr2.read();
95                // try again
96            }
97        }
98    }
99}
100
101macro_rules! hal {
102    ($($I2CX:ident: ($i2cX:ident, $i2cXen:ident, $i2cXrst:ident),)+) => {
103        $(
104            impl<SCL, SDA> I2c<$I2CX, SCL, SDA> {
105                /// Configures the I2C peripheral to work in master mode
106                ///
107                /// freq: Maximum 400 KHz
108                pub fn $i2cX<F>(
109                    i2c: $I2CX,
110                    scl: SCL,
111                    sda: SDA,
112                    freq: F,
113                    clocks: Clocks,
114                    apb1: &mut APB1,
115                ) -> Self where
116                    F: Into<KiloHertz>,
117                    SCL: SclPin<$I2CX>,
118                    SDA: SdaPin<$I2CX>,
119                {
120                    // Enable peripheral
121                    apb1.enr().modify(|_, w| w.$i2cXen().set_bit());
122                    // Reset peripheral
123                    apb1.rstr().modify(|_, w| w.$i2cXrst().set_bit());
124                    apb1.rstr().modify(|_, w| w.$i2cXrst().clear_bit());
125
126                    let i2cclk = clocks.pclk1();
127                    let i2cclk_mhz = Into::<MegaHertz>::into(i2cclk).0;
128                    let i2cfreq_mhz = u8(i2cclk_mhz).unwrap()
129                        .max(2)    // Minimum 2 MHz
130                        .min(50);  // Maximum 50 MHz
131                    i2c.cr2.modify(|_, w| unsafe { w.freq().bits(i2cfreq_mhz) });
132                    // T[high] = T[low] = CCR * T[pclk1]
133                    let i2cclk_khz = Into::<KiloHertz>::into(i2cclk).0;
134                    let freq_khz = freq.into().0;
135                    let ccr = u16((i2cclk_khz / freq_khz) >> 1).unwrap();
136                    i2c.ccr.modify(|_, w| unsafe { w.ccr().bits(ccr) });
137                    let trise = u8(((i2cclk_khz / freq_khz) >> 1) + 1).unwrap();
138                    i2c.trise.modify(|_, w| unsafe { w.trise().bits(trise) });
139
140                    // Enable the peripheral
141                    i2c.cr1.write(|w| w.pe().set_bit());
142
143                    I2c { i2c, scl, sda }
144                }
145            }
146
147            impl<SCL, SDA> Read for I2c<$I2CX, SCL, SDA> {
148                type Error = Error;
149
150                fn read(
151                    &mut self,
152                    addr: u8,
153                    buffer: &mut [u8],
154                ) -> Result<(), Error> {
155                    // START
156                    self.i2c.cr1.modify(|_, w| {
157                        w.start().set_bit()
158                            .ack().set_bit()
159                    });
160                    // Wait for master mode selected
161                    while ! self.i2c.sr1.read().sb().bit() ||
162                          ! self.i2c.sr2.read().msl().bit() {}
163                    // Send address
164                    self.i2c.dr.write(|w| unsafe { w.bits((u32(addr) << 1) | 1) });
165                    // Wait for address sent
166                    busy_wait!(self.i2c, addr);
167                    // To clear addr
168                    self.i2c.sr2.read();
169
170                    let len = buffer.len();
171                    for (i, byte) in buffer.iter_mut().enumerate() {
172                        if i == len - 1 {
173                            self.i2c.cr1.modify(|_, w| {
174                                w.ack().clear_bit()
175                            });
176                        } else {
177                        }
178
179                        // Wait until we have received something
180                        busy_wait!(self.i2c, rx_ne);
181
182                        *byte = self.i2c.dr.read().bits() as u8;
183                    }
184                    // STOP
185                    self.i2c.cr1.modify(|_, w| {
186                        w.stop().set_bit()
187                    });
188                    while self.i2c.sr2.read().busy().bit() {
189                        if self.i2c.sr1.read().rx_ne().bit() {
190                            self.i2c.dr.read();
191                        }
192                    }
193
194                    Ok(())
195                }
196            }
197
198            impl<SCL, SDA> Write for I2c<$I2CX, SCL, SDA> {
199                type Error = Error;
200
201                fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
202                    // START
203                    self.i2c.cr1.modify(|_, w| {
204                        w.start().set_bit()
205                            .ack().set_bit()
206                    });
207                    // Wait for master mode selected
208                    while ! self.i2c.sr1.read().sb().bit() ||
209                          ! self.i2c.sr2.read().msl().bit() {}
210                    // Send address
211                    self.i2c.dr.write(|w| unsafe { w.bits((u32(addr) << 1) | 0) });
212                    // Wait for address sent
213                    busy_wait!(self.i2c, addr);
214                    // To clear addr
215                    self.i2c.sr2.read();
216                    
217                    for byte in bytes {
218                        // Wait until we are allowed to send data (START has been ACKed or last byte
219                        // when through)
220                        busy_wait!(self.i2c, tx_e);
221
222                        // put byte on the wire
223                        self.i2c.dr.write(|w| unsafe { w.bits(u32(*byte)) });
224                    }
225
226                    // Wait until the last transmission is finished
227                    busy_wait!(self.i2c, tx_e);
228
229                    // STOP
230                    self.i2c.cr1.modify(|_, w| {
231                        w.stop().set_bit()
232                            .ack().clear_bit()
233                    });
234
235                    while self.i2c.sr2.read().busy().bit() {}
236                    Ok(())
237                }
238            }
239        )+
240    }
241}
242
243hal! {
244    I2C1: (i2c1, i2c1en, i2c1rst),
245    I2C2: (i2c2, i2c2en, i2c2rst),
246    I2C3: (i2c3, i2c3en, i2c3rst),
247}