1use super::*;
2
3use crate::pac::DWT;
4
5pub struct BlockingI2c<I2C: Instance> {
10 nb: I2c<I2C>,
11 start_retries: u8,
12 timeouts: DwtTimeouts,
13}
14
15#[derive(Clone, Copy, Debug, PartialEq, Eq)]
16pub struct DwtTimeouts {
17 start: u32,
18 addr: u32,
19 data: u32,
20}
21
22impl<I2C: Instance> BlockingI2c<I2C> {
23 #[allow(clippy::too_many_arguments)]
25 pub fn new<const R: u8>(
26 i2c: impl Into<Rmp<I2C, R>>,
27 pins: (impl RInto<I2C::Scl, R>, impl RInto<I2C::Sda, R>),
28 mode: impl Into<Mode>,
29 rcc: &mut Rcc,
30 start_timeout_us: u32,
31 start_retries: u8,
32 addr_timeout_us: u32,
33 data_timeout_us: u32,
34 ) -> Self {
35 I2c::new(i2c, pins, mode, rcc).blocking(
36 start_timeout_us,
37 start_retries,
38 addr_timeout_us,
39 data_timeout_us,
40 &rcc.clocks,
41 )
42 }
43}
44
45impl<I2C: Instance> I2c<I2C> {
46 pub fn blocking(
48 self,
49 start_timeout_us: u32,
50 start_retries: u8,
51 addr_timeout_us: u32,
52 data_timeout_us: u32,
53 clocks: &Clocks,
54 ) -> BlockingI2c<I2C> {
55 let sysclk_mhz = clocks.sysclk().to_MHz();
56 BlockingI2c {
57 nb: self,
58 start_retries,
59 timeouts: DwtTimeouts {
60 start: start_timeout_us * sysclk_mhz,
61 addr: addr_timeout_us * sysclk_mhz,
62 data: data_timeout_us * sysclk_mhz,
63 },
64 }
65 }
66 pub fn blocking_default(self, clocks: Clocks) -> BlockingI2c<I2C> {
67 let sysclk_mhz = clocks.sysclk().to_MHz();
68 BlockingI2c {
69 nb: self,
70 start_retries: 10,
71 timeouts: DwtTimeouts {
72 start: 1000 * sysclk_mhz,
73 addr: 1000 * sysclk_mhz,
74 data: 1000 * sysclk_mhz,
75 },
76 }
77 }
78}
79
80macro_rules! wait_for_flag {
81 ($i2c:expr, $flag:ident, $nack:ident) => {{
82 let sr1 = $i2c.sr1().read();
83
84 if sr1.berr().bit_is_set() {
85 $i2c.sr1().write(|w| w.berr().clear_bit());
86 Err(Error::Bus.into())
87 } else if sr1.arlo().bit_is_set() {
88 $i2c.sr1().write(|w| w.arlo().clear_bit());
89 Err(Error::ArbitrationLoss.into())
90 } else if sr1.af().bit_is_set() {
91 $i2c.sr1().write(|w| w.af().clear_bit());
92 Err(Error::NoAcknowledge(NoAcknowledgeSource::$nack).into())
93 } else if sr1.ovr().bit_is_set() {
94 $i2c.sr1().write(|w| w.ovr().clear_bit());
95 Err(Error::Overrun.into())
96 } else if sr1.$flag().bit_is_set() {
97 Ok(())
98 } else {
99 Err(nb::Error::WouldBlock)
100 }
101 }};
102}
103
104macro_rules! busy_wait {
105 ($nb_expr:expr, $exit_cond:expr) => {{
106 loop {
107 match $nb_expr {
108 Err(nb::Error::Other(e)) => {
109 #[allow(unreachable_code)]
110 break Err(e);
111 }
112 Err(nb::Error::WouldBlock) => {
113 if $exit_cond {
114 break Err(Error::Timeout);
115 }
116 }
117 Ok(x) => break Ok(x),
118 }
119 }
120 }};
121}
122
123macro_rules! busy_wait_cycles {
124 ($nb_expr:expr, $cycles:expr) => {{
125 let started = DWT::cycle_count();
126 let cycles = $cycles;
127 busy_wait!($nb_expr, DWT::cycle_count().wrapping_sub(started) >= cycles)
128 }};
129}
130
131impl<I2C: Instance> BlockingI2c<I2C> {
132 fn wait_after_sent_start(&mut self) -> nb::Result<(), Error> {
136 wait_for_flag!(self.nb.i2c, sb, Unknown)
137 }
138
139 fn wait_for_stop(&mut self) -> nb::Result<(), Error> {
143 if self.nb.i2c.cr1().read().stop().is_no_stop() {
144 Ok(())
145 } else {
146 Err(nb::Error::WouldBlock)
147 }
148 }
149
150 fn send_start_and_wait(&mut self) -> Result<(), Error> {
151 let mut retries_left = self.start_retries;
154 let mut last_ret = Ok(());
155 while retries_left > 0 {
156 self.nb.send_start();
157 last_ret = busy_wait_cycles!(self.wait_after_sent_start(), self.timeouts.start);
158 if last_ret.is_err() {
159 self.nb.reset();
160 } else {
161 break;
162 }
163 retries_left -= 1;
164 }
165 last_ret
166 }
167
168 fn send_addr_and_wait(&mut self, addr: u8, read: bool) -> Result<(), Error> {
169 self.nb.i2c.sr1().read();
170 self.nb.send_addr(addr, read);
171 let ret = busy_wait_cycles!(
172 wait_for_flag!(self.nb.i2c, addr, Address),
173 self.timeouts.addr
174 );
175 if let Err(Error::NoAcknowledge(_)) = ret {
176 self.nb.send_stop();
177 }
178 ret
179 }
180
181 fn write_bytes_and_wait(&mut self, bytes: &[u8]) -> Result<(), Error> {
182 self.nb.i2c.sr1().read();
183 self.nb.i2c.sr2().read();
184
185 self.nb.i2c.dr().write(|w| w.dr().set(bytes[0]));
186
187 for byte in &bytes[1..] {
188 busy_wait_cycles!(wait_for_flag!(self.nb.i2c, tx_e, Data), self.timeouts.data)?;
189 self.nb.i2c.dr().write(|w| w.dr().set(*byte));
190 }
191 busy_wait_cycles!(wait_for_flag!(self.nb.i2c, btf, Data), self.timeouts.data)?;
192
193 Ok(())
194 }
195
196 fn write_without_stop(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
197 self.send_start_and_wait()?;
198 self.send_addr_and_wait(addr, false)?;
199
200 let ret = self.write_bytes_and_wait(bytes);
201 if let Err(Error::NoAcknowledge(_)) = ret {
202 self.nb.send_stop();
203 }
204 ret
205 }
206
207 pub fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
208 self.write_without_stop(addr, bytes)?;
209 self.nb.send_stop();
210 busy_wait_cycles!(self.wait_for_stop(), self.timeouts.data)?;
211
212 Ok(())
213 }
214
215 pub fn reset(&mut self) {
216 self.nb.reset();
217 }
218
219 pub fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> {
220 self.send_start_and_wait()?;
221 self.send_addr_and_wait(addr, true)?;
222
223 match buffer.len() {
224 1 => {
225 self.nb.i2c.cr1().modify(|_, w| w.ack().clear_bit());
226 self.nb.i2c.sr1().read();
227 self.nb.i2c.sr2().read();
228 self.nb.send_stop();
229
230 busy_wait_cycles!(wait_for_flag!(self.nb.i2c, rx_ne, Data), self.timeouts.data)?;
231 buffer[0] = self.nb.i2c.dr().read().dr().bits();
232
233 busy_wait_cycles!(self.wait_for_stop(), self.timeouts.data)?;
234 self.nb.i2c.cr1().modify(|_, w| w.ack().set_bit());
235 }
236 2 => {
237 self.nb
238 .i2c
239 .cr1()
240 .modify(|_, w| w.pos().set_bit().ack().set_bit());
241 self.nb.i2c.sr1().read();
242 self.nb.i2c.sr2().read();
243 self.nb.i2c.cr1().modify(|_, w| w.ack().clear_bit());
244
245 busy_wait_cycles!(wait_for_flag!(self.nb.i2c, btf, Data), self.timeouts.data)?;
246 self.nb.send_stop();
247 buffer[0] = self.nb.i2c.dr().read().dr().bits();
248 buffer[1] = self.nb.i2c.dr().read().dr().bits();
249
250 busy_wait_cycles!(self.wait_for_stop(), self.timeouts.data)?;
251 self.nb
252 .i2c
253 .cr1()
254 .modify(|_, w| w.pos().clear_bit().ack().clear_bit());
255 self.nb.i2c.cr1().modify(|_, w| w.ack().set_bit());
256 }
257 buffer_len => {
258 self.nb.i2c.cr1().modify(|_, w| w.ack().set_bit());
259 self.nb.i2c.sr1().read();
260 self.nb.i2c.sr2().read();
261
262 let (first_bytes, last_two_bytes) = buffer.split_at_mut(buffer_len - 3);
263 for byte in first_bytes {
264 busy_wait_cycles!(
265 wait_for_flag!(self.nb.i2c, rx_ne, Data),
266 self.timeouts.data
267 )?;
268 *byte = self.nb.i2c.dr().read().dr().bits();
269 }
270
271 busy_wait_cycles!(wait_for_flag!(self.nb.i2c, btf, Data), self.timeouts.data)?;
272 self.nb.i2c.cr1().modify(|_, w| w.ack().clear_bit());
273 last_two_bytes[0] = self.nb.i2c.dr().read().dr().bits();
274 self.nb.send_stop();
275 last_two_bytes[1] = self.nb.i2c.dr().read().dr().bits();
276 busy_wait_cycles!(wait_for_flag!(self.nb.i2c, rx_ne, Data), self.timeouts.data)?;
277 last_two_bytes[2] = self.nb.i2c.dr().read().dr().bits();
278
279 busy_wait_cycles!(self.wait_for_stop(), self.timeouts.data)?;
280 self.nb.i2c.cr1().modify(|_, w| w.ack().set_bit());
281 }
282 }
283
284 Ok(())
285 }
286
287 pub fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
288 if !bytes.is_empty() {
289 self.write_without_stop(addr, bytes)?;
290 }
291
292 if !buffer.is_empty() {
293 self.read(addr, buffer)?;
294 } else if !bytes.is_empty() {
295 self.nb.send_stop();
296 busy_wait_cycles!(self.wait_for_stop(), self.timeouts.data)?;
297 }
298
299 Ok(())
300 }
301
302 pub fn transaction_slice(
303 &mut self,
304 _addr: u8,
305 _ops_slice: &mut [embedded_hal::i2c::Operation<'_>],
306 ) -> Result<(), Error> {
307 todo!();
308 }
309
310 pub(crate) fn transaction_slice_hal_02(
311 &mut self,
312 _addr: u8,
313 _ops_slice: &mut [embedded_hal_02::blocking::i2c::Operation<'_>],
314 ) -> Result<(), Error> {
315 todo!();
316 }
317}
318
319pub trait BlockingI2cExt: I2cExt {
320 #[allow(clippy::too_many_arguments)]
321 fn blocking_i2c(
322 self,
323 pins: (impl RInto<Self::Scl, 0>, impl RInto<Self::Sda, 0>),
324 mode: impl Into<Mode>,
325 rcc: &mut Rcc,
326 start_timeout_us: u32,
327 start_retries: u8,
328 addr_timeout_us: u32,
329 data_timeout_us: u32,
330 ) -> BlockingI2c<Self> {
331 Self::i2c(self, pins, mode, rcc).blocking(
332 start_timeout_us,
333 start_retries,
334 addr_timeout_us,
335 data_timeout_us,
336 &rcc.clocks,
337 )
338 }
339}
340
341impl<I2C: I2cExt> BlockingI2cExt for I2C {}
342
343impl<I2C: Instance, const R: u8> Rmp<I2C, R> {
344 #[allow(clippy::too_many_arguments)]
345 pub fn blocking_i2c(
346 self,
347 pins: (impl RInto<I2C::Scl, R>, impl RInto<I2C::Sda, R>),
348 mode: impl Into<Mode>,
349 rcc: &mut Rcc,
350 start_timeout_us: u32,
351 start_retries: u8,
352 addr_timeout_us: u32,
353 data_timeout_us: u32,
354 ) -> BlockingI2c<I2C> {
355 self.i2c(pins, mode, rcc).blocking(
356 start_timeout_us,
357 start_retries,
358 addr_timeout_us,
359 data_timeout_us,
360 &rcc.clocks,
361 )
362 }
363}