1use 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#[derive(Debug)]
19pub enum Error {
20 Bus,
22 Arbitration,
24 Acknowledge,
26 Overrun,
28 Pec,
30 Timeout,
32 Alert,
34 #[doc(hidden)] _Extensible,
35}
36
37pub unsafe trait SclPin<I2C> {}
40
41pub 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#[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 }
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 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 apb1.enr().modify(|_, w| w.$i2cXen().set_bit());
122 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) .min(50); i2c.cr2.modify(|_, w| unsafe { w.freq().bits(i2cfreq_mhz) });
132 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 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 self.i2c.cr1.modify(|_, w| {
157 w.start().set_bit()
158 .ack().set_bit()
159 });
160 while ! self.i2c.sr1.read().sb().bit() ||
162 ! self.i2c.sr2.read().msl().bit() {}
163 self.i2c.dr.write(|w| unsafe { w.bits((u32(addr) << 1) | 1) });
165 busy_wait!(self.i2c, addr);
167 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 busy_wait!(self.i2c, rx_ne);
181
182 *byte = self.i2c.dr.read().bits() as u8;
183 }
184 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 self.i2c.cr1.modify(|_, w| {
204 w.start().set_bit()
205 .ack().set_bit()
206 });
207 while ! self.i2c.sr1.read().sb().bit() ||
209 ! self.i2c.sr2.read().msl().bit() {}
210 self.i2c.dr.write(|w| unsafe { w.bits((u32(addr) << 1) | 0) });
212 busy_wait!(self.i2c, addr);
214 self.i2c.sr2.read();
216
217 for byte in bytes {
218 busy_wait!(self.i2c, tx_e);
221
222 self.i2c.dr.write(|w| unsafe { w.bits(u32(*byte)) });
224 }
225
226 busy_wait!(self.i2c, tx_e);
228
229 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}