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(true) => {
187                    sens.sar_i2c_ctrl().modify(|r, w| {
188                        let mut value = r.sar_i2c_ctrl().bits();
189                        value &= !(0xFF << 19);
190                        value |= (byte as u32) << 19;
191                        value |= 1 << 27;
192                        unsafe { w.sar_i2c_ctrl().bits(value) }
193                    });
194                    self.i2c
195                        .register_block()
196                        .int_clr()
197                        .write(|w| w.tx_data().clear_bit_by_one());
198                }
199                Ok(false) => panic!("Peripheral didn't wait for data"),
200                Err(err) => {
201                    // Stop transmission.
202                    sens.sar_i2c_ctrl().modify(|_, w| {
203                        w.sar_i2c_start_force().clear_bit();
204                        w.sar_i2c_start().clear_bit()
205                    });
206
207                    return Err(err);
208                }
209            }
210        }
211
212        let result = self.wait_for_complete_interrupt();
213
214        // Stop transmission.
215        sens.sar_i2c_ctrl().write(|w| {
216            w.sar_i2c_start_force().clear_bit();
217            w.sar_i2c_start().clear_bit()
218        });
219
220        result
221    }
222
223    pub(super) fn read_bytes(
224        &mut self,
225        address: u8,
226        register: u8,
227        data: &mut [u8],
228    ) -> Result<(), Error> {
229        let sens = unsafe { crate::pac::SENS::steal() };
230
231        if data.len() > u8::MAX as usize {
232            return Err(Error::TransactionSizeLimitExceeded);
233        }
234
235        // Slave addr + Reg addr
236        self.write_cmd(
237            2,
238            Command::Write {
239                ack_exp: Ack::Ack,
240                ack_check_en: true,
241                length: 2,
242            },
243        );
244        // Restart
245        self.write_cmd(3, Command::Start);
246        self.write_cmd(
247            4,
248            Command::Write {
249                ack_exp: Ack::Ack,
250                ack_check_en: true,
251                // Reg addr
252                length: 1,
253            },
254        );
255        if data.len() > 1 {
256            self.write_cmd(
257                5,
258                Command::Read {
259                    ack_value: Ack::Ack,
260                    length: (data.len() - 1) as _,
261                },
262            );
263            self.write_cmd(
264                6,
265                Command::Read {
266                    ack_value: Ack::Nack,
267                    length: 1,
268                },
269            );
270            self.write_cmd(7, Command::Stop);
271        } else {
272            self.write_cmd(
273                5,
274                Command::Read {
275                    ack_value: Ack::Nack,
276                    length: 1,
277                },
278            );
279            self.write_cmd(6, Command::Stop);
280        }
281
282        self.clear_interrupts();
283
284        // Start transmission.
285        let ctrl = {
286            let mut result = 0;
287            result |= address as u32;
288            result |= (register as u32) << 11;
289            result |= 0u32 << 27; // Read
290            result
291        };
292        sens.sar_i2c_ctrl().write(|w| {
293            unsafe { w.sar_i2c_ctrl().bits(ctrl) };
294            w.sar_i2c_start_force().set_bit();
295            w.sar_i2c_start().set_bit()
296        });
297
298        for byte in data {
299            match self.wait_for_rx_interrupt() {
300                Ok(true) => {
301                    *byte = self.i2c.register_block().data().read().i2c_rdata().bits();
302                    self.i2c
303                        .register_block()
304                        .int_clr()
305                        .write(|w| w.rx_data().clear_bit_by_one());
306                }
307                Ok(false) => panic!("Peripheral didn't wait for data to be read"),
308                Err(err) => {
309                    // Stop transmission.
310                    sens.sar_i2c_ctrl().modify(|_, w| {
311                        w.sar_i2c_start_force().clear_bit();
312                        w.sar_i2c_start().clear_bit()
313                    });
314
315                    return Err(err);
316                }
317            }
318        }
319
320        let result = self.wait_for_complete_interrupt();
321
322        // Stop transmission.
323        sens.sar_i2c_ctrl().modify(|_, w| {
324            w.sar_i2c_start_force().clear_bit();
325            w.sar_i2c_start().clear_bit()
326        });
327
328        result
329    }
330
331    fn clear_interrupts(&self) {
332        self.i2c.register_block().int_clr().write(|w| {
333            w.trans_complete().clear_bit_by_one();
334            w.tx_data().clear_bit_by_one();
335            w.rx_data().clear_bit_by_one();
336            w.ack_err().clear_bit_by_one();
337            w.time_out().clear_bit_by_one();
338            w.arbitration_lost().clear_bit_by_one()
339        });
340    }
341
342    fn wait_for_tx_interrupt(&self) -> Result<bool, Error> {
343        loop {
344            let int_raw = self.i2c.register_block().int_raw().read();
345            if int_raw.tx_data().bit_is_set() {
346                break Ok(true);
347            } else if int_raw.trans_complete().bit_is_set() {
348                break Ok(false);
349            } else if int_raw.time_out().bit_is_set() {
350                break Err(Error::TimeOut);
351            } else if int_raw.ack_err().bit_is_set() {
352                break Err(Error::AckCheckFailed);
353            } else if int_raw.arbitration_lost().bit_is_set() {
354                break Err(Error::ArbitrationLost);
355            }
356        }
357    }
358
359    fn wait_for_rx_interrupt(&self) -> Result<bool, Error> {
360        loop {
361            let int_raw = self.i2c.register_block().int_raw().read();
362            if int_raw.rx_data().bit_is_set() {
363                break Ok(true);
364            } else if int_raw.trans_complete().bit_is_set() {
365                break Ok(false);
366            } else if int_raw.time_out().bit_is_set() {
367                break Err(Error::TimeOut);
368            } else if int_raw.ack_err().bit_is_set() {
369                break Err(Error::AckCheckFailed);
370            } else if int_raw.arbitration_lost().bit_is_set() {
371                break Err(Error::ArbitrationLost);
372            }
373        }
374    }
375
376    fn wait_for_complete_interrupt(&self) -> Result<(), Error> {
377        loop {
378            let int_raw = self.i2c.register_block().int_raw().read();
379            if int_raw.trans_complete().bit_is_set() {
380                break Ok(());
381            } else if int_raw.time_out().bit_is_set() {
382                break Err(Error::TimeOut);
383            } else if int_raw.ack_err().bit_is_set() {
384                break Err(Error::AckCheckFailed);
385            } else if int_raw.arbitration_lost().bit_is_set() {
386                break Err(Error::ArbitrationLost);
387            }
388        }
389    }
390
391    fn write_cmd(&self, idx: usize, command: Command) {
392        let cmd = command.into();
393        self.i2c
394            .register_block()
395            .cmd(idx)
396            .write(|w| unsafe { w.command().bits(cmd) });
397    }
398
399    pub(super) fn disable(&mut self) {
400        // Reset and disable RTC I2C clock
401        SENS::regs()
402            .sar_peri_reset_conf()
403            .modify(|_, w| w.sar_rtc_i2c_reset().set_bit());
404
405        SENS::regs()
406            .sar_peri_clk_gate_conf()
407            .modify(|_, w| w.rtc_i2c_clk_en().clear_bit());
408    }
409}
410
411/// I2C-specific configuration errors
412#[derive(Debug, Clone, Copy, PartialEq)]
413#[cfg_attr(feature = "defmt", derive(defmt::Format))]
414#[non_exhaustive]
415pub enum ConfigError {
416    /// The timeout period is longer than the configuration register allows.
417    TimeoutTooLong,
418}
419
420/// I2C driver configuration
421#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, procmacros::BuilderLite)]
422#[cfg_attr(feature = "defmt", derive(defmt::Format))]
423#[non_exhaustive]
424pub struct Config {
425    /// The I2C timings (clock frequency).
426    timing: Timing,
427
428    /// I2C SCL timeout period.
429    timeout: Duration,
430}
431
432/// I2C timings
433#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, procmacros::BuilderLite)]
434#[cfg_attr(feature = "defmt", derive(defmt::Format))]
435pub struct Timing {
436    /// SCL low period
437    scl_low_period: u32,
438    /// SCL high period
439    scl_high_period: u32,
440    /// Period between the SDA switch and the falling edge of SCL
441    sda_duty: u32,
442    /// Waiting time after the START condition in micro seconds
443    scl_start_period: u32,
444    /// Waiting time before the END condition in micro seconds
445    scl_stop_period: u32,
446}
447
448impl Timing {
449    /// I2C timings for standard mode (100 kHz).
450    pub fn standard_mode() -> Self {
451        Self::default()
452            .with_scl_low_period(clock_from_micros(5))
453            .with_scl_high_period(clock_from_micros(5))
454            .with_sda_duty(clock_from_micros(2))
455            .with_scl_start_period(clock_from_micros(3))
456            .with_scl_stop_period(clock_from_micros(6))
457    }
458
459    /// I2C timings for fast mode (400 kHz).
460    pub fn fast_mode() -> Self {
461        Self::default()
462            .with_scl_low_period(clock_from_nanos(1_400))
463            .with_scl_high_period(clock_from_nanos(300))
464            .with_sda_duty(clock_from_nanos(1_000))
465            .with_scl_start_period(clock_from_nanos(2_000))
466            .with_scl_stop_period(clock_from_nanos(1_300))
467    }
468}
469
470fn clock_from_micros(micros: u64) -> u32 {
471    nanos_to_clock(micros * 1_000)
472}
473
474fn clock_from_nanos(nanos: u64) -> u32 {
475    nanos_to_clock(nanos)
476}
477
478fn nanos_to_clock(nanos: u64) -> u32 {
479    ((nanos as u128 * crate::soc::clocks::rc_fast_clk_frequency() as u128) / 1_000_000_000) as u32
480}
481
482/// A generic I2C Command.
483enum Command {
484    Start,
485    Stop,
486    Write {
487        /// This bit is to set an expected ACK value for the transmitter.
488        ack_exp: Ack,
489        /// Enables checking the ACK value received against the ack_exp
490        /// value.
491        ack_check_en: bool,
492        /// Length of data (in bytes) to be written. The maximum length is
493        /// 255, while the minimum is 1.
494        length: u8,
495    },
496    Read {
497        /// Indicates whether the receiver will send an ACK after this byte
498        /// has been received.
499        ack_value: Ack,
500        /// Length of data (in bytes) to be read. The maximum length is 255,
501        /// while the minimum is 1.
502        length: u8,
503    },
504}
505
506#[derive(Eq, PartialEq, Copy, Clone)]
507enum Ack {
508    Ack,
509    Nack,
510}
511
512impl From<Command> for u16 {
513    fn from(c: Command) -> u16 {
514        let opcode = match c {
515            Command::Start => 0,
516            Command::Stop => 3,
517            Command::Write { .. } => 1,
518            Command::Read { .. } => 2,
519        };
520
521        let length = match c {
522            Command::Start | Command::Stop => 0,
523            Command::Write { length: l, .. } | Command::Read { length: l, .. } => l,
524        };
525
526        let ack_exp = match c {
527            Command::Start | Command::Stop | Command::Read { .. } => Ack::Nack,
528            Command::Write { ack_exp: exp, .. } => exp,
529        };
530
531        let ack_check_en = match c {
532            Command::Start | Command::Stop | Command::Read { .. } => false,
533            Command::Write {
534                ack_check_en: en, ..
535            } => en,
536        };
537
538        let ack_value = match c {
539            Command::Start | Command::Stop | Command::Write { .. } => Ack::Nack,
540            Command::Read { ack_value: ack, .. } => ack,
541        };
542
543        let mut cmd: u16 = length.into();
544
545        if ack_check_en {
546            cmd |= 1 << 8;
547        } else {
548            cmd &= !(1 << 8);
549        }
550
551        if ack_exp == Ack::Nack {
552            cmd |= 1 << 9;
553        } else {
554            cmd &= !(1 << 9);
555        }
556
557        if ack_value == Ack::Nack {
558            cmd |= 1 << 10;
559        } else {
560            cmd &= !(1 << 10);
561        }
562
563        cmd |= opcode << 11;
564
565        cmd
566    }
567}