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 let cmd_r = Arc::new(UnsafeCell::new(cmd_r));
44 let mode = Arc::new(AtomicCell::new(Work::Stop));
45 let err_code = Arc::new(AtomicCell::new(None));
46 let i2c1 = unsafe { i2c.steal() };
47 let i2c2 = unsafe { i2c.steal() };
48 let it = I2cBusInterruptHandler {
49 i2c: i2c1,
50 mode: Arc::clone(&mode),
51 cmd_r: Arc::clone(&cmd_r),
52 step: Step::End,
53 sub_step: 0,
54 data_iter: None,
55 buf_iter: None,
56 read_len: 0,
57 slave_addr: Address::Seven(0),
58 notifier: notifier.clone(),
59 last_operation: false,
60 };
63 let it_err = I2cBusErrorInterruptHandler {
64 i2c: i2c2,
65 err_code: Arc::clone(&err_code),
66 notifier,
67 };
68 (
69 Self {
70 i2c,
71 speed: HertzU32::from_raw(0),
72 mode,
73 err_code,
74 cmd_w,
75 cmd_r,
76 waiter,
77 },
78 it,
79 it_err,
80 )
81 }
82
83 fn check_stopped(&mut self) -> bool {
84 if self.i2c.is_stopped() {
85 true
86 } else {
87 let mut t = OS::Timeout::start_ms(1);
88 let mut i = 0;
89 loop {
90 if self.i2c.is_stopped() {
91 return true;
92 } else if t.timeout() {
93 match i {
94 0 => {
95 self.i2c.handle_error(Error::Busy);
96 i += 1;
97 }
98 _ => break,
99 }
100 } else {
101 OS::yield_thread();
102 }
103 }
104 false
105 }
106 }
107}
108
109impl<OS, I2C> I2cBusInterface for I2cBusInterrupt<OS, I2C>
110where
111 OS: OsInterface,
112 I2C: I2cPeriph + Steal,
113{
114 #[inline]
115 fn transaction(
116 &mut self,
117 slave_addr: Address,
118 speed: HertzU32,
119 operations: &mut [Operation<'_, u8>],
120 ) -> Result<(), Error> {
121 if !self.check_stopped() {
123 return Err(Error::Busy);
124 }
125
126 self.i2c.disable_all_interrupt();
127
128 let cmd = unsafe { &mut *self.cmd_r.get() };
130 while cmd.pop().is_ok() {}
131
132 match slave_addr {
134 Address::Seven(addr) => self.cmd_w.push(Command::SlaveAddr(addr))?,
135 Address::Ten(addr) => self.cmd_w.push(Command::SlaveAddr10(addr))?,
136 }
137
138 let period = (speed.into_duration() as NanosDurationU32).ticks() * 12;
139 let mut timeout_ns = 0;
140 let mut i = 0;
141 while i < operations.len() {
142 match &operations[i] {
144 Operation::DelayNs(_)
145 | Operation::Transfer(_, _)
146 | Operation::TransferInPlace(_) => {
147 panic!()
148 }
149 _ => (),
150 }
151
152 let mut write_len = 0;
154 for op in operations[i..].iter() {
155 if let Operation::Write(data) = op {
156 let d: &[u8] = data;
157 if d.len() == 0 {
158 return Err(Error::Buffer);
159 }
160 write_len += d.len();
161 self.cmd_w.push(Command::Write(d.as_ptr(), d.len()))?;
162 i += 1;
163 } else {
164 break;
165 }
166 }
167
168 if write_len > 0 {
169 timeout_ns += (write_len as u32 + 2) * period;
170 self.cmd_w.push(Command::WriteEnd)?;
171 }
172
173 let mut buf_len = 0;
175 for op in operations[i..].iter() {
176 if let Operation::Read(buf) = op {
177 if buf.len() == 0 {
178 return Err(Error::Buffer);
179 }
180 buf_len += buf.len();
181 } else {
182 break;
183 }
184 }
185
186 if buf_len > 0 {
188 timeout_ns += (buf_len as u32 + 2) * period;
189 self.cmd_w.push(Command::Read(buf_len))?;
190 for op in operations[i..].iter_mut() {
191 if let Operation::Read(buf) = op {
192 let b: &mut [u8] = buf;
193 self.cmd_w.push(Command::ReadBuf(b.as_mut_ptr(), b.len()))?;
194 i += 1;
195 } else {
196 break;
197 }
198 }
199 }
200 }
201
202 if self.speed != speed {
204 self.speed = speed;
205 self.i2c.set_speed(speed);
206 }
207
208 self.err_code.store(None, Ordering::Release);
210 self.mode.store(Work::Start, Ordering::Release);
211 self.i2c.it_send_start();
212
213 let rst = self.waiter.wait_with(OS::O, timeout_ns.nanos(), 2, || {
214 let mode = self.mode.load(Ordering::Acquire);
215 let err_code = self.err_code.load(Ordering::Acquire);
216 if Work::Success == mode {
217 return Some(Ok(()));
218 } else if let Some(err) = err_code {
219 return Some(match mode {
220 Work::Addr => Err(err.nack_addr()),
221 Work::Data => Err(err.nack_data()),
222 _ => Err(err),
223 });
224 } else if Work::Stop == mode {
225 return Some(Err(Error::Other));
226 }
227 None
228 });
229
230 self.i2c.disable_all_interrupt();
231
232 self.mode.store(Work::Stop, Ordering::Release);
233 if !self.i2c.is_stopped() {
234 self.i2c.send_stop();
235 }
236
237 let rst = match rst {
238 None => Err(Error::Timeout),
239 Some(rst) => rst,
240 };
241 if let Err(err) = rst {
242 self.i2c.handle_error(err);
243 }
244 rst
245 }
246}
247
248impl<T> From<PushError<T>> for Error {
249 fn from(_value: PushError<T>) -> Self {
250 Self::Buffer
251 }
252}
253
254pub struct I2cBusInterruptHandler<OS: OsInterface, I2C> {
257 i2c: I2C,
258 mode: Arc<AtomicCell<Work>>,
259 cmd_r: Arc<UnsafeCell<Consumer<Command>>>,
260 notifier: OS::Notifier,
261
262 step: Step,
263 sub_step: u8,
264 slave_addr: Address,
265 data_iter: Option<Iter<'static, u8>>,
266 buf_iter: Option<IterMut<'static, u8>>,
267 read_len: usize,
268 last_operation: bool,
269 }
272
273impl<OS, I2C> I2cBusInterruptHandler<OS, I2C>
274where
275 OS: OsInterface,
276 I2C: I2cPeriph,
277{
278 pub fn handler(&mut self) {
279 if Work::Start == self.mode.load(Ordering::Acquire) {
283 if self.prepare_cmd() {
284 match self.cmd().pop() {
285 Ok(Command::Write(p, l)) => {
286 self.to_prepare_write(p, l);
287 }
288 Ok(Command::Read(len)) => {
289 self.to_prepare_read(len);
290 }
291 _ => {
292 self.step = Step::End;
293 }
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.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.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 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().map(|d| *d);
395 data_iter.replace(iter);
396 data
397 }
398 _ => None,
399 },
400 },
401 None => None,
402 }
403 }
404
405 fn 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_ok();
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_ok();
426 b
427 }
428 _ => None,
429 },
430 };
431 byte.map(|b| *b = data);
432 }
433
434 fn step_to(&mut self, step: Step) {
435 self.step = step;
436 match step {
437 Step::PrepareWrite | Step::PrepareRead => {
438 self.mode.store(Work::Addr, Ordering::Release);
439 self.sub_step = 0;
440 }
441 Step::Write | Step::Read => {
442 self.mode.store(Work::Data, Ordering::Release);
443 }
444 Step::End => self.finish(true),
445 }
446 }
447
448 fn prepare_cmd(&mut self) -> bool {
449 self.step = Step::End;
450 self.data_iter = None;
451 self.buf_iter = None;
452
453 match self.cmd().pop() {
454 Ok(Command::SlaveAddr(addr)) => {
455 self.slave_addr = Address::Seven(addr);
456 true
457 }
458 Ok(Command::SlaveAddr10(addr)) => {
459 self.slave_addr = Address::Ten(addr);
460 true
461 }
462 _ => false,
463 }
464 }
465
466 #[inline]
467 fn finish(&mut self, successful: bool) {
468 self.i2c.disable_all_interrupt();
469 self.data_iter = None;
470 self.buf_iter = None;
471
472 let mode = if successful {
473 Work::Success
474 } else {
475 Work::Stop
476 };
477 self.mode.store(mode, Ordering::Release);
478 }
479
480 #[inline]
481 fn cmd(&mut self) -> &mut Consumer<Command> {
482 unsafe { &mut *self.cmd_r.get() }
483 }
484}
485
486#[derive(Clone, Copy, PartialEq, PartialOrd)]
487enum Step {
488 PrepareWrite = 0,
489 Write = 1,
490 PrepareRead = 2,
491 Read = 3,
492 End = 200,
493}
494
495pub struct I2cBusErrorInterruptHandler<OS: OsInterface, I2C> {
498 i2c: I2C,
499 err_code: Arc<AtomicCell<Option<Error>>>,
500 notifier: OS::Notifier,
501}
502
503impl<OS, I2C> I2cBusErrorInterruptHandler<OS, I2C>
504where
505 OS: OsInterface,
506 I2C: I2cPeriph,
507{
508 pub fn handler(&mut self) {
509 if let Some(err) = self.i2c.get_and_clean_error() {
510 self.err_code.store(Some(err), Ordering::Release);
511 self.i2c.disable_all_interrupt();
512 self.notifier.notify();
513 }
514 }
515}
516
517#[cfg(test)]
518mod tests {
519 use fugit::{KilohertzU32, MicrosDurationU32, NanosDurationU32, RateExtU32};
520
521 #[test]
522 fn test_dur() {
523 let speed: KilohertzU32 = 200.kHz();
524 let dur = (speed.into_duration() as MicrosDurationU32).ticks();
525 assert_eq!(dur, 5);
526 let dur = (speed.into_duration() as NanosDurationU32).ticks();
527 assert_eq!(dur, 5000);
528
529 let speed: KilohertzU32 = 20.kHz();
530 let dur = (speed.into_duration() as NanosDurationU32).ticks();
531 assert_eq!(dur, 50000);
532
533 let speed: KilohertzU32 = 400.kHz();
534 let dur = (speed.into_duration() as NanosDurationU32).ticks();
535 assert_eq!(dur, 2500);
536 }
537
538 #[test]
539 fn for_loop() {
540 let data = [1, 2, 3, 4, 5, 6];
541
542 let mut count = 0;
543 let mut i = 0;
544 while i < data.len() {
545 for d in data[i..].iter() {
546 if *d < 4 {
547 i += 1;
548 } else {
549 break;
550 }
551 count += 1;
552 }
553
554 assert_eq!(i, 3);
555 assert_eq!(count, 3);
556
557 for d in data[i..].iter() {
558 if *d >= 4 {
559 i += 1;
560 } else {
561 break;
562 }
563 count += 1;
564 }
565
566 assert_eq!(i, 6);
567 assert_eq!(count, 6);
568 }
569 }
570}