1use super::{utils::*, *};
2use crate::{
3 Steal,
4 common::{
5 atomic_cell::{AtomicCell, Ordering},
6 bus_device::Operation,
7 fugit::NanosDurationU32,
8 ringbuf::{Consumer, Producer, PushError, RingBuffer},
9 },
10};
11use core::{
12 cell::UnsafeCell,
13 slice::{self, Iter, IterMut},
14};
15
16pub struct I2cBusInterrupt<OS: OsInterface, I2C> {
19 i2c: I2C,
20 mode: Arc<AtomicCell<Work>>,
21 err_code: Arc<AtomicCell<Option<Error>>>,
22 cmd_w: Producer<Command>,
23 cmd_r: Arc<UnsafeCell<Consumer<Command>>>,
24 waiter: OS::NotifyWaiter,
25 speed: HertzU32,
26}
27
28impl<OS, I2C> I2cBusInterrupt<OS, I2C>
29where
30 OS: OsInterface,
31 I2C: I2cPeriph + Steal,
32{
33 pub fn new(
34 i2c: I2C,
35 max_operation: usize,
36 ) -> (
37 Self,
38 I2cBusInterruptHandler<OS, I2C>,
39 I2cBusErrorInterruptHandler<OS, I2C>,
40 ) {
41 let (notifier, waiter) = OS::notify();
42 let (cmd_w, cmd_r) = RingBuffer::<Command>::new(max_operation + 8);
43 #[allow(clippy::arc_with_non_send_sync)]
45 let cmd_r = Arc::new(UnsafeCell::new(cmd_r));
46 let mode = Arc::new(AtomicCell::new(Work::Stop));
47 let err_code = Arc::new(AtomicCell::new(None));
48 let i2c1 = unsafe { i2c.steal() };
49 let i2c2 = unsafe { i2c.steal() };
50 let it = I2cBusInterruptHandler {
51 i2c: i2c1,
52 mode: Arc::clone(&mode),
53 cmd_r: Arc::clone(&cmd_r),
54 step: Step::End,
55 sub_step: 0,
56 data_iter: None,
57 buf_iter: None,
58 read_len: 0,
59 slave_addr: Address::Seven(0),
60 notifier: notifier.clone(),
61 last_operation: false,
62 };
65 let it_err = I2cBusErrorInterruptHandler {
66 i2c: i2c2,
67 err_code: Arc::clone(&err_code),
68 notifier,
69 };
70 (
71 Self {
72 i2c,
73 speed: HertzU32::from_raw(0),
74 mode,
75 err_code,
76 cmd_w,
77 cmd_r,
78 waiter,
79 },
80 it,
81 it_err,
82 )
83 }
84
85 fn check_stopped(&mut self) -> bool {
86 if self.i2c.is_stopped() {
87 true
88 } else {
89 let mut t = OS::timeout().start_ms(1);
90 let mut i = 0;
91 loop {
92 if self.i2c.is_stopped() {
93 return true;
94 } else if t.timeout() {
95 match i {
96 0 => {
97 self.i2c.handle_error(Error::Busy);
98 i += 1;
99 }
100 _ => break,
101 }
102 } else {
103 OS::yield_thread();
104 }
105 }
106 false
107 }
108 }
109}
110
111impl<OS, I2C> I2cBusInterface for I2cBusInterrupt<OS, I2C>
112where
113 OS: OsInterface,
114 I2C: I2cPeriph + Steal,
115{
116 #[inline]
117 fn transaction(
118 &mut self,
119 slave_addr: Address,
120 speed: HertzU32,
121 operations: &mut [Operation<'_, u8>],
122 ) -> Result<(), Error> {
123 if !self.check_stopped() {
125 return Err(Error::Busy);
126 }
127
128 self.i2c.disable_all_interrupt();
129
130 let cmd = unsafe { &mut *self.cmd_r.get() };
132 while cmd.pop().is_ok() {}
133
134 match slave_addr {
136 Address::Seven(addr) => self.cmd_w.push(Command::SlaveAddr(addr))?,
137 Address::Ten(addr) => self.cmd_w.push(Command::SlaveAddr10(addr))?,
138 }
139
140 let period = (speed.into_duration() as NanosDurationU32).ticks() * 12;
141 let mut timeout_ns = 0;
142 let mut i = 0;
143 while i < operations.len() {
144 match &operations[i] {
146 Operation::DelayNs(_)
147 | Operation::Transfer(_, _)
148 | Operation::TransferInPlace(_) => {
149 panic!()
150 }
151 _ => (),
152 }
153
154 let mut write_len = 0;
156 for op in operations[i..].iter() {
157 if let Operation::Write(data) = op {
158 let d: &[u8] = data;
159 if d.is_empty() {
160 return Err(Error::Buffer);
161 }
162 write_len += d.len();
163 self.cmd_w.push(Command::Write(d.as_ptr(), d.len()))?;
164 i += 1;
165 } else {
166 break;
167 }
168 }
169
170 if write_len > 0 {
171 timeout_ns += (write_len as u32 + 2) * period;
172 self.cmd_w.push(Command::WriteEnd)?;
173 }
174
175 let mut buf_len = 0;
177 for op in operations[i..].iter() {
178 if let Operation::Read(buf) = op {
179 if buf.is_empty() {
180 return Err(Error::Buffer);
181 }
182 buf_len += buf.len();
183 } else {
184 break;
185 }
186 }
187
188 if buf_len > 0 {
190 timeout_ns += (buf_len as u32 + 2) * period;
191 self.cmd_w.push(Command::Read(buf_len))?;
192 for op in operations[i..].iter_mut() {
193 if let Operation::Read(buf) = op {
194 let b: &mut [u8] = buf;
195 self.cmd_w.push(Command::ReadBuf(b.as_mut_ptr(), b.len()))?;
196 i += 1;
197 } else {
198 break;
199 }
200 }
201 }
202 }
203
204 if self.speed != speed {
206 self.speed = speed;
207 self.i2c.set_speed(speed);
208 }
209
210 self.err_code.store(None, Ordering::Release);
212 self.mode.store(Work::Start, Ordering::Release);
213 self.i2c.it_send_start();
214
215 let rst = self.waiter.wait_with(OS::O, timeout_ns.nanos(), 2, || {
216 let mode = self.mode.load(Ordering::Acquire);
217 let err_code = self.err_code.load(Ordering::Acquire);
218 if Work::Success == mode {
219 return Some(Ok(()));
220 } else if let Some(err) = err_code {
221 return Some(match mode {
222 Work::Addr => Err(err.nack_addr()),
223 Work::Data => Err(err.nack_data()),
224 _ => Err(err),
225 });
226 } else if Work::Stop == mode {
227 return Some(Err(Error::Other));
228 }
229 None
230 });
231
232 self.i2c.disable_all_interrupt();
233
234 self.mode.store(Work::Stop, Ordering::Release);
235 if !self.i2c.is_stopped() {
236 self.i2c.send_stop();
237 }
238
239 let rst = match rst {
240 None => Err(Error::Timeout),
241 Some(rst) => rst,
242 };
243 if let Err(err) = rst {
244 self.i2c.handle_error(err);
245 }
246 rst
247 }
248}
249
250impl<T> From<PushError<T>> for Error {
251 fn from(_value: PushError<T>) -> Self {
252 Self::Buffer
253 }
254}
255
256pub struct I2cBusInterruptHandler<OS: OsInterface, I2C> {
259 i2c: I2C,
260 mode: Arc<AtomicCell<Work>>,
261 cmd_r: Arc<UnsafeCell<Consumer<Command>>>,
262 notifier: OS::Notifier,
263
264 step: Step,
265 sub_step: u8,
266 slave_addr: Address,
267 data_iter: Option<Iter<'static, u8>>,
268 buf_iter: Option<IterMut<'static, u8>>,
269 read_len: usize,
270 last_operation: bool,
271 }
274
275impl<OS, I2C> I2cBusInterruptHandler<OS, I2C>
276where
277 OS: OsInterface,
278 I2C: I2cPeriph,
279{
280 pub fn handler(&mut self) {
281 if Work::Start == self.mode.load(Ordering::Acquire) && self.prepare_cmd() {
285 match self.cmd().pop() {
286 Ok(Command::Write(p, l)) => {
287 self.setp_to_prepare_write(p, l);
288 }
289 Ok(Command::Read(len)) => {
290 self.step_to_prepare_read(len);
291 }
292 _ => {
293 self.step = Step::End;
294 }
295 }
296 }
297
298 match self.step {
299 Step::PrepareWrite => {
300 if self.prepare_write() {
301 self.mode.store(Work::Data, Ordering::Release);
302 self.step = Step::Write;
303 }
304 }
305 Step::Write => {
306 let cmd = unsafe { &mut *self.cmd_r.get() };
307 let data_iter = &mut self.data_iter;
308 if self
309 .i2c
310 .it_write_with(|| Self::load_data(data_iter, cmd))
311 .is_ok()
312 {
313 match self.cmd().pop() {
314 Ok(Command::Read(len)) => {
315 self.step_to_prepare_read(len);
316 self.i2c.disable_data_interrupt();
317 self.i2c.it_send_start();
318 }
319 _ => {
320 self.i2c.send_stop();
321 self.step_to(Step::End);
322 }
323 }
324 }
325 }
326 Step::PrepareRead => {
327 if self.prepare_read() {
328 self.step_to(Step::Read);
329 }
330 }
331 Step::Read => {
332 if let Some(data) = self.i2c.it_read(self.read_len, self.last_operation) {
333 self.store_data(data);
334 self.read_len -= 1;
335 if self.read_len == 0 {
336 self.i2c.disable_data_interrupt();
337 match self.cmd().pop() {
338 Ok(Command::Write(p, l)) => {
339 self.setp_to_prepare_write(p, l);
340 }
341 _ => self.step_to(Step::End),
342 }
343 }
344 }
345 }
346 Step::End => {
347 self.finish(false);
349 }
350 }
351
352 if self.step >= Step::Read {
353 self.notifier.notify();
354 }
355 }
356
357 #[inline]
358 fn prepare_write(&mut self) -> bool {
359 self.i2c
360 .it_prepare_write(self.slave_addr, &mut self.sub_step)
361 .is_ok()
362 }
363
364 #[inline]
365 fn prepare_read(&mut self) -> bool {
366 self.i2c
367 .it_prepare_read(
368 self.slave_addr,
369 self.read_len,
370 self.last_operation,
371 &mut self.sub_step,
372 )
373 .is_ok()
374 }
375
376 fn setp_to_prepare_write(&mut self, p: *const u8, len: usize) {
377 let data = unsafe { slice::from_raw_parts(p, len) };
378 self.data_iter = Some(data.iter());
379 self.step_to(Step::PrepareWrite);
380 }
381
382 #[inline]
383 fn load_data(
384 data_iter: &mut Option<Iter<'static, u8>>,
385 cmd_r: &mut Consumer<Command>,
386 ) -> Option<u8> {
387 match data_iter.as_mut() {
388 Some(iter) => match iter.next() {
389 Some(data) => Some(*data),
390 None => match cmd_r.pop() {
391 Ok(Command::Write(p, l)) => {
392 let data = unsafe { slice::from_raw_parts(p, l) };
393 let mut iter = data.iter();
394 let data = iter.next().copied();
395 data_iter.replace(iter);
396 data
397 }
398 _ => None,
399 },
400 },
401 None => None,
402 }
403 }
404
405 fn step_to_prepare_read(&mut self, len: usize) {
406 self.read_len = len;
407 if let Ok(Command::ReadBuf(p, l)) = self.cmd().pop() {
408 let data = unsafe { slice::from_raw_parts_mut(p, l) };
409 self.buf_iter.replace(data.iter_mut());
410 }
411 self.last_operation = self.cmd().peek().is_err();
412 self.step_to(Step::PrepareRead);
413 }
414
415 #[inline]
416 fn store_data(&mut self, data: u8) {
417 let byte = match &mut self.buf_iter {
418 Some(iter) => iter.next(),
419 None => match self.cmd().pop() {
420 Ok(Command::ReadBuf(p, l)) => {
421 let data = unsafe { slice::from_raw_parts_mut(p, l) };
422 let mut iter = data.iter_mut();
423 let b = iter.next();
424 self.buf_iter.replace(iter);
425 self.last_operation = self.cmd().peek().is_err();
426 b
427 }
428 _ => None,
429 },
430 };
431 if let Some(b) = byte {
432 *b = data
433 }
434 }
435
436 fn step_to(&mut self, step: Step) {
437 self.step = step;
438 match step {
439 Step::PrepareWrite | Step::PrepareRead => {
440 self.mode.store(Work::Addr, Ordering::Release);
441 self.sub_step = 0;
442 }
443 Step::Write | Step::Read => {
444 self.mode.store(Work::Data, Ordering::Release);
445 }
446 Step::End => self.finish(true),
447 }
448 }
449
450 fn prepare_cmd(&mut self) -> bool {
451 self.step = Step::End;
452 self.data_iter = None;
453 self.buf_iter = None;
454
455 match self.cmd().pop() {
456 Ok(Command::SlaveAddr(addr)) => {
457 self.slave_addr = Address::Seven(addr);
458 true
459 }
460 Ok(Command::SlaveAddr10(addr)) => {
461 self.slave_addr = Address::Ten(addr);
462 true
463 }
464 _ => false,
465 }
466 }
467
468 #[inline]
469 fn finish(&mut self, successful: bool) {
470 self.i2c.disable_all_interrupt();
471 self.data_iter = None;
472 self.buf_iter = None;
473
474 let mode = if successful {
475 Work::Success
476 } else {
477 Work::Stop
478 };
479 self.mode.store(mode, Ordering::Release);
480 }
481
482 #[inline]
483 fn cmd(&mut self) -> &mut Consumer<Command> {
484 unsafe { &mut *self.cmd_r.get() }
485 }
486}
487
488#[derive(Clone, Copy, PartialEq, PartialOrd)]
489enum Step {
490 PrepareWrite = 0,
491 Write = 1,
492 PrepareRead = 2,
493 Read = 3,
494 End = 200,
495}
496
497pub struct I2cBusErrorInterruptHandler<OS: OsInterface, I2C> {
500 i2c: I2C,
501 err_code: Arc<AtomicCell<Option<Error>>>,
502 notifier: OS::Notifier,
503}
504
505impl<OS, I2C> I2cBusErrorInterruptHandler<OS, I2C>
506where
507 OS: OsInterface,
508 I2C: I2cPeriph,
509{
510 pub fn handler(&mut self) {
511 if let Some(err) = self.i2c.get_and_clean_error() {
512 self.err_code.store(Some(err), Ordering::Release);
513 self.i2c.disable_all_interrupt();
514 self.notifier.notify();
515 }
516 }
517}
518
519#[cfg(test)]
520mod tests {
521 use fugit::{KilohertzU32, MicrosDurationU32, NanosDurationU32, RateExtU32};
522
523 #[test]
524 fn test_dur() {
525 let speed: KilohertzU32 = 200.kHz();
526 let dur = (speed.into_duration() as MicrosDurationU32).ticks();
527 assert_eq!(dur, 5);
528 let dur = (speed.into_duration() as NanosDurationU32).ticks();
529 assert_eq!(dur, 5000);
530
531 let speed: KilohertzU32 = 20.kHz();
532 let dur = (speed.into_duration() as NanosDurationU32).ticks();
533 assert_eq!(dur, 50000);
534
535 let speed: KilohertzU32 = 400.kHz();
536 let dur = (speed.into_duration() as NanosDurationU32).ticks();
537 assert_eq!(dur, 2500);
538 }
539
540 #[test]
541 fn for_loop() {
542 let data = [1, 2, 3, 4, 5, 6];
543
544 let mut count = 0;
545 let mut i = 0;
546 while i < data.len() {
547 for d in data[i..].iter() {
548 if *d < 4 {
549 i += 1;
550 } else {
551 break;
552 }
553 count += 1;
554 }
555
556 assert_eq!(i, 3);
557 assert_eq!(count, 3);
558
559 for d in data[i..].iter() {
560 if *d >= 4 {
561 i += 1;
562 } else {
563 break;
564 }
565 count += 1;
566 }
567
568 assert_eq!(i, 6);
569 assert_eq!(count, 6);
570 }
571 }
572}