Skip to main content

esp_hal/i2c/lp_i2c/
rtc_i2c.rs

1//! RTC_I2C implementation of the low-power I2C driver.
2//!
3//! This peripheral transfers through a single data register and always needs a slave sub-register
4//! address.
5
6use crate::{
7    gpio::{
8        LpPin,
9        lp_io::{LpFunction, low_level},
10    },
11    i2c::lp_i2c::{Error, LpI2c, Scl, Sda},
12    peripherals::{GPIO, RTC_IO, SENS},
13    time::Duration,
14};
15
16fn bind_pin(pin: &impl LpPin, function: LpFunction) {
17    let lp = pin.lp_number();
18
19    GPIO::regs()
20        .pin(pin.number() as usize)
21        .modify(|_, w| w.pad_driver().bit(true));
22    RTC_IO::regs()
23        .touch_pad(lp as usize)
24        .modify(|_, w| w.rue().bit(true).rde().bit(false));
25    RTC_IO::regs()
26        .rtc_gpio_enable_w1ts()
27        .write(|w| unsafe { w.rtc_gpio_enable_w1ts().bits(1 << lp) });
28    low_level::set_config(lp, true, true, function);
29}
30
31for_each_lp_function! {
32    (($_func:ident, SAR_I2C_SCL_n, $n:literal), $gpio:ident, $af:ident, $_lp_in:tt $_lp_out:tt) => {
33        impl Scl for crate::peripherals::$gpio<'_> {
34            fn connect_scl(&self) {
35                bind_pin(self, LpFunction::$af);
36                // sar_i2c_io holds both selector fields; update only this one.
37                RTC_IO::regs().sar_i2c_io().modify(|_, w| unsafe {
38                    w.sar_i2c_scl_sel().bits($n)
39                });
40            }
41        }
42    };
43    (($_func:ident, SAR_I2C_SDA_n, $n:literal), $gpio:ident, $af:ident, $_lp_in:tt $_lp_out:tt) => {
44        impl Sda for crate::peripherals::$gpio<'_> {
45            fn connect_sda(&self) {
46                bind_pin(self, LpFunction::$af);
47                // sar_i2c_io holds both selector fields; update only this one.
48                RTC_IO::regs().sar_i2c_io().modify(|_, w| unsafe {
49                    w.sar_i2c_sda_sel().bits($n)
50                });
51            }
52        }
53    };
54}
55
56impl<'d> LpI2c<'d> {
57    pub(super) fn init(&mut self) {
58        // Clear any stale config registers
59        self.i2c.register_block().ctrl().reset();
60        SENS::regs().sar_i2c_ctrl().reset();
61
62        // Reset RTC I2C
63        SENS::regs()
64            .sar_peri_reset_conf()
65            .modify(|_, w| w.sar_rtc_i2c_reset().set_bit());
66        self.i2c
67            .register_block()
68            .ctrl()
69            .modify(|_, w| w.i2c_reset().set_bit());
70        // The state machine does not always come out of reset when the pulse is shorter than this.
71        crate::rom::ets_delay_us(20);
72        self.i2c
73            .register_block()
74            .ctrl()
75            .modify(|_, w| w.i2c_reset().clear_bit());
76        SENS::regs()
77            .sar_peri_reset_conf()
78            .modify(|_, w| w.sar_rtc_i2c_reset().clear_bit());
79
80        // Enable internal open-drain for SDA and SCL
81        self.i2c.register_block().ctrl().modify(|_, w| {
82            w.sda_force_out().clear_bit();
83            w.scl_force_out().clear_bit()
84        });
85
86        // Enable clock gate.
87        SENS::regs()
88            .sar_peri_clk_gate_conf()
89            .modify(|_, w| w.rtc_i2c_clk_en().set_bit());
90
91        // Configure the RTC I2C controller into master mode.
92        self.i2c
93            .register_block()
94            .ctrl()
95            .modify(|_, w| w.ms_mode().set_bit());
96        self.i2c
97            .register_block()
98            .ctrl()
99            .modify(|_, w| w.i2c_ctrl_clk_gate_en().set_bit());
100    }
101
102    pub(super) fn configure(&mut self, config: &Config) -> Result<(), ConfigError> {
103        let ticks = nanos_to_clock(config.timeout.as_micros().saturating_mul(1_000));
104
105        // The register field is 20 bits wide.
106        if ticks > (1 << 20) - 1 {
107            return Err(ConfigError::TimeoutTooLong);
108        }
109
110        self.i2c
111            .register_block()
112            .scl_low()
113            .write(|w| unsafe { w.period().bits(config.timing.scl_low_period) });
114        self.i2c
115            .register_block()
116            .scl_high()
117            .write(|w| unsafe { w.period().bits(config.timing.scl_high_period) });
118        self.i2c
119            .register_block()
120            .sda_duty()
121            .write(|w| unsafe { w.num().bits(config.timing.sda_duty) });
122        self.i2c
123            .register_block()
124            .scl_start_period()
125            .write(|w| unsafe { w.scl_start_period().bits(config.timing.scl_start_period) });
126        self.i2c
127            .register_block()
128            .scl_stop_period()
129            .write(|w| unsafe { w.scl_stop_period().bits(config.timing.scl_stop_period) });
130
131        self.i2c
132            .register_block()
133            .to()
134            .write(|w| unsafe { w.time_out().bits(ticks) });
135
136        Ok(())
137    }
138
139    pub(super) fn write_bytes(
140        &mut self,
141        address: u8,
142        register: u8,
143        data: &[u8],
144    ) -> Result<(), Error> {
145        let sens = unsafe { crate::pac::SENS::steal() };
146
147        if data.len() > u8::MAX as usize - 2 {
148            return Err(Error::TransactionSizeLimitExceeded);
149        }
150
151        self.write_cmd(
152            0,
153            Command::Write {
154                ack_exp: Ack::Ack,
155                ack_check_en: true,
156                // Slave addr + Reg addr + data
157                length: 2 + (data.len() as u8),
158            },
159        );
160        self.write_cmd(1, Command::Stop);
161
162        self.clear_interrupts();
163
164        let ctrl = {
165            let mut result = 0;
166            // Configure slave address.
167            result |= address as u32;
168            // Set slave register.
169            result |= (register as u32) << 11;
170            // Set first data
171            result |= (data[0] as u32) << 19;
172            result |= 1u32 << 27; // Write
173            result
174        };
175        sens.sar_i2c_ctrl()
176            .write(|w| unsafe { w.sar_i2c_ctrl().bits(ctrl) });
177
178        // Start transmission.
179        sens.sar_i2c_ctrl().modify(|_, w| {
180            w.sar_i2c_start_force().set_bit();
181            w.sar_i2c_start().set_bit()
182        });
183
184        for &byte in data.iter().skip(1) {
185            match self.wait_for_tx_interrupt() {
186                Ok(is_tx) => {
187                    if is_tx {
188                        sens.sar_i2c_ctrl().modify(|r, w| {
189                            let mut value = r.sar_i2c_ctrl().bits();
190                            value &= !(0xFF << 19);
191                            value |= (byte as u32) << 19;
192                            value |= 1 << 27;
193                            unsafe { w.sar_i2c_ctrl().bits(value) }
194                        });
195                        self.i2c
196                            .register_block()
197                            .int_clr()
198                            .write(|w| w.tx_data().clear_bit_by_one());
199                    } else {
200                        core::panic!("Peripheral didn't wait for data");
201                    }
202                }
203                Err(err) => {
204                    // Stop transmission.
205                    sens.sar_i2c_ctrl().modify(|_, w| {
206                        w.sar_i2c_start_force().clear_bit();
207                        w.sar_i2c_start().clear_bit()
208                    });
209
210                    return Err(err);
211                }
212            }
213        }
214
215        let result = self.wait_for_complete_interrupt();
216
217        // Stop transmission.
218        sens.sar_i2c_ctrl().write(|w| {
219            w.sar_i2c_start_force().clear_bit();
220            w.sar_i2c_start().clear_bit()
221        });
222
223        result
224    }
225
226    pub(super) fn read_bytes(
227        &mut self,
228        address: u8,
229        register: u8,
230        data: &mut [u8],
231    ) -> Result<(), Error> {
232        let sens = unsafe { crate::pac::SENS::steal() };
233
234        if data.len() > u8::MAX as usize {
235            return Err(Error::TransactionSizeLimitExceeded);
236        }
237
238        // Slave addr + Reg addr
239        self.write_cmd(
240            2,
241            Command::Write {
242                ack_exp: Ack::Ack,
243                ack_check_en: true,
244                length: 2,
245            },
246        );
247        // Restart
248        self.write_cmd(3, Command::Start);
249        self.write_cmd(
250            4,
251            Command::Write {
252                ack_exp: Ack::Ack,
253                ack_check_en: true,
254                // Reg addr
255                length: 1,
256            },
257        );
258        if data.len() > 1 {
259            self.write_cmd(
260                5,
261                Command::Read {
262                    ack_value: Ack::Ack,
263                    length: (data.len() - 1) as _,
264                },
265            );
266            self.write_cmd(
267                6,
268                Command::Read {
269                    ack_value: Ack::Nack,
270                    length: 1,
271                },
272            );
273            self.write_cmd(7, Command::Stop);
274        } else {
275            self.write_cmd(
276                5,
277                Command::Read {
278                    ack_value: Ack::Nack,
279                    length: 1,
280                },
281            );
282            self.write_cmd(6, Command::Stop);
283        }
284
285        self.clear_interrupts();
286
287        // Start transmission.
288        let ctrl = {
289            let mut result = 0;
290            result |= address as u32;
291            result |= (register as u32) << 11;
292            result |= 0u32 << 27; // Read
293            result
294        };
295        sens.sar_i2c_ctrl().write(|w| {
296            unsafe { w.sar_i2c_ctrl().bits(ctrl) };
297            w.sar_i2c_start_force().set_bit();
298            w.sar_i2c_start().set_bit()
299        });
300
301        for byte in data {
302            match self.wait_for_rx_interrupt() {
303                Ok(is_rx) => {
304                    if is_rx {
305                        *byte = self.i2c.register_block().data().read().i2c_rdata().bits();
306                        self.i2c
307                            .register_block()
308                            .int_clr()
309                            .write(|w| w.rx_data().clear_bit_by_one());
310                    } else {
311                        core::panic!("Peripheral didn't wait for data to be read");
312                    }
313                }
314                Err(err) => {
315                    // Stop transmission.
316                    sens.sar_i2c_ctrl().modify(|_, w| {
317                        w.sar_i2c_start_force().clear_bit();
318                        w.sar_i2c_start().clear_bit()
319                    });
320
321                    return Err(err);
322                }
323            }
324        }
325
326        let result = self.wait_for_complete_interrupt();
327
328        // Stop transmission.
329        sens.sar_i2c_ctrl().modify(|_, w| {
330            w.sar_i2c_start_force().clear_bit();
331            w.sar_i2c_start().clear_bit()
332        });
333
334        result
335    }
336
337    fn clear_interrupts(&self) {
338        self.i2c.register_block().int_clr().write(|w| {
339            w.trans_complete().clear_bit_by_one();
340            w.tx_data().clear_bit_by_one();
341            w.rx_data().clear_bit_by_one();
342            w.ack_err().clear_bit_by_one();
343            w.time_out().clear_bit_by_one();
344            w.arbitration_lost().clear_bit_by_one()
345        });
346    }
347
348    fn wait_for_tx_interrupt(&self) -> Result<bool, Error> {
349        loop {
350            let int_raw = self.i2c.register_block().int_raw().read();
351            if int_raw.tx_data().bit_is_set() {
352                break Ok(true);
353            } else if int_raw.trans_complete().bit_is_set() {
354                break Ok(false);
355            } else if int_raw.time_out().bit_is_set() {
356                break Err(Error::TimeOut);
357            } else if int_raw.ack_err().bit_is_set() {
358                break Err(Error::AckCheckFailed);
359            } else if int_raw.arbitration_lost().bit_is_set() {
360                break Err(Error::ArbitrationLost);
361            }
362        }
363    }
364
365    fn wait_for_rx_interrupt(&self) -> Result<bool, Error> {
366        loop {
367            let int_raw = self.i2c.register_block().int_raw().read();
368            if int_raw.rx_data().bit_is_set() {
369                break Ok(true);
370            } else if int_raw.trans_complete().bit_is_set() {
371                break Ok(false);
372            } else if int_raw.time_out().bit_is_set() {
373                break Err(Error::TimeOut);
374            } else if int_raw.ack_err().bit_is_set() {
375                break Err(Error::AckCheckFailed);
376            } else if int_raw.arbitration_lost().bit_is_set() {
377                break Err(Error::ArbitrationLost);
378            }
379        }
380    }
381
382    fn wait_for_complete_interrupt(&self) -> Result<(), Error> {
383        loop {
384            let int_raw = self.i2c.register_block().int_raw().read();
385            if int_raw.trans_complete().bit_is_set() {
386                break Ok(());
387            } else if int_raw.time_out().bit_is_set() {
388                break Err(Error::TimeOut);
389            } else if int_raw.ack_err().bit_is_set() {
390                break Err(Error::AckCheckFailed);
391            } else if int_raw.arbitration_lost().bit_is_set() {
392                break Err(Error::ArbitrationLost);
393            }
394        }
395    }
396
397    fn write_cmd(&self, idx: usize, command: Command) {
398        let cmd = command.into();
399        self.i2c
400            .register_block()
401            .cmd(idx)
402            .write(|w| unsafe { w.command().bits(cmd) });
403    }
404
405    pub(super) fn disable(&mut self) {
406        // Reset and disable RTC I2C clock
407        SENS::regs()
408            .sar_peri_reset_conf()
409            .modify(|_, w| w.sar_rtc_i2c_reset().set_bit());
410
411        SENS::regs()
412            .sar_peri_clk_gate_conf()
413            .modify(|_, w| w.rtc_i2c_clk_en().clear_bit());
414    }
415}
416
417/// I2C-specific configuration errors
418#[derive(Debug, Clone, Copy, PartialEq)]
419#[cfg_attr(feature = "defmt", derive(defmt::Format))]
420#[non_exhaustive]
421pub enum ConfigError {
422    /// The timeout period is longer than the configuration register allows.
423    TimeoutTooLong,
424}
425
426/// I2C driver configuration
427#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, procmacros::BuilderLite)]
428#[cfg_attr(feature = "defmt", derive(defmt::Format))]
429#[non_exhaustive]
430pub struct Config {
431    /// The I2C timings (clock frequency).
432    timing: Timing,
433
434    /// I2C SCL timeout period.
435    timeout: Duration,
436}
437
438/// I2C timings
439#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, procmacros::BuilderLite)]
440#[cfg_attr(feature = "defmt", derive(defmt::Format))]
441pub struct Timing {
442    /// SCL low period
443    scl_low_period: u32,
444    /// SCL high period
445    scl_high_period: u32,
446    /// Period between the SDA switch and the falling edge of SCL
447    sda_duty: u32,
448    /// Waiting time after the START condition in micro seconds
449    scl_start_period: u32,
450    /// Waiting time before the END condition in micro seconds
451    scl_stop_period: u32,
452}
453
454impl Timing {
455    /// I2C timings for standard mode (100 kHz).
456    pub fn standard_mode() -> Self {
457        Self::default()
458            .with_scl_low_period(clock_from_micros(5))
459            .with_scl_high_period(clock_from_micros(5))
460            .with_sda_duty(clock_from_micros(2))
461            .with_scl_start_period(clock_from_micros(3))
462            .with_scl_stop_period(clock_from_micros(6))
463    }
464
465    /// I2C timings for fast mode (400 kHz).
466    pub fn fast_mode() -> Self {
467        Self::default()
468            .with_scl_low_period(clock_from_nanos(1_400))
469            .with_scl_high_period(clock_from_nanos(300))
470            .with_sda_duty(clock_from_nanos(1_000))
471            .with_scl_start_period(clock_from_nanos(2_000))
472            .with_scl_stop_period(clock_from_nanos(1_300))
473    }
474}
475
476fn clock_from_micros(micros: u64) -> u32 {
477    nanos_to_clock(micros * 1_000)
478}
479
480fn clock_from_nanos(nanos: u64) -> u32 {
481    nanos_to_clock(nanos)
482}
483
484fn nanos_to_clock(nanos: u64) -> u32 {
485    ((nanos as u128 * crate::soc::clocks::rc_fast_clk_frequency() as u128) / 1_000_000_000) as u32
486}
487
488/// A generic I2C Command
489enum Command {
490    Start,
491    Stop,
492    Write {
493        /// This bit is to set an expected ACK value for the transmitter.
494        ack_exp: Ack,
495        /// Enables checking the ACK value received against the ack_exp
496        /// value.
497        ack_check_en: bool,
498        /// Length of data (in bytes) to be written. The maximum length is
499        /// 255, while the minimum is 1.
500        length: u8,
501    },
502    Read {
503        /// Indicates whether the receiver will send an ACK after this byte
504        /// has been received.
505        ack_value: Ack,
506        /// Length of data (in bytes) to be read. The maximum length is 255,
507        /// while the minimum is 1.
508        length: u8,
509    },
510}
511
512#[derive(Eq, PartialEq, Copy, Clone)]
513enum Ack {
514    Ack,
515    Nack,
516}
517
518impl From<Command> for u16 {
519    fn from(c: Command) -> u16 {
520        let opcode = match c {
521            Command::Start => 0,
522            Command::Stop => 3,
523            Command::Write { .. } => 1,
524            Command::Read { .. } => 2,
525        };
526
527        let length = match c {
528            Command::Start | Command::Stop => 0,
529            Command::Write { length: l, .. } | Command::Read { length: l, .. } => l,
530        };
531
532        let ack_exp = match c {
533            Command::Start | Command::Stop | Command::Read { .. } => Ack::Nack,
534            Command::Write { ack_exp: exp, .. } => exp,
535        };
536
537        let ack_check_en = match c {
538            Command::Start | Command::Stop | Command::Read { .. } => false,
539            Command::Write {
540                ack_check_en: en, ..
541            } => en,
542        };
543
544        let ack_value = match c {
545            Command::Start | Command::Stop | Command::Write { .. } => Ack::Nack,
546            Command::Read { ack_value: ack, .. } => ack,
547        };
548
549        let mut cmd: u16 = length.into();
550
551        if ack_check_en {
552            cmd |= 1 << 8;
553        } else {
554            cmd &= !(1 << 8);
555        }
556
557        if ack_exp == Ack::Nack {
558            cmd |= 1 << 9;
559        } else {
560            cmd &= !(1 << 9);
561        }
562
563        if ack_value == Ack::Nack {
564            cmd |= 1 << 10;
565        } else {
566            cmd &= !(1 << 10);
567        }
568
569        cmd |= opcode << 11;
570
571        cmd
572    }
573}