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        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            // count: [0; 4],
61            // reg: [0; 16],
62        };
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        // the bus is protected, so it must be stopped
122        if !self.check_stopped() {
123            return Err(Error::Busy);
124        }
125
126        self.i2c.disable_all_interrupt();
127
128        // clean old commands
129        let cmd = unsafe { &mut *self.cmd_r.get() };
130        while cmd.pop().is_ok() {}
131
132        // prepare commands
133        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            // Unsupported operations
143            match &operations[i] {
144                Operation::DelayNs(_)
145                | Operation::Transfer(_, _)
146                | Operation::TransferInPlace(_) => {
147                    panic!()
148                }
149                _ => (),
150            }
151
152            // push writing buffer
153            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            // push reading length
174            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            // push reading buffer
187            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        // change speed
203        if self.speed != speed {
204            self.speed = speed;
205            self.i2c.set_speed(speed);
206        }
207
208        // reset error code
209        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
254// Interrupt Handler ------------------------------------------------
255
256pub 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    // count: [u32; 4],
270    // reg: [u32; 16],
271}
272
273impl<OS, I2C> I2cBusInterruptHandler<OS, I2C>
274where
275    OS: OsInterface,
276    I2C: I2cPeriph,
277{
278    pub fn handler(&mut self) {
279        // self.reg[(self.count[0] & 0x0F) as usize] = self.i2c.read_sr();
280        // self.count[0] += 1;
281
282        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                // 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 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
495// Error Interrupt Handler ------------------------------------------
496
497pub 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}