Skip to main content

ra_hal/
i2c.rs

1//! I2C Bus Interface (`IIC`).
2//!
3//! # Notes
4//! Is it really worth allocating a buffer and grabbing an interrupt to make up for the lack of built-in FIFO?
5//! # TODO
6//! * Error checking and handling
7//! * Clock config for arbitrary rates
8
9use core::{future::poll_fn, marker::PhantomData, task::Poll};
10
11use cortex_m::asm;
12use embassy_hal_internal::{
13    Peri, PeripheralType, atomic_ring_buffer::RingBuffer, interrupt::InterruptExt as _,
14};
15use embassy_sync::waitqueue::AtomicWaker;
16use embedded_hal_1::i2c::SevenBitAddress;
17
18use crate::{
19    dtc::{Channel as DtcChannel, DtcInterruptHandler, Instance as DtcInstance},
20    event_link::{IcuInterrupt as _, InterruptEvent},
21    gpio::{Flex, Pin, PortFunction, WithOpenDrain},
22    interrupt::{
23        self,
24        typelevel::{Handler as InterruptHandler, Interrupt as InterruptType},
25    },
26    module_stop::ModuleStop,
27    pac::{self, iic::vals::Cks},
28    write_protect::ProtectedModify,
29};
30
31/// Represents one of the possible modes of transfer e.g. spin-wait), interrupt, or DMA.
32#[allow(private_bounds)]
33pub trait TransferMode: SealedTransferMode {}
34trait SealedTransferMode {}
35
36/// Synchronous mode.
37pub struct Blocking;
38
39/// Interrupt driven asynchronous mode.
40pub struct Async<RxInt: InterruptType, TeInt: InterruptType, TxInt: InterruptType> {
41    _rx: PhantomData<RxInt>,
42    _te: PhantomData<TeInt>,
43    _tx: PhantomData<TxInt>,
44}
45
46/// DTC driven asynchronous mode.
47pub struct Dtc<RxInt: InterruptType, TxDtc: DtcInstance> {
48    rx_dtc: PhantomData<RxInt>,
49    tx_dtc: DtcChannel<TxDtc>,
50}
51
52impl TransferMode for Blocking {}
53impl SealedTransferMode for Blocking {}
54
55impl<RxInt: InterruptType, TeInt: InterruptType, TxInt: InterruptType> TransferMode
56    for Async<RxInt, TeInt, TxInt>
57{
58}
59
60impl<RxInt: InterruptType, TeInt: InterruptType, TxInt: InterruptType> SealedTransferMode
61    for Async<RxInt, TeInt, TxInt>
62{
63}
64
65impl<RxInt: InterruptType, TxDtc: DtcInstance> TransferMode for Dtc<RxInt, TxDtc> {}
66impl<RxInt: InterruptType, TxDtc: DtcInstance> SealedTransferMode for Dtc<RxInt, TxDtc> {}
67
68/// I2C driver for the `IIC` peripheral.
69///
70/// # Notes
71///
72/// While there are internal pull-up resistors on the pins attached to the `IIC` peripherals they do *not* function in peripheral mode.
73#[allow(private_bounds)]
74pub struct I2c<'d, I: Instance, M: TransferMode> {
75    _instance: PhantomData<&'d I>,
76    mode: M,
77    // These are set to WithOpenDrain because on the RA4M1 all I2C pins have both capabilities
78    _scl: Flex<'d, WithOpenDrain>,
79    _sda: Flex<'d, WithOpenDrain>,
80}
81
82/// Clock configuration for an [`I2c`] instance.
83#[derive(Copy, Clone, Debug)]
84#[cfg_attr(feature = "defmt", derive(defmt::Format))]
85pub struct ClockConfig {
86    /// Divider for the `IIC` reference clock (`IICϕ`). `PCKLB / divider = IICϕ`. §29.2.3.
87    pub divider: Divider,
88
89    /// `I2C` Low-level period (`t_low`). Units are `IICϕ` cycles? §29.2.15.
90    pub low: u8,
91
92    /// `I2C` High-level period (`t_high`). Units are `IICϕ` cycles? §29.2.16.
93    pub high: u8,
94}
95
96/// `IICϕ` divider
97#[derive(Copy, Clone, Debug)]
98#[allow(missing_docs)]
99#[cfg_attr(feature = "defmt", derive(defmt::Format))]
100pub enum Divider {
101    Div1 = 0x0,
102    Div2 = 0x01,
103    Div4 = 0x02,
104    Div8 = 0x03,
105    Div16 = 0x04,
106    Div32 = 0x05,
107    Div64 = 0x06,
108    Div128 = 0x07,
109}
110
111/// Max supported speed is 400 kHz § 29.1
112#[derive(Debug, Copy, Clone, Default)]
113#[cfg_attr(feature = "defmt", derive(defmt::Format))]
114pub enum I2cSpeed {
115    /// 100 kHz
116    #[default]
117    Normal,
118
119    /// 400 kHz
120    Fast,
121
122    /// FastMode+
123    #[cfg(any(ra4l1, ra6m5))]
124    FastModePlus,
125}
126
127/// Interrupt handler that handles incoming data for an [`I2c`] instance.
128pub struct RxInterruptHandler<I: Instance> {
129    _phantom: PhantomData<I>,
130}
131
132/// Interrupt handler that handles outgoing data (transmission end) for an [`I2c`] instance.
133pub struct TeInterruptHandler<I: Instance> {
134    _phantom: PhantomData<I>,
135}
136
137/// Interrupt handler that handles outgoing data (tx buffer empty) for an [`I2c`] instance.
138pub struct TxInterruptHandler<I: Instance> {
139    _phantom: PhantomData<I>,
140}
141
142/// [`I2c`] driver instance.
143#[allow(private_bounds)]
144pub trait Instance: SealedInstance + ModuleStop + PeripheralType + 'static + Send {}
145
146pub(crate) trait SealedInstance {
147    #[cfg(feature = "defmt")]
148    const PERIPHERAL: &'static str;
149    #[cfg(not(feature = "defmt"))]
150    const PERIPHERAL: () = ();
151
152    const RX_INTERRUPT_EVENT: InterruptEvent;
153    const TE_INTERRUPT_EVENT: InterruptEvent;
154    const TX_INTERRUPT_EVENT: InterruptEvent;
155
156    fn regs() -> pac::iic::Iic;
157
158    /// Waker for receive data events.
159    fn rx_waker() -> &'static AtomicWaker;
160
161    /// Waker for transmit buffer empty events.
162    fn tx_waker() -> &'static AtomicWaker;
163
164    /// Waker for "transmit end" events.
165    fn te_waker() -> &'static AtomicWaker;
166
167    /// # Returns
168    /// Static [`RingBuffer`] for outgoing data.
169    fn tx_buffer() -> &'static RingBuffer;
170}
171
172/// GPIO pin connected to the `SCL` line of an [`I2c`] instance.
173#[allow(private_bounds)]
174pub trait SclPin<I: Instance>: SealedSclPin<I> {}
175
176pub(crate) trait SealedSclPin<I: SealedInstance>: Pin + PeripheralType {
177    const PERIPHERAL_FUNC: PortFunction;
178
179    #[inline(always)]
180    fn set_as_scl(&self) {
181        trace!("P{}{:02}: SclPin::new", self.port(), self.pin());
182        self.set_as_pf(Self::PERIPHERAL_FUNC);
183    }
184}
185
186/// GPIO pin connected to the `SDA` line of an [`I2c`] instance.
187#[allow(private_bounds)]
188pub trait SdaPin<I: Instance>: SealedSdaPin<I> {}
189
190pub(crate) trait SealedSdaPin<I: SealedInstance>: Pin {
191    const PERIPHERAL_FUNC: PortFunction;
192
193    #[inline(always)]
194    fn set_as_sda(&self) {
195        trace!("P{}{:02}: SdaPin::new", self.port(), self.pin());
196        self.set_as_pf(Self::PERIPHERAL_FUNC);
197    }
198}
199
200impl From<Divider> for Cks {
201    fn from(value: Divider) -> Self {
202        Self::from_bits(value as u8)
203    }
204}
205
206macro_rules! instance_impl {
207    ($instance:ident, $rx_int:ident, $te_int:ident, $tx_int:ident) => {
208        paste::paste! {
209            impl crate::i2c::Instance for crate::peripherals::$instance {}
210            impl crate::i2c::SealedInstance for crate::peripherals::$instance {
211                #[cfg(feature = "defmt")]
212                const PERIPHERAL: &'static str = concat!(stringify!($instance), ": ");
213
214                const RX_INTERRUPT_EVENT: crate::event_link::InterruptEvent = crate::event_link::InterruptEvent::$rx_int;
215                const TE_INTERRUPT_EVENT: crate::event_link::InterruptEvent = crate::event_link::InterruptEvent::$te_int;
216                const TX_INTERRUPT_EVENT: crate::event_link::InterruptEvent = crate::event_link::InterruptEvent::$tx_int;
217
218                #[inline(always)]
219                fn regs() -> pac::iic::Iic {
220                    // Safety:
221                    // This is safe because we know the different type
222                    // only adds extra registers that we don't use.
223                    let instance_ptr = crate::pac::$instance.as_ptr();
224                    unsafe { crate::pac::iic::Iic::from_ptr(instance_ptr) }
225                }
226
227                /// Waker for incoming data events.
228                fn rx_waker() -> &'static embassy_sync::waitqueue::AtomicWaker {
229                    static RX_WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new();
230                    &RX_WAKER
231                }
232
233                /// Waker for "transmit end" events.
234                fn te_waker() -> &'static embassy_sync::waitqueue::AtomicWaker {
235                    static TE_WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new();
236                    &TE_WAKER
237                }
238
239                /// Waker for transmit buffer empty events.
240                fn tx_waker() -> &'static embassy_sync::waitqueue::AtomicWaker {
241                    static TX_WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new();
242                    &TX_WAKER
243                }
244
245                fn tx_buffer() -> &'static embassy_hal_internal::atomic_ring_buffer::RingBuffer {
246                    static TX_BUF: embassy_hal_internal::atomic_ring_buffer::RingBuffer = embassy_hal_internal::atomic_ring_buffer::RingBuffer::new();
247                    &TX_BUF
248                }
249            }
250        }
251    };
252}
253pub(crate) use instance_impl;
254
255impl<'d, I: Instance> I2c<'d, I, Blocking> {
256    /// Creates a new blocking `I2c` driver.
257    ///
258    /// # Arguments
259    /// * `iic` An [`IIC`](trait@Instance) peripheral.
260    /// * `scl` A [`Pin`] that can be connected to the [clock line](trait@SclPin).
261    /// * `sda` A [`Pin`] that can be connected to the [data line](trait@SdaPin).
262    /// * `speed` Bitrate.
263    ///
264    /// # Notes
265    /// The `RA4M1` does not provide any pull-up resistors for use with `I2C`.
266    /// The exact speeds you will see depend on the capacitive load and resistors used.
267    #[inline]
268    pub fn new_blocking<C: SclPin<I>, D: SdaPin<I>>(
269        iic: Peri<'d, I>,
270        scl: Peri<'d, C>,
271        sda: Peri<'d, D>,
272        speed: I2cSpeed,
273    ) -> Self {
274        Self::new_inner(iic, scl, sda, speed, Blocking {})
275    }
276
277    fn blocking_read(&self, address: u8, data: &mut [u8]) -> Result<(), I2cError> {
278        let iic = I::regs();
279        let r_addr = (address << 1) | 0x01;
280        let data_len = data.len();
281
282        while iic.iccr2().read().bbsy() {
283            asm::nop();
284        }
285
286        iic.iccr2().modify(|r| r.set_st(true));
287
288        while !iic.icsr2().read().tdre() {
289            asm::nop();
290        }
291
292        iic.icdrt().write_value(r_addr);
293
294        let mut status = iic.icsr2().read();
295        while !status.rdrf() {
296            if status.nackf() {
297                iic.iccr2().modify(|r| r.set_sp(true));
298                return Err(I2cError::Nack);
299            }
300            asm::nop();
301            status = iic.icsr2().read();
302        }
303
304        // Required dummy read
305        let _ = iic.icdrr().read();
306
307        for (i, byte) in data.iter_mut().enumerate() {
308            if i == (data_len - 1) {
309                iic.icmr3().protected_modify(|r| r.set_ackbt(true));
310            }
311            while !iic.icsr2().read().rdrf() {
312                asm::nop();
313            }
314            *byte = iic.icdrr().read();
315        }
316
317        while !iic.icsr2().read().rdrf() {
318            asm::nop();
319        }
320
321        iic.iccr2().modify(|r| r.set_sp(true));
322
323        // Required dummy read
324        let _ = iic.icdrr().read();
325
326        while !iic.icsr2().read().stop() {
327            asm::nop()
328        }
329
330        iic.icmr3().modify(|r| r.set_wait(false));
331        iic.icsr2().modify(|r| r.set_stop(false));
332
333        Ok(())
334    }
335
336    fn blocking_write(&self, address: u8, data: &[u8]) -> Result<(), I2cError> {
337        let iic = I::regs();
338
339        // info!("write! addr={:02x}, len={}", address, data.len());
340
341        let w_addr = (address << 1) | 0x00;
342
343        while iic.iccr2().read().bbsy() {
344            asm::nop();
345        }
346        iic.iccr2().modify(|r| r.set_st(true));
347
348        while !iic.icsr2().read().tdre() {
349            if iic.icsr2().read().nackf() {
350                return Err(I2cError::Nack);
351            }
352            asm::nop();
353        }
354
355        iic.icdrt().write_value(w_addr);
356        while !iic.icsr2().read().tdre() {
357            asm::nop();
358        }
359
360        if iic.icsr2().read().nackf() {
361            iic.iccr2().modify(|r| r.set_sp(true));
362            return Err(I2cError::Nack);
363        }
364
365        for byte in data.iter() {
366            while !iic.icsr2().read().tdre() {
367                asm::nop();
368            }
369            iic.icdrt().write_value(*byte);
370        }
371
372        while !iic.icsr2().read().tend() {
373            asm::nop();
374        }
375
376        iic.iccr2().modify(|r| r.set_sp(true));
377
378        while !iic.icsr2().read().stop() {
379            asm::nop();
380        }
381
382        iic.icsr2().modify(|r| {
383            r.set_stop(false);
384            r.set_nackf(false);
385        });
386
387        Ok(())
388    }
389}
390
391impl<'d, I: Instance, RxInt: InterruptType, TxDtc: DtcInstance> I2c<'d, I, Dtc<RxInt, TxDtc>> {
392    /// Creates a new asynchronous, [`DTC`](module@crate::dtc) driven `I2c` driver.
393    ///
394    /// # Arguments
395    /// * `iic` An [`IIC`](trait@Instance) peripheral.
396    /// * `scl` A [`Pin`] that can be connected to the [clock line](trait@SclPin).
397    /// * `sda` A [`Pin`] that can be connected to the [data line](trait@SdaPin).
398    /// * `speed` Bitrate.
399    /// * `tx_dtc` DTC peripheral for transmission.
400    /// * `irqs` interrupts bound with the [`bind_interrupts!`](crate::bind_interrupts) macro.
401    ///
402    /// # Notes
403    /// This uses DTC for transmission and interrupts for reception.
404    /// Due to limitations with the `IIC` peripheral DMA/DTC reception offers little, if any, benefit.
405    pub fn new_dtc<C: SclPin<I>, D: SdaPin<I>>(
406        iic: Peri<'d, I>,
407        scl: Peri<'d, C>,
408        sda: Peri<'d, D>,
409        speed: I2cSpeed,
410        tx_dtc: Peri<'d, TxDtc>,
411        irqs: impl interrupt::typelevel::Binding<RxInt, RxInterruptHandler<I>>
412        + interrupt::typelevel::Binding<TxDtc::Int, DtcInterruptHandler<TxDtc>>
413        + Clone
414        + 'd,
415    ) -> Self {
416        let tx_dtc = DtcChannel::new(tx_dtc, irqs);
417        let dtc = Dtc {
418            tx_dtc,
419            rx_dtc: PhantomData,
420        };
421
422        Self::new_inner(iic, scl, sda, speed, dtc)
423    }
424
425    async fn dtc_write(&mut self, address: u8, data: &[u8]) -> Result<usize, I2cError> {
426        let iic = I::regs();
427
428        if data.is_empty() {
429            return Ok(0);
430        }
431
432        let w_addr = (address << 1) | 0x00;
433
434        while iic.iccr2().read().bbsy() {}
435
436        iic.icsr2().modify(|r| {
437            r.set_start(false);
438            r.set_stop(false);
439        });
440
441        iic.icier().write(|r| {
442            r.set_stie(true);
443            r.set_spie(true);
444            r.set_tie(true);
445        });
446
447        let addr = [w_addr];
448
449        let tx1 = self
450            .mode
451            .tx_dtc
452            .prepare_write(&addr, iic.icdrt().as_ptr() as *mut _, false);
453        let tx2 = self
454            .mode
455            .tx_dtc
456            .prepare_write(data, iic.icdrt().as_ptr() as *mut _, true);
457        let chain = [tx1, tx2];
458
459        // Safety: The address buffer, data buffer, and the register should outlive the transfer.
460        let tx = unsafe { self.mode.tx_dtc.write_chain(&chain, I::TX_INTERRUPT_EVENT) };
461
462        iic.iccr2().modify(|r| r.set_st(true));
463
464        tx.await.expect("DTC transfer failed");
465
466        // This shouldn't take long and isn't worth the overhead of an interrupt
467        while !iic.icsr2().read().tend() {}
468
469        // Reading `tend` will not clear it, but a stop condition will.
470        iic.iccr2().modify(|r| r.set_sp(true));
471
472        while !iic.icsr2().read().stop() {}
473
474        iic.icsr2().modify(|r| {
475            r.set_stop(false);
476            r.set_nackf(false);
477        });
478
479        Ok(addr.len())
480    }
481
482    async fn dtc_read(&self, address: u8, data: &mut [u8]) -> Result<(), I2cError> {
483        let iic = I::regs();
484        let r_addr = (address << 1) | 0x01;
485        let data_len = data.len();
486
487        iic.icier().write(|r| r.set_rie(true));
488
489        while iic.iccr2().read().bbsy() {
490            asm::nop();
491        }
492
493        iic.iccr2().modify(|r| r.set_st(true));
494
495        while !iic.icsr2().read().tdre() {
496            asm::nop();
497        }
498
499        iic.icdrt().write_value(r_addr);
500
501        let mut status = iic.icsr2().read();
502        while !status.rdrf() {
503            if status.nackf() {
504                iic.iccr2().modify(|r| r.set_sp(true));
505                return Err(I2cError::Nack);
506            }
507            asm::nop();
508            status = iic.icsr2().read();
509        }
510
511        // Required dummy read
512        let _ = iic.icdrr().read();
513
514        for (i, byte) in data.iter_mut().enumerate() {
515            if i == (data_len - 1) {
516                iic.icmr3().protected_modify(|r| r.set_ackbt(true));
517            }
518
519            *byte = poll_fn(|cx| {
520                if iic.icsr2().read().rdrf() {
521                    let byte = iic.icdrr().read();
522                    Poll::Ready(byte)
523                } else {
524                    I::rx_waker().register(cx.waker());
525                    Poll::Pending
526                }
527            })
528            .await;
529        }
530
531        poll_fn(|cx| {
532            if iic.icsr2().read().rdrf() {
533                Poll::Ready(())
534            } else {
535                I::rx_waker().register(cx.waker());
536                Poll::Pending
537            }
538        })
539        .await;
540
541        iic.iccr2().modify(|r| r.set_sp(true));
542
543        // Required dummy read
544        let _ = iic.icdrr().read();
545
546        while !iic.icsr2().read().stop() {
547            asm::nop()
548        }
549
550        iic.icmr3().modify(|r| r.set_wait(false));
551        iic.icsr2().modify(|r| r.set_stop(false));
552
553        iic.icier().write(|r| r.set_rie(false));
554
555        Ok(())
556    }
557}
558
559impl<'d, I: Instance, RxInt: InterruptType, TeInt: InterruptType, TxInt: InterruptType>
560    I2c<'d, I, Async<RxInt, TeInt, TxInt>>
561{
562    /// Creates a new asynchronous, interrupt driven `I2c` driver.
563    ///
564    /// # Arguments
565    /// * `iic` An [`IIC`](trait@Instance) peripheral.
566    /// * `scl` A [`Pin`] that can be connected to the [clock line](trait@SclPin).
567    /// * `sda` A [`Pin`] that can be connected to the [data line](trait@SdaPin).
568    /// * `speed` Bitrate.
569    /// * `tx_buffer` Transmit buffer.
570    /// * `irqs` interrupts bound with the [`bind_interrupts!`](crate::bind_interrupts) macro.
571    pub fn new_async<C: SclPin<I>, D: SdaPin<I>>(
572        iic: Peri<'d, I>,
573        scl: Peri<'d, C>,
574        sda: Peri<'d, D>,
575        speed: I2cSpeed,
576        tx_buffer: &'d mut [u8],
577        irqs: impl interrupt::typelevel::Binding<RxInt, RxInterruptHandler<I>>
578        + interrupt::typelevel::Binding<TeInt, TeInterruptHandler<I>>
579        + interrupt::typelevel::Binding<TxInt, TxInterruptHandler<I>>
580        + 'd,
581    ) -> Self {
582        let _ = irqs;
583        let tx_len = tx_buffer.len();
584
585        // Safety: Caller defines the backing store for the ring buffer and the borrow checker
586        //         should ensure that it remains in place as long as we need.
587        unsafe { I::tx_buffer().init(tx_buffer.as_mut_ptr(), tx_len) };
588
589        // Safety: Interrupt handlers are defined by the irqs argument and thus the interrupts are safe to enable.
590        unsafe {
591            // Enable in NVIC
592            RxInt::IRQ.enable();
593            TeInt::IRQ.enable();
594            TxInt::IRQ.enable();
595
596            // Enable in ICU
597            RxInt::IRQ.icu_enable(I::RX_INTERRUPT_EVENT);
598            TeInt::IRQ.icu_enable(I::TE_INTERRUPT_EVENT);
599            TxInt::IRQ.icu_enable(I::TX_INTERRUPT_EVENT);
600        }
601
602        let iic_regs = I::regs();
603
604        iic_regs.icier().modify(|r| {
605            r.set_tie(true);
606            r.set_teie(false);
607        });
608
609        TeInt::IRQ.icu_unpend();
610        TxInt::IRQ.icu_unpend();
611
612        Self::new_inner(
613            iic,
614            scl,
615            sda,
616            speed,
617            Async {
618                _rx: PhantomData,
619                _te: PhantomData,
620                _tx: PhantomData,
621            },
622        )
623    }
624
625    async fn write(&self, address: u8, data: &[u8]) -> Result<usize, I2cError> {
626        let iic = I::regs();
627
628        if data.is_empty() {
629            return Ok(0);
630        }
631
632        let w_addr = (address << 1) | 0x00;
633
634        while iic.iccr2().read().bbsy() {}
635
636        iic.icsr2().modify(|r| {
637            r.set_start(false);
638            r.set_stop(false);
639        });
640
641        iic.icier().write(|r| {
642            r.set_stie(true);
643            r.set_spie(true);
644            r.set_tie(true);
645        });
646
647        let mut written: usize = 0;
648        let mut writer = unsafe { I::tx_buffer().writer() };
649
650        let out = writer.push_slice();
651        if out.is_empty() {
652            error!("{}TX buffer is full", I::PERIPHERAL);
653        }
654        out[0] = w_addr;
655        writer.push_done(1);
656        let mut started = false;
657
658        let ret = poll_fn(|cx| {
659            if written < data.len() {
660                I::tx_waker().register(cx.waker());
661
662                if I::tx_buffer().is_full() {
663                    debug!("{}TX buffer full in async write", I::PERIPHERAL);
664                    return Poll::Pending;
665                }
666
667                let out = writer.push_slice();
668                let chunk_len = out.len().min(data.len().saturating_sub(written));
669                out[..chunk_len].copy_from_slice(&data[written..(written + chunk_len)]);
670
671                writer.push_done(chunk_len);
672
673                written += chunk_len;
674
675                if !started {
676                    // TODO: § 29.17.2
677                    // if TxInt::IRQ.icu_is_pending() {
678                    //     iic.iccr1().modify(r| r.set_ice(false));
679                    //     iic.icier().modify(r| r.set_tie(false));
680                    //     while iic.icier().read().tie() {
681                    //         asm::nop();
682                    //     }
683                    //     TxInt::IRQ.unpend();
684                    //     TxInt::IRQ.icu_unpend();
685                    // }
686
687                    started = true;
688                    iic.iccr2().modify(|r| r.set_st(true));
689                }
690
691                if written < data.len() {
692                    return Poll::Pending;
693                }
694
695                // If there's nothing else wait on the Transmit End interrupt
696                I::te_waker().register(cx.waker());
697
698                if !iic.icsr2().read().tend() {
699                    return Poll::Pending;
700                }
701            } else {
702                I::te_waker().register(cx.waker());
703
704                if !iic.icsr2().read().tend() {
705                    return Poll::Pending;
706                }
707            }
708
709            Poll::Ready(Ok(written))
710        })
711        .await?;
712
713        // Reading `tend` will not clear it, but a stop condition will.
714        iic.iccr2().modify(|r| r.set_sp(true));
715
716        while !iic.icsr2().read().stop() {}
717
718        iic.icsr2().modify(|r| {
719            r.set_stop(false);
720            r.set_nackf(false);
721        });
722
723        Ok(ret)
724    }
725
726    async fn read_byte(&self) -> u8 {
727        let iic = I::regs();
728
729        poll_fn(|cx| {
730            if iic.icsr2().read().rdrf() {
731                let byte = iic.icdrr().read();
732                Poll::Ready(byte)
733            } else {
734                I::rx_waker().register(cx.waker());
735                Poll::Pending
736            }
737        })
738        .await
739    }
740
741    async fn read(&self, address: u8, data: &mut [u8]) -> Result<(), I2cError> {
742        let iic = I::regs();
743        let r_addr = (address << 1) | 0x01;
744        let data_len = data.len();
745
746        iic.icier().write(|r| r.set_rie(true));
747
748        while iic.iccr2().read().bbsy() {
749            asm::nop();
750        }
751
752        iic.iccr2().modify(|r| r.set_st(true));
753
754        while !iic.icsr2().read().tdre() {
755            asm::nop();
756        }
757
758        iic.icdrt().write_value(r_addr);
759
760        let mut status = iic.icsr2().read();
761        while !status.rdrf() {
762            if status.nackf() {
763                iic.iccr2().modify(|r| r.set_sp(true));
764                return Err(I2cError::Nack);
765            }
766            asm::nop();
767            status = iic.icsr2().read();
768        }
769
770        // Required dummy read
771        let _ = iic.icdrr().read();
772
773        for (i, byte) in data.iter_mut().enumerate() {
774            if i == (data_len - 1) {
775                iic.icmr3().protected_modify(|r| r.set_ackbt(true));
776            }
777
778            *byte = self.read_byte().await;
779        }
780
781        poll_fn(|cx| {
782            if iic.icsr2().read().rdrf() {
783                Poll::Ready(())
784            } else {
785                I::rx_waker().register(cx.waker());
786                Poll::Pending
787            }
788        })
789        .await;
790
791        iic.iccr2().modify(|r| r.set_sp(true));
792
793        // Required dummy read
794        let _ = iic.icdrr().read();
795
796        while !iic.icsr2().read().stop() {
797            asm::nop()
798        }
799
800        iic.icmr3().modify(|r| r.set_wait(false));
801        iic.icsr2().modify(|r| r.set_stop(false));
802
803        iic.icier().write(|r| r.set_rie(false));
804
805        Ok(())
806    }
807}
808
809#[allow(private_bounds)]
810impl<'d, I: Instance, M: TransferMode> I2c<'d, I, M> {
811    #[inline]
812    fn new_inner<C: SclPin<I>, D: SdaPin<I>>(
813        iic: Peri<'d, I>,
814        scl: Peri<'d, C>,
815        sda: Peri<'d, D>,
816        speed: I2cSpeed,
817        mode: M,
818    ) -> Self {
819        let clock_config = crate::clock::clock_status();
820
821        #[rustfmt::skip]
822        let clk_config = match clock_config.peripheral_b.to_MHz(){
823            24 => {
824                [
825                    ClockConfig { divider: Divider::Div4, low: 25, high: 24 },
826                    ClockConfig { divider: Divider::Div1, low: 24, high: 16 },
827                ]
828            },
829            32 => {
830                [
831                    ClockConfig { divider: Divider::Div8, low: 15, high: 13 },
832                    ClockConfig { divider: Divider::Div2, low: 18, high: 9 },
833                ]
834            }
835            40 => {
836                warn!("Uh this isn't right");
837                [
838                    ClockConfig { divider: Divider::Div4, low: 25, high: 24 },
839                    ClockConfig { divider: Divider::Div1, low: 24, high: 16 },
840                ]
841            },
842            _ => unimplemented!()
843        };
844
845        let config = match speed {
846            // Tlow ≥ 4.7 µs, Thigh ≥ 4.0 µs, UM10204 Table 11
847            I2cSpeed::Normal => clk_config[0],
848            // Tlow ≥ 1.3 µs, Thigh ≥ 0.6 µs, UM10204 Table 11
849            I2cSpeed::Fast => clk_config[1],
850            #[cfg(any(ra4l1, ra6m5))]
851            I2cSpeed::FastModePlus => todo!(),
852        };
853
854        Self::new_with_clock_config(iic, scl, sda, config, mode)
855    }
856    /// Creates a new blocking `I2c` driver with specific clock timing.
857    /// # Arguments
858    /// * `iic` An [`IIC`](trait@Instance) peripheral.
859    /// * `scl` A [`Pin`] that can be connected to the [clock line](trait@SclPin).
860    /// * `sda` A [`Pin`] that can be connected to the [data line](trait@SdaPin).
861    /// * `clocks` Clock configuration.
862    ///
863    /// # Notes
864    /// From UM10204, Table 11.
865    /// For normal mode, aim for: Tlow ≥ 4.7 µs, Thigh ≥ 4.0 µs.
866    /// For fast mode, aim for: Tlow ≥ 1.3 µs, Thigh ≥ 0.6 µs.
867    fn new_with_clock_config<C: SclPin<I>, D: SdaPin<I>>(
868        iic: Peri<'d, I>,
869        scl: Peri<'d, C>,
870        sda: Peri<'d, D>,
871        clocks: ClockConfig,
872        mode: M,
873    ) -> Self {
874        let _ = iic;
875        I::start_module();
876
877        let iic = I::regs();
878
879        iic.iccr1().write(|r| r.set_ice(false));
880        iic.iccr1().modify(|r| r.set_iicrst(true));
881        iic.iccr1().modify(|r| r.set_ice(true));
882
883        iic.icmr1().modify(|r| r.set_cks(clocks.divider.into()));
884
885        // Use modify here because chiptool doesn't respect the reset values
886        // Lifted these from the arduino library.
887        iic.icbrl().modify(|r| r.set_brl(clocks.low));
888        iic.icbrh().modify(|r| r.set_brh(clocks.high));
889
890        iic.iccr1().modify(|r| r.set_iicrst(false));
891
892        // p826
893        // Do not assign the SCLn or SDAn pin to the IIC when setting up the pin function control.
894        // Slave address comparison is performed if the pins are assigned to the IIC.
895        scl.set_as_scl();
896        sda.set_as_sda();
897
898        Self {
899            _instance: PhantomData,
900            mode,
901            _scl: Flex::new(scl),
902            _sda: Flex::new(sda),
903        }
904    }
905}
906
907impl<RxInt: InterruptType, TeInt: InterruptType, TxInt: InterruptType> Drop
908    for Async<RxInt, TeInt, TxInt>
909{
910    fn drop(&mut self) {
911        RxInt::IRQ.icu_disable();
912        TeInt::IRQ.icu_disable();
913        TxInt::IRQ.icu_disable();
914    }
915}
916
917impl<RxInt: InterruptType, TxDtc: DtcInstance> Drop for Dtc<RxInt, TxDtc> {
918    fn drop(&mut self) {
919        RxInt::IRQ.icu_disable();
920        TxDtc::Int::IRQ.dtc_disable();
921    }
922}
923
924impl<'d, I: Instance, M: TransferMode> Drop for I2c<'d, I, M> {
925    fn drop(&mut self) {
926        I::stop_module();
927    }
928}
929
930macro_rules! scl_pin {
931    ($instance:ident, $pin:ident, $pfunc:ident) => {
932        impl crate::i2c::SclPin<crate::peripherals::$instance> for crate::peripherals::$pin {}
933        impl crate::i2c::SealedSclPin<crate::peripherals::$instance> for crate::peripherals::$pin {
934            const PERIPHERAL_FUNC: crate::gpio::PortFunction = crate::gpio::PortFunction::$pfunc;
935        }
936    };
937}
938pub(crate) use scl_pin;
939
940macro_rules! sda_pin {
941    ($instance:ident, $pin:ident, $pfunc:ident) => {
942        impl crate::i2c::SdaPin<crate::peripherals::$instance> for crate::peripherals::$pin {}
943        impl crate::i2c::SealedSdaPin<crate::peripherals::$instance> for crate::peripherals::$pin {
944            const PERIPHERAL_FUNC: crate::gpio::PortFunction = crate::gpio::PortFunction::$pfunc;
945        }
946    };
947}
948pub(crate) use sda_pin;
949
950/// I2C error.
951#[derive(Debug, PartialEq, Eq, Copy, Clone)]
952#[cfg_attr(feature = "defmt", derive(defmt::Format))]
953pub enum I2cError {
954    /// Arbitration lost
955    Arbitration,
956
957    /// ACK not received (either to the address or to a data byte)
958    Nack,
959
960    /// Overrun error
961    Overrun,
962}
963
964impl core::fmt::Display for I2cError {
965    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
966        let message = match self {
967            Self::Arbitration => "Arbitration Lost",
968            Self::Nack => "ACK Not Received",
969            Self::Overrun => "Buffer Overrun",
970        };
971
972        write!(f, "{}", message)
973    }
974}
975
976impl core::error::Error for I2cError {}
977
978impl embedded_hal_1::i2c::Error for I2cError {
979    fn kind(&self) -> embedded_hal_1::i2c::ErrorKind {
980        match *self {
981            Self::Arbitration => embedded_hal_1::i2c::ErrorKind::ArbitrationLoss,
982            Self::Nack => embedded_hal_1::i2c::ErrorKind::NoAcknowledge(
983                embedded_hal_1::i2c::NoAcknowledgeSource::Unknown,
984            ),
985            Self::Overrun => embedded_hal_1::i2c::ErrorKind::Overrun,
986        }
987    }
988}
989
990impl<'d, I: Instance, M: TransferMode> embedded_hal_1::i2c::ErrorType for I2c<'d, I, M> {
991    type Error = I2cError;
992}
993
994impl<'d, I: Instance> embedded_hal_1::i2c::I2c<SevenBitAddress> for I2c<'d, I, Blocking> {
995    fn transaction(
996        &mut self,
997        address: u8,
998        operations: &mut [embedded_hal_1::i2c::Operation<'_>],
999    ) -> Result<(), Self::Error> {
1000        for op in operations.iter_mut() {
1001            match op {
1002                embedded_hal_1::i2c::Operation::Read(buffer) => {
1003                    self.blocking_read(address, buffer)?;
1004                }
1005                embedded_hal_1::i2c::Operation::Write(data) => {
1006                    self.blocking_write(address, data)?;
1007                }
1008            }
1009        }
1010
1011        Ok(())
1012    }
1013}
1014
1015impl<'d, I: Instance, RxInt: InterruptType, TeInt: InterruptType, TxInt: InterruptType>
1016    embedded_hal_async::i2c::I2c for I2c<'d, I, Async<RxInt, TeInt, TxInt>>
1017{
1018    async fn transaction(
1019        &mut self,
1020        address: u8,
1021        operations: &mut [embedded_hal_1::i2c::Operation<'_>],
1022    ) -> Result<(), Self::Error> {
1023        for op in operations.iter_mut() {
1024            match op {
1025                embedded_hal_1::i2c::Operation::Read(buffer) => {
1026                    I2c::read(self, address, buffer).await?;
1027                }
1028                embedded_hal_1::i2c::Operation::Write(data) => {
1029                    I2c::write(self, address, data).await?;
1030                }
1031            }
1032        }
1033
1034        Ok(())
1035    }
1036}
1037
1038impl<'d, I: Instance, RxInt: InterruptType, TxDtc: DtcInstance> embedded_hal_async::i2c::I2c
1039    for I2c<'d, I, Dtc<RxInt, TxDtc>>
1040{
1041    async fn transaction(
1042        &mut self,
1043        address: u8,
1044        operations: &mut [embedded_hal_1::i2c::Operation<'_>],
1045    ) -> Result<(), Self::Error> {
1046        for op in operations.iter_mut() {
1047            match op {
1048                embedded_hal_1::i2c::Operation::Read(buffer) => {
1049                    I2c::dtc_read(self, address, buffer).await?;
1050                }
1051                embedded_hal_1::i2c::Operation::Write(data) => {
1052                    I2c::dtc_write(self, address, data).await?;
1053                }
1054            }
1055        }
1056
1057        Ok(())
1058    }
1059}
1060
1061impl<I: Instance, TeInt: InterruptType> InterruptHandler<TeInt> for TeInterruptHandler<I> {
1062    // Table 29.10, note 4 admonishes us to clear `tend` here, but since we set a stop
1063    // condition after the waker is awoken this should be okay.
1064    unsafe fn on_interrupt() {
1065        trace!("{}TeInt", I::PERIPHERAL);
1066        TeInt::IRQ.icu_unpend();
1067        let iic = I::regs();
1068        iic.icier().modify(|r| r.set_teie(false));
1069        I::te_waker().wake();
1070    }
1071}
1072
1073impl<I: Instance, TxInt: InterruptType> InterruptHandler<TxInt> for TxInterruptHandler<I> {
1074    unsafe fn on_interrupt() {
1075        trace!("{}TxInt", I::PERIPHERAL);
1076        TxInt::IRQ.icu_unpend();
1077
1078        let iic = I::regs();
1079        let mut tx_reader = unsafe { I::tx_buffer().reader() };
1080        let out_buf = tx_reader.pop_slice();
1081        let out_len = out_buf.len();
1082
1083        if out_buf.is_empty() {
1084            iic.icier().modify(|r| {
1085                r.set_tie(false);
1086                r.set_teie(true);
1087            });
1088
1089            return;
1090        }
1091
1092        iic.icdrt().write_value(out_buf[0]);
1093
1094        tx_reader.pop_done(1);
1095
1096        if out_len == 1 {
1097            iic.icier().modify(|r| {
1098                r.set_tie(false);
1099                r.set_teie(true);
1100            });
1101            return;
1102        }
1103
1104        I::tx_waker().wake();
1105    }
1106}
1107
1108impl<I: Instance, RxInt: InterruptType> InterruptHandler<RxInt> for RxInterruptHandler<I> {
1109    unsafe fn on_interrupt() {
1110        trace!("{}RxI", I::PERIPHERAL);
1111
1112        RxInt::IRQ.icu_unpend();
1113
1114        I::rx_waker().wake();
1115    }
1116}