stm32f30x_hal/i2c.rs
1//! Inter-Integrated Circuit (I2C) bus
2
3use cast::u8;
4use stm32f30x::{I2C1, I2C2};
5
6use gpio::gpioa::{PA10, PA9};
7use gpio::gpiob::{PB6, PB7, PB8, PB9};
8use gpio::gpiof::{PF0, PF1, PF6};
9use gpio::AF4;
10use hal::blocking::i2c::{Write, WriteRead};
11use rcc::{APB1, Clocks};
12use time::Hertz;
13
14/// I2C error
15#[derive(Debug)]
16pub enum Error {
17 /// Bus error
18 Bus,
19 /// Arbitration loss
20 Arbitration,
21 // Overrun, // slave mode only
22 // Pec, // SMBUS mode only
23 // Timeout, // SMBUS mode only
24 // Alert, // SMBUS mode only
25 #[doc(hidden)]
26 _Extensible,
27}
28
29// FIXME these should be "closed" traits
30/// SCL pin -- DO NOT IMPLEMENT THIS TRAIT
31pub unsafe trait SclPin<I2C> {}
32
33/// SDA pin -- DO NOT IMPLEMENT THIS TRAIT
34pub unsafe trait SdaPin<I2C> {}
35
36// unsafe impl SclPin<I2C1> for PA15<AF4> {}
37unsafe impl SclPin<I2C1> for PB6<AF4> {}
38unsafe impl SclPin<I2C1> for PB8<AF4> {}
39
40unsafe impl SclPin<I2C2> for PA9<AF4> {}
41unsafe impl SclPin<I2C2> for PF1<AF4> {}
42unsafe impl SclPin<I2C2> for PF6<AF4> {}
43
44// unsafe impl SdaPin<I2C1> for PA14<AF4> {}
45unsafe impl SdaPin<I2C1> for PB7<AF4> {}
46unsafe impl SdaPin<I2C1> for PB9<AF4> {}
47
48unsafe impl SdaPin<I2C2> for PA10<AF4> {}
49unsafe impl SdaPin<I2C2> for PF0<AF4> {}
50
51/// I2C peripheral operating in master mode
52pub struct I2c<I2C, PINS> {
53 i2c: I2C,
54 pins: PINS,
55}
56
57macro_rules! busy_wait {
58 ($i2c:expr, $flag:ident) => {
59 loop {
60 let isr = $i2c.isr.read();
61
62 if isr.berr().bit_is_set() {
63 return Err(Error::Bus);
64 } else if isr.arlo().bit_is_set() {
65 return Err(Error::Arbitration);
66 } else if isr.$flag().bit_is_set() {
67 break;
68 } else {
69 // try again
70 }
71 }
72 };
73}
74
75macro_rules! hal {
76 ($($I2CX:ident: ($i2cX:ident, $i2cXen:ident, $i2cXrst:ident),)+) => {
77 $(
78 impl<SCL, SDA> I2c<$I2CX, (SCL, SDA)> {
79 /// Configures the I2C peripheral to work in master mode
80 pub fn $i2cX<F>(
81 i2c: $I2CX,
82 pins: (SCL, SDA),
83 freq: F,
84 clocks: Clocks,
85 apb1: &mut APB1,
86 ) -> Self where
87 F: Into<Hertz>,
88 SCL: SclPin<$I2CX>,
89 SDA: SdaPin<$I2CX>,
90 {
91 apb1.enr().modify(|_, w| w.$i2cXen().enabled());
92 apb1.rstr().modify(|_, w| w.$i2cXrst().set_bit());
93 apb1.rstr().modify(|_, w| w.$i2cXrst().clear_bit());
94
95 let freq = freq.into().0;
96
97 assert!(freq <= 1_000_000);
98
99 // TODO review compliance with the timing requirements of I2C
100 // t_I2CCLK = 1 / PCLK1
101 // t_PRESC = (PRESC + 1) * t_I2CCLK
102 // t_SCLL = (SCLL + 1) * t_PRESC
103 // t_SCLH = (SCLH + 1) * t_PRESC
104 //
105 // t_SYNC1 + t_SYNC2 > 4 * t_I2CCLK
106 // t_SCL ~= t_SYNC1 + t_SYNC2 + t_SCLL + t_SCLH
107 let i2cclk = clocks.pclk1().0;
108 let ratio = i2cclk / freq - 4;
109 let (presc, scll, sclh, sdadel, scldel) = if freq >= 100_000 {
110 // fast-mode or fast-mode plus
111 // here we pick SCLL + 1 = 2 * (SCLH + 1)
112 let presc = ratio / 387;
113
114 let sclh = ((ratio / (presc + 1)) - 3) / 3;
115 let scll = 2 * (sclh + 1) - 1;
116
117 let (sdadel, scldel) = if freq > 400_000 {
118 // fast-mode plus
119 let sdadel = 0;
120 let scldel = i2cclk / 4_000_000 / (presc + 1) - 1;
121
122 (sdadel, scldel)
123 } else {
124 // fast-mode
125 let sdadel = i2cclk / 8_000_000 / (presc + 1);
126 let scldel = i2cclk / 2_000_000 / (presc + 1) - 1;
127
128 (sdadel, scldel)
129 };
130
131 (presc, scll, sclh, sdadel, scldel)
132 } else {
133 // standard-mode
134 // here we pick SCLL = SCLH
135 let presc = ratio / 514;
136
137 let sclh = ((ratio / (presc + 1)) - 2) / 2;
138 let scll = sclh;
139
140 let sdadel = i2cclk / 2_000_000 / (presc + 1);
141 let scldel = i2cclk / 800_000 / (presc + 1) - 1;
142
143 (presc, scll, sclh, sdadel, scldel)
144 };
145
146 let presc = u8(presc).unwrap();
147 assert!(presc < 16);
148 let scldel = u8(scldel).unwrap();
149 assert!(scldel < 16);
150 let sdadel = u8(sdadel).unwrap();
151 assert!(sdadel < 16);
152 let sclh = u8(sclh).unwrap();
153 let scll = u8(scll).unwrap();
154
155 // Configure for "fast mode" (400 KHz)
156 i2c.timingr.write(|w| unsafe {
157 w.presc()
158 .bits(presc)
159 .scll()
160 .bits(scll)
161 .sclh()
162 .bits(sclh)
163 .sdadel()
164 .bits(sdadel)
165 .scldel()
166 .bits(scldel)
167 });
168
169 // Enable the peripheral
170 i2c.cr1.write(|w| w.pe().set_bit());
171
172 I2c { i2c, pins }
173 }
174
175 /// Releases the I2C peripheral and associated pins
176 pub fn free(self) -> ($I2CX, (SCL, SDA)) {
177 (self.i2c, self.pins)
178 }
179 }
180
181 impl<PINS> Write for I2c<$I2CX, PINS> {
182 type Error = Error;
183
184 fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
185 // TODO support transfers of more than 255 bytes
186 assert!(bytes.len() < 256 && bytes.len() > 0);
187
188 // START and prepare to send `bytes`
189 self.i2c.cr2.write(|w| {
190 w.sadd1()
191 .bits(addr)
192 .rd_wrn()
193 .clear_bit()
194 .nbytes()
195 .bits(bytes.len() as u8)
196 .start()
197 .set_bit()
198 .autoend()
199 .set_bit()
200 });
201
202 for byte in bytes {
203 // Wait until we are allowed to send data (START has been ACKed or last byte
204 // when through)
205 busy_wait!(self.i2c, txis);
206
207 // put byte on the wire
208 self.i2c.txdr.write(|w| w.txdata().bits(*byte));
209 }
210
211 // Wait until the last transmission is finished ???
212 // busy_wait!(self.i2c, busy);
213
214 // automatic STOP
215
216 Ok(())
217 }
218 }
219
220 impl<PINS> WriteRead for I2c<$I2CX, PINS> {
221 type Error = Error;
222
223 fn write_read(
224 &mut self,
225 addr: u8,
226 bytes: &[u8],
227 buffer: &mut [u8],
228 ) -> Result<(), Error> {
229 // TODO support transfers of more than 255 bytes
230 assert!(bytes.len() < 256 && bytes.len() > 0);
231 assert!(buffer.len() < 256 && buffer.len() > 0);
232
233 // TODO do we have to explicitly wait here if the bus is busy (e.g. another
234 // master is communicating)?
235
236 // START and prepare to send `bytes`
237 self.i2c.cr2.write(|w| {
238 w.sadd1()
239 .bits(addr)
240 .rd_wrn()
241 .clear_bit()
242 .nbytes()
243 .bits(bytes.len() as u8)
244 .start()
245 .set_bit()
246 .autoend()
247 .clear_bit()
248 });
249
250 for byte in bytes {
251 // Wait until we are allowed to send data (START has been ACKed or last byte
252 // when through)
253 busy_wait!(self.i2c, txis);
254
255 // put byte on the wire
256 self.i2c.txdr.write(|w| w.txdata().bits(*byte));
257 }
258
259 // Wait until the last transmission is finished
260 busy_wait!(self.i2c, tc);
261
262 // reSTART and prepare to receive bytes into `buffer`
263 self.i2c.cr2.write(|w| {
264 w.sadd1()
265 .bits(addr)
266 .rd_wrn()
267 .set_bit()
268 .nbytes()
269 .bits(buffer.len() as u8)
270 .start()
271 .set_bit()
272 .autoend()
273 .set_bit()
274 });
275
276 for byte in buffer {
277 // Wait until we have received something
278 busy_wait!(self.i2c, rxne);
279
280 *byte = self.i2c.rxdr.read().rxdata().bits();
281 }
282
283 // automatic STOP
284
285 Ok(())
286 }
287 }
288 )+
289 }
290}
291
292hal! {
293 I2C1: (i2c1, i2c1en, i2c1rst),
294 I2C2: (i2c2, i2c2en, i2c2rst),
295}