e310x_hal/
i2c.rs

1//! I2C Master Interface
2//!
3//! The SiFive Inter-Integrated Circuit (I2C) Master Interface
4//! is based on OpenCores® I2C Master Core.
5//!
6//! You can use the [`I2c`] interface with these I2C instances
7//!
8//! # I2C0
9//! - SDA: Pin 12 IOF0
10//! - SCL: Pin 13 IOF0
11//! - Interrupt::I2C0
12
13use crate::{clock::Clocks, time::Bps};
14use core::ops::Deref;
15use e310x::{i2c0, I2c0};
16use embedded_hal::i2c::{self, ErrorKind, ErrorType, NoAcknowledgeSource, Operation};
17
18/// SDA pin
19pub trait SdaPin<I2C>: private::Sealed {}
20
21/// SCL pin
22pub trait SclPin<I2C>: private::Sealed {}
23
24/// I2cX trait extends the I2C peripheral
25pub trait I2cX: Deref<Target = i2c0::RegisterBlock> + private::Sealed {}
26
27mod i2c_impl {
28    use super::{I2c0, I2cX, SclPin, SdaPin};
29    use crate::gpio::{gpio0, IOF0};
30
31    /// I2C0
32    impl I2cX for I2c0 {}
33    impl<T> SdaPin<I2c0> for gpio0::Pin12<IOF0<T>> {}
34    impl<T> SclPin<I2c0> for gpio0::Pin13<IOF0<T>> {}
35}
36
37/// Transmission speed
38pub enum Speed {
39    /// 100Kbps
40    Normal,
41
42    /// 400Kbps
43    Fast,
44
45    /// Custom speed
46    Custom(Bps),
47}
48
49/// I2C abstraction
50pub struct I2c<I2C, PINS> {
51    i2c: I2C,
52    pins: PINS,
53}
54
55impl<I2C: I2cX, SDA, SCL> I2c<I2C, (SDA, SCL)> {
56    /// Configures an I2C peripheral
57    pub fn new(i2c: I2C, sda: SDA, scl: SCL, speed: Speed, clocks: Clocks) -> Self
58    where
59        SDA: SdaPin<I2C>,
60        SCL: SclPin<I2C>,
61    {
62        // Calculate prescaler value
63        let desired_speed = match speed {
64            Speed::Normal => 100_000,
65            Speed::Fast => 400_000,
66            Speed::Custom(bps) => bps.0,
67        };
68        let clock = clocks.tlclk().0;
69        assert!(desired_speed * 5 <= clock);
70        let prescaler = clock / (5 * desired_speed) - 1;
71        assert!(prescaler < (1 << 16));
72
73        // Turn off i2c
74        i2c.ctr().write(|w| w.en().clear_bit().ien().clear_bit());
75
76        // Set prescaler
77        let prescaler_lo = (prescaler & 0xff) as u8;
78        let prescaler_hi = ((prescaler >> 8) & 0xff) as u8;
79        i2c.prer_lo()
80            .write(|w| unsafe { w.value().bits(prescaler_lo) });
81        i2c.prer_hi()
82            .write(|w| unsafe { w.value().bits(prescaler_hi) });
83
84        // Turn on i2c
85        i2c.ctr().write(|w| w.en().set_bit());
86
87        Self {
88            i2c,
89            pins: (sda, scl),
90        }
91    }
92}
93
94impl<I2C, PINS> I2c<I2C, PINS> {
95    /// Releases the I2C peripheral and associated pins
96    pub fn free(self) -> (I2C, PINS) {
97        (self.i2c, self.pins)
98    }
99}
100
101impl<I2C: I2cX, PINS> I2c<I2C, PINS> {
102    /// Read the status register.
103    fn read_sr(&self) -> i2c0::sr::R {
104        self.i2c.sr().read()
105    }
106
107    /// Clear the interrupt flag in the control register.
108    fn clear_interrupt(&self) {
109        self.i2c.cr().write(|w| w.iack().set_bit());
110    }
111
112    /// Reset the I2C peripheral.
113    fn reset(&self) {
114        self.clear_interrupt();
115    }
116
117    /// Set the stop bit in the control register.
118    /// A stop condition will be sent on the bus.
119    fn set_stop(&self) {
120        self.i2c.cr().write(|w| w.sto().set_bit());
121    }
122
123    /// Set the next byte to be transmitted to the I2C slave device.
124    ///
125    /// # Note
126    ///
127    /// This function does not start the transmission. You must call
128    /// [`Self::write_to_slave`] to start the transmission.
129    fn write_txr(&self, byte: u8) {
130        self.i2c.txr_rxr().write(|w| unsafe { w.data().bits(byte) });
131    }
132
133    /// Read the last byte received from the I2C slave device.
134    fn read_rxr(&self) -> u8 {
135        self.i2c.txr_rxr().read().data().bits()
136    }
137
138    /// Trigger a write to the slave device.
139    /// This function should be called after writing to the transmit register.
140    ///
141    /// # Note
142    ///
143    /// This function does not block until the write is complete. You must call
144    /// [`Self::wait_for_write`] to wait for the write to complete.
145    fn trigger_write(&self, start: bool, stop: bool) {
146        self.i2c
147            .cr()
148            .write(|w| w.sta().bit(start).wr().set_bit().sto().bit(stop));
149    }
150
151    /// Trigger a read from the slave device.
152    /// This function should be called before reading the receive register.
153    ///
154    /// # Note
155    ///
156    /// This function does not block until the read is complete. You must call
157    /// [`Self::wait_for_read`] to wait for the read to complete.
158    fn trigger_read(&self, ack: bool, stop: bool) {
159        self.i2c
160            .cr()
161            .write(|w| w.rd().set_bit().ack().bit(ack).sto().bit(stop));
162    }
163
164    /// Check if the I2C peripheral is idle.
165    fn is_idle(&self) -> bool {
166        !self.read_sr().busy().bit_is_set()
167    }
168
169    /// Blocking version of [`Self::is_idle`].
170    fn wait_idle(&self) {
171        while !self.is_idle() {}
172    }
173
174    /// Acknowledge an interrupt.
175    ///
176    /// # Errors
177    ///
178    /// In case of arbitration loss, a stop condition is sent
179    /// and an [`ErrorKind::ArbitrationLoss`] is returned.
180    fn ack_interrupt(&self) -> nb::Result<(), ErrorKind> {
181        let sr = self.read_sr();
182        if sr.if_().bit_is_set() {
183            self.clear_interrupt();
184            if sr.al().bit_is_set() {
185                self.set_stop();
186                Err(nb::Error::Other(ErrorKind::ArbitrationLoss))
187            } else {
188                Ok(())
189            }
190        } else {
191            Err(nb::Error::WouldBlock)
192        }
193    }
194
195    /// Wait for a read operation to complete.
196    ///
197    /// # Errors
198    ///
199    /// In case of arbitration loss it waits until the bus is idle
200    /// before returning an [`ErrorKind::ArbitrationLoss`] error.
201    fn wait_for_read(&self) -> Result<(), ErrorKind> {
202        nb::block!(self.ack_interrupt())
203    }
204
205    /// Wait for a write operation to complete.
206    ///
207    /// # Errors
208    ///
209    /// If the slave device does not acknowledge the write, a stop condition
210    /// is sent and an [`ErrorKind::NoAcknowledge`] is returned.
211    ///
212    /// In case of arbitration loss it waits until the bus is idle
213    /// before returning an [`ErrorKind::ArbitrationLoss`] error.
214    fn wait_for_write(&self, source: NoAcknowledgeSource) -> Result<(), ErrorKind> {
215        nb::block!(self.ack_interrupt())?;
216        if self.read_sr().rx_ack().bit_is_set() {
217            self.set_stop();
218            Err(ErrorKind::NoAcknowledge(source))
219        } else {
220            Ok(())
221        }
222    }
223}
224
225const FLAG_READ: u8 = 1;
226const FLAG_WRITE: u8 = 0;
227
228impl<I2C: I2cX, PINS> ErrorType for I2c<I2C, PINS> {
229    type Error = ErrorKind;
230}
231
232impl<I2C: I2cX, PINS> i2c::I2c for I2c<I2C, PINS> {
233    fn transaction(
234        &mut self,
235        address: u8,
236        operations: &mut [Operation<'_>],
237    ) -> Result<(), Self::Error> {
238        let n_ops = operations.len();
239        if n_ops == 0 {
240            return Ok(());
241        }
242
243        self.wait_idle();
244        self.reset();
245
246        // we use this flag to detect when we need to send a (repeated) start
247        let mut last_op_was_read = match &operations[0] {
248            Operation::Read(_) => false,
249            Operation::Write(_) => true,
250        };
251
252        for (i, operation) in operations.iter_mut().enumerate() {
253            match operation {
254                Operation::Write(bytes) => {
255                    // Send write command
256                    self.write_txr((address << 1) + FLAG_WRITE);
257                    self.trigger_write(last_op_was_read, false);
258                    self.wait_for_write(NoAcknowledgeSource::Address)?;
259                    last_op_was_read = false;
260
261                    // Write bytes
262                    let n_bytes = bytes.len();
263                    for (j, byte) in bytes.iter().enumerate() {
264                        self.write_txr(*byte);
265                        self.trigger_write(false, (i == n_ops - 1) && (j == n_bytes - 1));
266                        self.wait_for_write(NoAcknowledgeSource::Data)?;
267                    }
268                }
269                Operation::Read(buffer) => {
270                    // Send read command
271                    self.write_txr((address << 1) + FLAG_READ);
272                    self.trigger_write(!last_op_was_read, false);
273                    self.wait_for_write(NoAcknowledgeSource::Address)?;
274                    last_op_was_read = true;
275
276                    // Read bytes
277                    let n_bytes = buffer.len();
278                    for (j, byte) in buffer.iter_mut().enumerate() {
279                        self.trigger_read(j == n_bytes - 1, (i == n_ops - 1) && (j == n_bytes - 1));
280                        self.wait_for_read()?;
281                        *byte = self.read_rxr();
282                    }
283                }
284            }
285        }
286        self.wait_idle();
287
288        Ok(())
289    }
290}
291
292mod private {
293    use super::I2c0;
294    use crate::gpio::{gpio0, IOF0};
295
296    pub trait Sealed {}
297
298    // I2C0
299    impl Sealed for I2c0 {}
300    impl<T> Sealed for gpio0::Pin12<IOF0<T>> {}
301    impl<T> Sealed for gpio0::Pin13<IOF0<T>> {}
302}