Skip to main content

esp_hal/i2c/slave/
mod.rs

1//! # Inter-Integrated Circuit (I2C) - Slave mode
2//!
3//! ## Overview
4//!
5//! This driver implements the I2C Slave mode. In this mode, the MCU responds to
6//! and communicates with one or more master devices. The MCU acts as a slave
7//! device on the I2C bus, identified by its unique I2C address.
8//!
9//! ## Implementation
10//!
11//! This driver supports both Blocking and Async modes, using hardware SCL clock stretching
12//! to handle flow control. The async implementation runs a callback-free waker model, waking
13//! the task waker when stretching or transaction completeness interrupts occur.
14
15use core::{
16    future::Future,
17    marker::PhantomData,
18    pin::Pin,
19    task::{Context, Poll},
20};
21
22use enumset::{EnumSet, EnumSetType};
23
24use crate::{
25    Async,
26    Blocking,
27    DriverMode,
28    asynch::AtomicWaker,
29    gpio::{
30        DriveMode,
31        InputSignal,
32        OutputConfig,
33        OutputSignal,
34        PinGuard,
35        Pull,
36        interconnect::{self, PeripheralInput, PeripheralOutput},
37    },
38    handler,
39    i2c::master::I2cAddress,
40    interrupt::InterruptHandler,
41    pac::i2c0::RegisterBlock,
42    private,
43    ram,
44    rtc_cntl::WakeLock,
45    system::PeripheralGuard,
46};
47
48/// FIFO size of the I2C peripheral.
49pub const FIFO_SIZE: usize = property!("i2c_master.fifo_size");
50
51/// I2C Slave error
52#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
53#[cfg_attr(feature = "defmt", derive(defmt::Format))]
54#[non_exhaustive]
55pub enum Error {
56    /// A timeout occurred during transmission.
57    Timeout,
58    /// The arbitration for the bus was lost.
59    ArbitrationLost,
60}
61
62impl embedded_hal::i2c::Error for Error {
63    fn kind(&self) -> embedded_hal::i2c::ErrorKind {
64        match self {
65            Self::ArbitrationLost => embedded_hal::i2c::ErrorKind::ArbitrationLoss,
66            _ => embedded_hal::i2c::ErrorKind::Other,
67        }
68    }
69}
70
71/// I2C Slave configuration
72#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, procmacros::BuilderLite)]
73#[cfg_attr(feature = "defmt", derive(defmt::Format))]
74#[non_exhaustive]
75pub struct Config {
76    /// The I2C slave address.
77    address: I2cAddress,
78}
79
80impl Config {
81    /// Creates a new I2C slave configuration with the specified address.
82    pub fn new(address: impl Into<I2cAddress>) -> Self {
83        Config {
84            address: address.into(),
85        }
86    }
87}
88
89/// I2C slave configuration errors
90#[derive(Debug, Clone, Copy, PartialEq)]
91#[cfg_attr(feature = "defmt", derive(defmt::Format))]
92#[non_exhaustive]
93pub enum ConfigError {
94    /// Provided address is not valid.
95    AddressInvalid,
96}
97
98impl core::error::Error for ConfigError {}
99
100impl core::fmt::Display for ConfigError {
101    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
102        match self {
103            ConfigError::AddressInvalid => write!(f, "Provided address is invalid"),
104        }
105    }
106}
107
108/// Received command from the master
109#[derive(Debug, Copy, Clone, Eq, PartialEq)]
110#[cfg_attr(feature = "defmt", derive(defmt::Format))]
111pub enum Command {
112    /// The master is requesting data from the slave.
113    Read,
114    /// The master wrote the specified number of bytes to the slave.
115    Write(usize),
116}
117
118/// Possible responses to responding to a read request
119#[derive(Debug, Copy, Clone, Eq, PartialEq)]
120#[cfg_attr(feature = "defmt", derive(defmt::Format))]
121pub enum ReadStatus {
122    /// Transaction Complete; master completed reading all provided bytes.
123    Done,
124    /// Transaction Incomplete; master is trying to read more bytes than were provided.
125    NeedMoreBytes,
126    /// Transaction Complete, but master stopped reading before all bytes were consumed.
127    LeftoverBytes(u16),
128}
129
130/// I2C Slave driver
131#[derive(Debug)]
132#[cfg_attr(feature = "defmt", derive(defmt::Format))]
133pub struct I2cSlave<'d, Dm: DriverMode> {
134    i2c: AnyI2c<'d>,
135    phantom: PhantomData<Dm>,
136    guard: PeripheralGuard,
137    config: DriverConfig,
138}
139
140#[derive(Debug)]
141#[cfg_attr(feature = "defmt", derive(defmt::Format))]
142struct DriverConfig {
143    config: Config,
144    sda_pin: PinGuard,
145    scl_pin: PinGuard,
146}
147
148impl<Dm: DriverMode> embedded_hal::i2c::ErrorType for I2cSlave<'_, Dm> {
149    type Error = Error;
150}
151
152impl<'d> I2cSlave<'d, Blocking> {
153    /// Create a new I2C slave instance.
154    pub fn new(i2c: impl Instance + 'd, config: Config) -> Result<Self, ConfigError> {
155        let guard = PeripheralGuard::new(i2c.info().peripheral);
156
157        let sda_pin = PinGuard::new_unconnected();
158        let scl_pin = PinGuard::new_unconnected();
159
160        let mut slave = I2cSlave {
161            i2c: i2c.degrade(),
162            phantom: PhantomData,
163            guard,
164            config: DriverConfig {
165                config,
166                sda_pin,
167                scl_pin,
168            },
169        };
170
171        slave.apply_config(&config)?;
172        Ok(slave)
173    }
174
175    /// Reconfigures the driver to operate in [`Async`] mode.
176    pub fn into_async(self) -> I2cSlave<'d, Async> {
177        self.i2c
178            .set_interrupt_handler(self.driver().info.async_handler);
179
180        I2cSlave {
181            i2c: self.i2c,
182            phantom: PhantomData,
183            guard: self.guard,
184            config: self.config,
185        }
186    }
187}
188
189impl<'d> I2cSlave<'d, Async> {
190    /// Reconfigures the driver to operate in [`Blocking`] mode.
191    pub fn into_blocking(self) -> I2cSlave<'d, Blocking> {
192        self.i2c.disable_peri_interrupt();
193
194        I2cSlave {
195            i2c: self.i2c,
196            phantom: PhantomData,
197            guard: self.guard,
198            config: self.config,
199        }
200    }
201}
202
203impl<'d, Dm: DriverMode> I2cSlave<'d, Dm> {
204    fn driver(&self) -> Driver<'_> {
205        Driver {
206            info: self.i2c.info(),
207            state: self.i2c.state(),
208            config: &self.config,
209        }
210    }
211
212    /// Connect a pin to the I2C SDA signal.
213    pub fn with_sda(mut self, sda: impl PeripheralInput<'d> + PeripheralOutput<'d>) -> Self {
214        let info = self.driver().info;
215        let input = info.sda_input;
216        let output = info.sda_output;
217        Driver::connect_pin(sda.into(), input, output, &mut self.config.sda_pin);
218        self
219    }
220
221    /// Connect a pin to the I2C SCL signal.
222    pub fn with_scl(mut self, scl: impl PeripheralInput<'d> + PeripheralOutput<'d>) -> Self {
223        let info = self.driver().info;
224        let input = info.scl_input;
225        let output = info.scl_output;
226        Driver::connect_pin(scl.into(), input, output, &mut self.config.scl_pin);
227        self
228    }
229
230    /// Applies a new configuration.
231    pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
232        self.config.config = *config;
233        self.driver().setup(config)?;
234        Ok(())
235    }
236}
237
238impl<'d, Dm: DriverMode> I2cSlave<'d, Dm> {
239    /// Listens for a request from the master.
240    ///
241    /// If the master writes to the slave, this method reads data into the provided
242    /// `buffer` and returns `Command::Write(len)`.
243    /// If the master is requesting a read, it returns `Command::Read` with the SCL line
244    /// stretched (held low).
245    pub fn listen(&mut self, buffer: &mut [u8]) -> Result<Command, Error> {
246        let regs = self.driver().info.regs();
247
248        self.driver().reset_fifo();
249
250        regs.scl_stretch_conf().modify(|_, w| unsafe {
251            w.stretch_protect_num().bits(0x3ff);
252            w.slave_scl_stretch_en().set_bit()
253        });
254
255        regs.int_clr().write(|w| unsafe { w.bits(0x3fff) });
256        regs.scl_stretch_conf()
257            .modify(|_, w| w.slave_scl_stretch_clr().set_bit());
258        self.driver().update_registers();
259
260        let mut bytes_read = 0;
261        loop {
262            self.driver().check_errors()?;
263            if let Some(res) = self.driver().listen_step(buffer, &mut bytes_read) {
264                return res;
265            }
266        }
267    }
268
269    /// Responds to a master read request.
270    ///
271    /// Writes the contents of `buffer` to the TX FIFO, clears the clock stretch,
272    /// and waits for the transaction to complete.
273    pub fn respond_to_read(&mut self, buffer: &[u8]) -> Result<ReadStatus, Error> {
274        let regs = self.driver().info.regs();
275        let mut bytes_written = 0;
276        let initial_write = core::cmp::min(buffer.len(), FIFO_SIZE);
277        for &byte in buffer.iter().take(initial_write) {
278            regs.data().write(|w| unsafe { w.fifo_rdata().bits(byte) });
279        }
280        bytes_written += initial_write;
281
282        regs.scl_stretch_conf()
283            .modify(|_, w| w.slave_scl_stretch_clr().set_bit());
284        regs.int_clr().write(|w| unsafe { w.bits(0x3fff) });
285        self.driver().update_registers();
286
287        loop {
288            self.driver().check_errors()?;
289            if let Some(res) = self
290                .driver()
291                .respond_to_read_step(buffer, &mut bytes_written)
292            {
293                return res;
294            }
295        }
296    }
297}
298
299impl<'d> I2cSlave<'d, Async> {
300    /// Listens for a request from the master asynchronously.
301    pub async fn listen_async(&mut self, buffer: &mut [u8]) -> Result<Command, Error> {
302        let regs = self.driver().info.regs();
303        let state = self.i2c.state();
304
305        self.driver().reset_fifo();
306
307        regs.scl_stretch_conf().modify(|_, w| unsafe {
308            w.stretch_protect_num().bits(0x3ff);
309            w.slave_scl_stretch_en().set_bit()
310        });
311
312        regs.int_clr().write(|w| unsafe { w.bits(0x3fff) });
313        regs.scl_stretch_conf()
314            .modify(|_, w| w.slave_scl_stretch_clr().set_bit());
315        self.driver().update_registers();
316
317        let mut bytes_read = 0;
318        loop {
319            I2cSlaveFuture::new(regs, state, Event::SlaveStretch | Event::TransComplete).await?;
320            if let Some(res) = self.driver().listen_step(buffer, &mut bytes_read) {
321                return res;
322            }
323        }
324    }
325
326    /// Responds to a master read request asynchronously.
327    pub async fn respond_to_read_async(&mut self, buffer: &[u8]) -> Result<ReadStatus, Error> {
328        let regs = self.driver().info.regs();
329        let state = self.i2c.state();
330
331        let mut bytes_written = 0;
332        let initial_write = core::cmp::min(buffer.len(), FIFO_SIZE);
333        for &byte in buffer.iter().take(initial_write) {
334            regs.data().write(|w| unsafe { w.fifo_rdata().bits(byte) });
335        }
336        bytes_written += initial_write;
337
338        regs.scl_stretch_conf()
339            .modify(|_, w| w.slave_scl_stretch_clr().set_bit());
340        regs.int_clr().write(|w| unsafe { w.bits(0x3fff) });
341        self.driver().update_registers();
342
343        loop {
344            I2cSlaveFuture::new(
345                regs,
346                state,
347                Event::SlaveStretch | Event::TransComplete | Event::Nack,
348            )
349            .await?;
350
351            if let Some(res) = self
352                .driver()
353                .respond_to_read_step(buffer, &mut bytes_written)
354            {
355                return res;
356            }
357        }
358    }
359}
360
361impl<Dm: DriverMode> private::Sealed for I2cSlave<'_, Dm> {}
362
363#[derive(Debug, EnumSetType)]
364#[cfg_attr(feature = "defmt", derive(defmt::Format))]
365#[non_exhaustive]
366pub(crate) enum Event {
367    SlaveStretch,
368    TransComplete,
369    Nack,
370}
371
372#[must_use = "futures do nothing unless you `.await` or poll them"]
373struct I2cSlaveFuture<'a> {
374    regs: &'a RegisterBlock,
375    state: &'a State,
376    events: EnumSet<Event>,
377    _wake_lock: WakeLock,
378}
379
380impl<'a> I2cSlaveFuture<'a> {
381    pub fn new(regs: &'a RegisterBlock, state: &'a State, events: EnumSet<Event>) -> Self {
382        regs.int_ena().modify(|_, w| {
383            if events.contains(Event::SlaveStretch) {
384                w.slave_stretch().set_bit();
385            }
386            if events.contains(Event::TransComplete) {
387                w.trans_complete().set_bit();
388            }
389            if events.contains(Event::Nack) {
390                w.nack().set_bit();
391            }
392            w.arbitration_lost().set_bit();
393            w.time_out().set_bit();
394            w
395        });
396
397        Self {
398            regs,
399            state,
400            events,
401            _wake_lock: WakeLock::new(),
402        }
403    }
404}
405
406impl Future for I2cSlaveFuture<'_> {
407    type Output = Result<(), Error>;
408
409    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
410        self.state.waker.register(cx.waker());
411
412        let raw = self.regs.int_raw().read();
413
414        if raw.arbitration_lost().bit_is_set() {
415            return Poll::Ready(Err(Error::ArbitrationLost));
416        }
417        if raw.time_out().bit_is_set() {
418            return Poll::Ready(Err(Error::Timeout));
419        }
420
421        let mut triggered = false;
422        if self.events.contains(Event::SlaveStretch) && raw.slave_stretch().bit_is_set() {
423            triggered = true;
424        }
425        if self.events.contains(Event::TransComplete) && raw.trans_complete().bit_is_set() {
426            triggered = true;
427        }
428        if self.events.contains(Event::Nack) && raw.nack().bit_is_set() {
429            triggered = true;
430        }
431
432        if triggered {
433            Poll::Ready(Ok(()))
434        } else {
435            self.regs.int_ena().modify(|_, w| {
436                if self.events.contains(Event::SlaveStretch) {
437                    w.slave_stretch().set_bit();
438                }
439                if self.events.contains(Event::TransComplete) {
440                    w.trans_complete().set_bit();
441                }
442                if self.events.contains(Event::Nack) {
443                    w.nack().set_bit();
444                }
445                w.arbitration_lost().set_bit();
446                w.time_out().set_bit();
447                w
448            });
449            Poll::Pending
450        }
451    }
452}
453
454impl Drop for I2cSlaveFuture<'_> {
455    fn drop(&mut self) {
456        self.regs.int_ena().write(|w| unsafe { w.bits(0) });
457    }
458}
459
460#[ram]
461fn async_handler(info: &Info, state: &State) {
462    info.regs().int_ena().write(|w| unsafe { w.bits(0) });
463    state.waker.wake();
464}
465
466/// I2C Slave state.
467#[non_exhaustive]
468pub struct State {
469    pub(crate) waker: AtomicWaker,
470}
471
472impl core::fmt::Debug for State {
473    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
474        f.debug_struct("State")
475            .field("waker", &"<AtomicWaker>")
476            .finish()
477    }
478}
479
480/// I2C Slave peripheral information.
481#[derive(Debug)]
482#[non_exhaustive]
483pub struct Info {
484    pub(crate) register_block: *const RegisterBlock,
485    pub(crate) peripheral: crate::system::Peripheral,
486    pub(crate) async_handler: InterruptHandler,
487    pub(crate) scl_output: OutputSignal,
488    pub(crate) scl_input: InputSignal,
489    pub(crate) sda_output: OutputSignal,
490    pub(crate) sda_input: InputSignal,
491}
492
493impl Info {
494    pub(crate) fn regs(&self) -> &RegisterBlock {
495        unsafe { &*self.register_block }
496    }
497}
498
499unsafe impl Sync for Info {}
500
501/// I2C Slave peripheral instance.
502pub trait Instance: crate::private::Sealed + any::Degrade {
503    #[doc(hidden)]
504    fn parts(&self) -> (&Info, &State);
505
506    #[doc(hidden)]
507    #[inline(always)]
508    fn info(&self) -> &Info {
509        self.parts().0
510    }
511
512    #[doc(hidden)]
513    #[inline(always)]
514    fn state(&self) -> &State {
515        self.parts().1
516    }
517}
518
519#[allow(dead_code)]
520struct Driver<'a> {
521    info: &'a Info,
522    state: &'a State,
523    config: &'a DriverConfig,
524}
525
526impl Driver<'_> {
527    fn regs(&self) -> &RegisterBlock {
528        self.info.regs()
529    }
530
531    fn connect_pin(
532        pin: crate::gpio::interconnect::OutputSignal<'_>,
533        input: InputSignal,
534        output: OutputSignal,
535        guard: &mut PinGuard,
536    ) {
537        pin.set_output_high(true);
538        pin.apply_output_config(
539            &OutputConfig::default()
540                .with_drive_mode(DriveMode::OpenDrain)
541                .with_pull(Pull::Up),
542        );
543        pin.set_output_enable(true);
544        pin.set_input_enable(true);
545        input.connect_to(&pin);
546        *guard = interconnect::OutputSignal::connect_with_guard(pin, output);
547    }
548
549    fn init_slave(&self) {
550        self.regs().ctr().write(|w| {
551            w.ms_mode().clear_bit(); // Slave mode
552            w.sda_force_out().set_bit();
553            w.scl_force_out().set_bit();
554            #[cfg(i2c_master_has_arbitration_en)]
555            w.arbitration_en().clear_bit();
556            w.tx_lsb_first().clear_bit();
557            w.rx_lsb_first().clear_bit();
558            w
559        });
560
561        self.reset_fifo();
562
563        self.regs().fifo_conf().modify(|_, w| {
564            w.nonfifo_en().clear_bit();
565            w
566        });
567    }
568
569    fn set_slave_addr(&self, address: I2cAddress) -> Result<(), ConfigError> {
570        match address {
571            I2cAddress::SevenBit(addr) if addr <= 0x7F => {
572                self.regs().slave_addr().write(|w| unsafe {
573                    w.slave_addr().bits(addr as u16);
574                    w.addr_10bit_en().bit(false)
575                });
576                Ok(())
577            }
578            _ => Err(ConfigError::AddressInvalid),
579        }
580    }
581
582    fn update_registers(&self) {
583        #[cfg(i2c_master_has_conf_update)]
584        self.regs().ctr().modify(|_, w| w.conf_upgate().set_bit());
585    }
586
587    fn setup(&self, config: &Config) -> Result<(), ConfigError> {
588        self.init_slave();
589        self.set_slave_addr(config.address)?;
590
591        let regs = self.regs();
592        regs.to().modify(|_, w| unsafe {
593            w.time_out_en().set_bit();
594            w.time_out_value().bits(14);
595            w
596        });
597
598        regs.clk_conf().modify(|_, w| w.sclk_sel().clear_bit());
599        self.set_slave_addr(config.address)?;
600
601        regs.ctr()
602            .modify(|_, w| w.addr_broadcasting_en().clear_bit());
603
604        regs.fifo_conf().modify(|_, w| {
605            w.fifo_prt_en().set_bit();
606            unsafe { w.txfifo_wm_thrhd().bits(0) }
607        });
608
609        regs.fifo_conf().modify(|_, w| w.fifo_prt_en().set_bit());
610        regs.ctr().write(|w| w.rx_full_ack_level().clear_bit());
611
612        regs.fifo_conf()
613            .modify(|_, w| unsafe { w.rxfifo_wm_thrhd().bits(0x1F) });
614
615        regs.sda_hold().write(|w| unsafe { w.time().bits(10u16) });
616        regs.sda_sample().write(|w| unsafe { w.time().bits(10u16) });
617
618        regs.int_ena().write(|w| unsafe { w.bits(0) });
619        regs.int_clr().write(|w| unsafe { w.bits(0x3fff) });
620
621        regs.scl_stretch_conf().modify(|_, w| unsafe {
622            w.stretch_protect_num().bits(0x3ff);
623            w.slave_scl_stretch_en().set_bit()
624        });
625
626        regs.scl_stretch_conf()
627            .modify(|_, w| w.slave_scl_stretch_clr().set_bit());
628        self.update_registers();
629
630        Ok(())
631    }
632
633    fn reset_fifo(&self) {
634        self.regs()
635            .fifo_conf()
636            .modify(|_, w| w.tx_fifo_rst().set_bit());
637        self.regs()
638            .fifo_conf()
639            .modify(|_, w| w.tx_fifo_rst().clear_bit());
640        self.regs()
641            .fifo_conf()
642            .modify(|_, w| w.rx_fifo_rst().set_bit());
643        self.regs()
644            .fifo_conf()
645            .modify(|_, w| w.rx_fifo_rst().clear_bit());
646    }
647
648    fn reset_fsm(&self) {
649        #[cfg(i2c_master_has_reliable_fsm_reset)]
650        {
651            self.regs().ctr().modify(|_, w| w.fsm_rst().set_bit());
652        }
653        #[cfg(not(i2c_master_has_reliable_fsm_reset))]
654        {
655            crate::system::PeripheralClockControl::reset(self.info.peripheral);
656            self.setup(&self.config.config).ok();
657        }
658    }
659
660    fn check_errors(&self) -> Result<(), Error> {
661        let r = self.regs().int_raw().read();
662
663        if r.arbitration_lost().bit_is_set() {
664            return Err(Error::ArbitrationLost);
665        }
666        if r.time_out().bit_is_set() {
667            return Err(Error::Timeout);
668        }
669        Ok(())
670    }
671
672    fn listen_step(
673        &self,
674        buffer: &mut [u8],
675        bytes_read: &mut usize,
676    ) -> Option<Result<Command, Error>> {
677        let regs = self.regs();
678        let ints = regs.int_raw().read();
679
680        if ints.slave_stretch().bit_is_set() {
681            let cause = regs.sr().read().stretch_cause().bits();
682            match cause {
683                0 => {
684                    let rw = regs.sr().read().slave_rw().bit_is_set();
685                    if rw {
686                        regs.int_clr()
687                            .write(|w| w.slave_stretch().clear_bit_by_one());
688                        return Some(Ok(Command::Read));
689                    } else {
690                        regs.scl_stretch_conf()
691                            .modify(|_, w| w.slave_scl_stretch_clr().set_bit());
692                        regs.int_clr()
693                            .write(|w| w.slave_stretch().clear_bit_by_one());
694                    }
695                }
696                2 => {
697                    while regs.sr().read().rxfifo_cnt().bits() > 0 && *bytes_read < buffer.len() {
698                        buffer[*bytes_read] = regs.data().read().fifo_rdata().bits();
699                        *bytes_read += 1;
700                    }
701                    regs.scl_stretch_conf()
702                        .modify(|_, w| w.slave_scl_stretch_clr().set_bit());
703                    regs.int_clr()
704                        .write(|w| w.slave_stretch().clear_bit_by_one());
705                }
706                _ => {
707                    regs.scl_stretch_conf()
708                        .modify(|_, w| w.slave_scl_stretch_clr().set_bit());
709                    regs.int_clr()
710                        .write(|w| w.slave_stretch().clear_bit_by_one());
711                }
712            }
713        }
714
715        while regs.sr().read().rxfifo_cnt().bits() > 0 && *bytes_read < buffer.len() {
716            buffer[*bytes_read] = regs.data().read().fifo_rdata().bits();
717            *bytes_read += 1;
718        }
719
720        if ints.trans_complete().bit_is_set() {
721            regs.int_clr()
722                .write(|w| w.trans_complete().clear_bit_by_one());
723            return Some(Ok(Command::Write(*bytes_read)));
724        }
725
726        None
727    }
728
729    fn respond_to_read_step(
730        &self,
731        buffer: &[u8],
732        bytes_written: &mut usize,
733    ) -> Option<Result<ReadStatus, Error>> {
734        let regs = self.regs();
735        let ints = regs.int_raw().read();
736
737        if ints.trans_complete().bit_is_set() || ints.nack().bit_is_set() {
738            let is_nack = ints.nack().bit_is_set();
739            regs.int_clr().write(|w| {
740                w.trans_complete().clear_bit_by_one();
741                w.nack().clear_bit_by_one()
742            });
743            if is_nack {
744                self.reset_fifo();
745                self.reset_fsm();
746            }
747
748            if *bytes_written > buffer.len() {
749                return Some(Ok(ReadStatus::NeedMoreBytes));
750            } else if *bytes_written < buffer.len() {
751                let rem = (buffer.len() - *bytes_written) as u16;
752                return Some(Ok(ReadStatus::LeftoverBytes(rem)));
753            } else {
754                return Some(Ok(ReadStatus::Done));
755            }
756        }
757
758        if ints.slave_stretch().bit_is_set() {
759            let cause = regs.sr().read().stretch_cause().bits();
760            if cause == 1 {
761                if *bytes_written < buffer.len() {
762                    let txfifo_cnt = regs.sr().read().txfifo_cnt().bits() as usize;
763                    let free = FIFO_SIZE - txfifo_cnt;
764                    let to_write = core::cmp::min(buffer.len() - *bytes_written, free);
765                    for i in 0..to_write {
766                        regs.data()
767                            .write(|w| unsafe { w.fifo_rdata().bits(buffer[*bytes_written + i]) });
768                    }
769                    *bytes_written += to_write;
770
771                    regs.scl_stretch_conf()
772                        .modify(|_, w| w.slave_scl_stretch_clr().set_bit());
773                    regs.int_clr()
774                        .write(|w| w.slave_stretch().clear_bit_by_one());
775                    self.update_registers();
776                } else {
777                    regs.data().write(|w| unsafe { w.fifo_rdata().bits(0xFF) });
778                    *bytes_written += 1;
779                    regs.scl_stretch_conf()
780                        .modify(|_, w| w.slave_scl_stretch_clr().set_bit());
781                    regs.int_clr()
782                        .write(|w| w.slave_stretch().clear_bit_by_one());
783                    self.update_registers();
784                }
785            } else {
786                regs.scl_stretch_conf()
787                    .modify(|_, w| w.slave_scl_stretch_clr().set_bit());
788                regs.int_clr()
789                    .write(|w| w.slave_stretch().clear_bit_by_one());
790                self.update_registers();
791            }
792        }
793
794        None
795    }
796}
797
798#[cfg(i2c_slave_i2c0)]
799impl crate::i2c::slave::Instance for crate::peripherals::I2C0<'_> {
800    fn parts(&self) -> (&Info, &State) {
801        #[handler]
802        #[ram]
803        pub(super) fn irq_handler() {
804            async_handler(&PERIPHERAL, &STATE);
805        }
806
807        static STATE: State = State {
808            waker: AtomicWaker::new(),
809        };
810
811        static PERIPHERAL: Info = Info {
812            register_block: crate::peripherals::I2C0::ptr(),
813            peripheral: crate::system::Peripheral::I2cExt0,
814            async_handler: irq_handler,
815            scl_output: OutputSignal::I2CEXT0_SCL,
816            scl_input: InputSignal::I2CEXT0_SCL,
817            sda_output: OutputSignal::I2CEXT0_SDA,
818            sda_input: InputSignal::I2CEXT0_SDA,
819        };
820        (&PERIPHERAL, &STATE)
821    }
822}
823
824#[cfg(i2c_slave_i2c1)]
825impl crate::i2c::slave::Instance for crate::peripherals::I2C1<'_> {
826    fn parts(&self) -> (&Info, &State) {
827        #[handler]
828        #[ram]
829        pub(super) fn irq_handler() {
830            async_handler(&PERIPHERAL, &STATE);
831        }
832
833        static STATE: State = State {
834            waker: AtomicWaker::new(),
835        };
836
837        static PERIPHERAL: Info = Info {
838            register_block: crate::peripherals::I2C1::ptr(),
839            peripheral: crate::system::Peripheral::I2cExt1,
840            async_handler: irq_handler,
841            scl_output: OutputSignal::I2CEXT1_SCL,
842            scl_input: InputSignal::I2CEXT1_SCL,
843            sda_output: OutputSignal::I2CEXT1_SDA,
844            sda_input: InputSignal::I2CEXT1_SDA,
845        };
846        (&PERIPHERAL, &STATE)
847    }
848}
849
850crate::any_peripheral! {
851    /// Any I2C peripheral in slave mode.
852    pub peripheral AnyI2c<'d> {
853        #[cfg(i2c_slave_i2c0)]
854        I2c0(crate::peripherals::I2C0<'d>),
855        #[cfg(i2c_slave_i2c1)]
856        I2c1(crate::peripherals::I2C1<'d>),
857    }
858}
859
860impl crate::i2c::slave::Instance for AnyI2c<'_> {
861    fn parts(&self) -> (&Info, &State) {
862        any::delegate!(self, i2c => { crate::i2c::slave::Instance::parts(i2c) })
863    }
864}
865
866impl AnyI2c<'_> {
867    fn bind_peri_interrupt(&self, handler: InterruptHandler) {
868        any::delegate!(self, i2c => { i2c.bind_peri_interrupt(handler) })
869    }
870
871    fn disable_peri_interrupt(&self) {
872        any::delegate!(self, i2c => { i2c.disable_peri_interrupt() })
873    }
874
875    fn enable_peri_interrupt(&self, priority: crate::interrupt::Priority) {
876        any::delegate!(self, i2c => { i2c.enable_peri_interrupt(priority) })
877    }
878
879    fn set_interrupt_handler(&self, handler: InterruptHandler) {
880        self.disable_peri_interrupt();
881
882        self.info().regs().int_ena().write(|w| unsafe { w.bits(0) });
883        self.info()
884            .regs()
885            .int_clr()
886            .write(|w| unsafe { w.bits(0x3fff) });
887
888        self.bind_peri_interrupt(handler);
889        self.enable_peri_interrupt(handler.priority());
890    }
891}