stm32f1_hal/common/i2c/
i2c_bus_it.rs

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
16// BUS --------------------------------------------------------------
17
18pub 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        // It's safe because it's only used when interrupts are disabled.
44        #[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            // count: [0; 4],
63            // reg: [0; 16],
64        };
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        // the bus is protected, so it must be stopped
124        if !self.check_stopped() {
125            return Err(Error::Busy);
126        }
127
128        self.i2c.disable_all_interrupt();
129
130        // clean old commands
131        let cmd = unsafe { &mut *self.cmd_r.get() };
132        while cmd.pop().is_ok() {}
133
134        // prepare commands
135        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            // Unsupported operations
145            match &operations[i] {
146                Operation::DelayNs(_)
147                | Operation::Transfer(_, _)
148                | Operation::TransferInPlace(_) => {
149                    panic!()
150                }
151                _ => (),
152            }
153
154            // push writing buffer
155            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            // push reading length
176            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            // push reading buffer
189            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        // change speed
205        if self.speed != speed {
206            self.speed = speed;
207            self.i2c.set_speed(speed);
208        }
209
210        // reset error code
211        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
256// Interrupt Handler ------------------------------------------------
257
258pub 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    // count: [u32; 4],
272    // reg: [u32; 16],
273}
274
275impl<OS, I2C> I2cBusInterruptHandler<OS, I2C>
276where
277    OS: OsInterface,
278    I2C: I2cPeriph,
279{
280    pub fn handler(&mut self) {
281        // self.reg[(self.count[0] & 0x0F) as usize] = self.i2c.read_sr();
282        // self.count[0] += 1;
283
284        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                // abnormal
348                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
497// Error Interrupt Handler ------------------------------------------
498
499pub 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}