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}