lpc55_hal/drivers/
i2c.rs

1use crate::time::Hertz;
2use crate::traits::wg::blocking::i2c::{Read, Write, WriteRead};
3use crate::typestates::pin::{
4    flexcomm::{
5        // Trait marking I2C peripherals and pins
6        I2c,
7        I2cPins,
8    },
9    PinId,
10};
11use core::cmp::min;
12use core::marker::PhantomData;
13
14pub mod prelude {
15    pub use super::Error as I2cError;
16    pub use super::I2cMaster;
17    pub use super::Result as I2cResult;
18}
19
20/// I2C error
21#[derive(Debug)]
22#[non_exhaustive]
23pub enum Error {
24    /// Bus error (catch-all)
25    Bus,
26    /// Arbitration loss
27    ArbitrationLoss,
28    /// NACK
29    NackAddress,
30    /// NACK
31    NackData,
32    /// Start/Stop error
33    StartStop,
34}
35
36pub type Result<T> = core::result::Result<T, Error>;
37
38// TODO: Parametrize with Master/Slave MODE
39/// I2C peripheral operating in master mode
40pub struct I2cMaster<PIO1, PIO2, I2C, PINS>
41where
42    PIO1: PinId,
43    PIO2: PinId,
44    I2C: I2c,
45    PINS: I2cPins<PIO1, PIO2, I2C>,
46{
47    i2c: I2C,
48    pins: PINS,
49    _pin1: PhantomData<PIO1>,
50    _pin2: PhantomData<PIO2>,
51}
52
53impl<PIO1, PIO2, I2C, PINS> I2cMaster<PIO1, PIO2, I2C, PINS>
54where
55    PIO1: PinId,
56    PIO2: PinId,
57    I2C: I2c,
58    PINS: I2cPins<PIO1, PIO2, I2C>,
59{
60    /// Weird crashes happen when running system at 150Mhz PLL.
61    /// Suggested use: 100khz or 400khz
62    pub fn new<Speed: Into<Hertz>>(i2c: I2C, pins: PINS, speed: Speed) -> Self {
63        // Simplified setup: We always use 12MHz clock, and only support 100kHz
64        let speed: Hertz = speed.into();
65        let speed: u32 = speed.0;
66        assert!(speed <= 1_000_000);
67        i2c.cfg.modify(
68            |_, w| w.msten().enabled(), // .slven().disabled()
69                                        // .monen().disabled()
70                                        // ...etc.
71        );
72
73        // use cortex_m_semihosting::hprintln;
74
75        // logic from `fsl_i2c.c` in SDK
76        let mut best_div: u16 = 0;
77        let mut best_scl: u8 = 0;
78        let mut best_err: u32 = 0;
79        for scl in (2..=9).rev() {
80            let denominator = 2 * scl * speed;
81            let div = min(10_000, 12_000_000 / denominator);
82            let err = 12_000_000 - div * denominator;
83            if err < best_err || best_err == 0 {
84                // first time, or smaller error
85                best_div = div as u16; // limited by 10_000
86                best_scl = scl as u8; // limited by 9
87                best_err = err;
88            }
89            if err == 0 || div >= 10_000 {
90                // clamped at 10k means next scl is smaller means err is larger
91                break;
92            }
93        }
94
95        // Weird suggestion from UM.
96        // UM also claims both that:
97        // - DIV must be 1 (?!)
98        // - Frequency after clkdiv must be <= 2 mhz
99        //
100        // if speed.0 == 400 {
101        //     best_div = 14;
102        //     best_scl = 0;
103        // }
104
105        // hprintln!("speed {}, div {}, scl {}", speed, best_div, best_scl).ok();
106
107        // best_div = 10; best_scl = 6;
108        // 100 kbits/s: div = 10, scl = 6
109        // 400 kbits/s: div = 3, scl = 5
110        // 1 mbit/s: div = 1, scl = 6
111        i2c.clkdiv
112            .modify(|_, w| unsafe { w.divval().bits(best_div - 1) });
113        i2c.msttime.modify(|_, w| {
114            w.mstsclhigh()
115                .bits(best_scl - 2)
116                .mstscllow()
117                .bits(best_scl - 2)
118        });
119
120        // or whatever...
121
122        Self {
123            i2c,
124            pins,
125            _pin1: PhantomData,
126            _pin2: PhantomData,
127        }
128    }
129
130    pub fn release(self) -> (I2C, PINS) {
131        (self.i2c, self.pins)
132    }
133
134    #[inline(always)]
135    fn return_on_error(&self) -> Result<()> {
136        // use cortex_m_semihosting::dbg;
137        if self.i2c.stat.read().mststate().is_nack_data() {
138            // dbg!(Error::NackData);
139            return Err(Error::NackData);
140        }
141        if self.i2c.stat.read().mststate().is_nack_address() {
142            // dbg!(Error::NackData);
143            return Err(Error::NackAddress);
144        }
145        if self.i2c.stat.read().mstarbloss().is_arbitration_loss() {
146            // dbg!(Error::NackData);
147            return Err(Error::ArbitrationLoss);
148        }
149        if self.i2c.stat.read().mstststperr().is_error() {
150            // dbg!(Error::NackData);
151            return Err(Error::StartStop);
152        }
153        Ok(())
154    }
155
156    fn write_without_stop(&mut self, addr: u8, bytes: &[u8]) -> Result<()> {
157        self.return_on_error()?;
158
159        // Write the slave address with the RW bit set to 0 to the master data register MSTDAT.
160        self.i2c
161            .mstdat
162            .modify(|_, w| unsafe { w.data().bits(addr << 1) });
163        // Start the transmission by setting the MSTSTART bit to 1 in the master control register.
164        self.i2c.mstctl.write(|w| w.mststart().start());
165        // Wait for the pending status to be set (MSTPENDING = 1) by polling the STAT register
166        // TODO: Consider implementing a timeout (loop at most N times...) :TODO
167        while self.i2c.stat.read().mstpending().is_in_progress() {
168            continue;
169        }
170
171        self.return_on_error()?;
172        if !self.i2c.stat.read().mststate().is_transmit_ready() {
173            // dbg!(Error::Bus);
174            return Err(Error::Bus);
175        }
176
177        // Send bytes
178        for byte in bytes {
179            // write a byte
180            self.i2c
181                .mstdat
182                .modify(|_, w| unsafe { w.data().bits(*byte) });
183            // instruct master to continue
184            self.i2c.mstctl.write(|w| w.mstcontinue().continue_());
185            // Wait until done
186            while self.i2c.stat.read().mstpending().is_in_progress() {
187                continue;
188            }
189
190            // Error handling
191            self.return_on_error()?;
192            if !self.i2c.stat.read().mststate().is_transmit_ready() {
193                // dbg!(Error::Bus);
194                return Err(Error::Bus);
195            }
196        }
197
198        // Fallthrough is success
199        Ok(())
200    }
201
202    fn stop(&mut self) -> Result<()> {
203        // Stop the transmission by setting the MSTSTOP bit to 1 in the master control register.
204        self.i2c.mstctl.write(|w| w.mststop().stop());
205        // Wait for the pending status to be set (MSTPENDING = 1) by polling the STAT register
206        while self.i2c.stat.read().mstpending().is_in_progress() {}
207
208        self.return_on_error()?;
209        if !self.i2c.stat.read().mststate().is_idle() {
210            // dbg!(Error::Bus);
211            return Err(Error::Bus);
212        }
213
214        // Fallthrough is success
215        Ok(())
216    }
217}
218
219impl<PIO1, PIO2, I2C, PINS> Write for I2cMaster<PIO1, PIO2, I2C, PINS>
220where
221    PIO1: PinId,
222    PIO2: PinId,
223    I2C: I2c,
224    PINS: I2cPins<PIO1, PIO2, I2C>,
225{
226    type Error = Error;
227
228    fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<()> {
229        self.write_without_stop(addr, bytes)?;
230        self.stop()
231    }
232}
233
234impl<PIO1, PIO2, I2C, PINS> Read for I2cMaster<PIO1, PIO2, I2C, PINS>
235where
236    PIO1: PinId,
237    PIO2: PinId,
238    I2C: I2c,
239    PINS: I2cPins<PIO1, PIO2, I2C>,
240{
241    type Error = Error;
242
243    fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<()> {
244        if let Some((last, buffer)) = buffer.split_last_mut() {
245            // Write the slave address with the RW bit set to 1 to the master data register MSTDAT.
246            self.i2c
247                .mstdat
248                .modify(|_, w| unsafe { w.data().bits((addr << 1) | 1) });
249            // Start the transmission by setting the MSTSTART bit to 1 in the master control register.
250            self.i2c.mstctl.write(|w| w.mststart().start());
251
252            // Wait for the pending status to be set (MSTPENDING = 1) by polling the STAT register
253            while self.i2c.stat.read().mstpending().is_in_progress() {}
254
255            self.return_on_error()?;
256            if !self.i2c.stat.read().mststate().is_receive_ready() {
257                return Err(Error::Bus);
258            }
259
260            for byte in buffer {
261                // Read a byte
262                *byte = self.i2c.mstdat.read().data().bits();
263                // Instruct master to continue
264                self.i2c.mstctl.write(|w| w.mstcontinue().continue_());
265
266                // Wait for next byte
267                while self.i2c.stat.read().mstpending().is_in_progress() {}
268
269                self.return_on_error()?;
270                if !self.i2c.stat.read().mststate().is_receive_ready() {
271                    return Err(Error::Bus);
272                }
273            }
274
275            // Read last byte
276            *last = self.i2c.mstdat.read().data().bits();
277
278            self.stop()?;
279        }
280
281        // Fallthrough is success
282        Ok(())
283    }
284}
285
286impl<PIO1, PIO2, I2C, PINS> WriteRead for I2cMaster<PIO1, PIO2, I2C, PINS>
287where
288    PIO1: PinId,
289    PIO2: PinId,
290    I2C: I2c,
291    PINS: I2cPins<PIO1, PIO2, I2C>,
292{
293    type Error = Error;
294
295    fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<()> {
296        self.write_without_stop(addr, bytes)?;
297        self.read(addr, buffer)?;
298
299        Ok(())
300    }
301}
302
303// impl<PINS> I2cCommon for I2cMaster<I2C, PINS>
304// where
305//     PINS: I2cPins<I2C>,
306// {
307//     fn send_byte(&self, byte: u8) -> Result<(), Error> {
308//         // Write the byte
309//         self.i2c.mstdat.modify(|_, w| unsafe { w.data().bits(byte) } );
310//         // Instruct master to continue
311//         self.i2c.mstctl.modify(|_, w| w.mstcontinue().continue_());
312//         // Wait until done
313//         while self.i2c.stat.read().mstpending().is_in_progress() {}
314//         // Check for error
315//         if !self.i2c.stat.read().mststate().is_transmit_ready() {
316//             return Err(Error::Nack);
317//         }
318
319//         Ok(())
320//     }
321
322//     fn recv_byte(&self) -> Result<u8, Error> {
323//         let data = self.i2c.mstdat.read().data().bits();
324//         // Wait until done
325//         while self.i2c.stat.read().mstpending().is_in_progress() {}
326//         // Check for error
327//         if !self.i2c.stat.read().mststate().is_receive_ready() {
328//             return Err(Error::Nack);
329//         }
330//         Ok(data)
331//     }
332// }
333
334// macro_rules impl_i2c
335// }}
336
337// impl_i2c!(I2c0, I2c0Master);
338// impl_i2c!(I2c1, I2c1Master);
339// impl_i2c!(I2c2, I2c2Master);
340// impl_i2c!(I2c3, I2c3Master);
341// impl_i2c!(I2c4, I2c4Master);
342// impl_i2c!(I2c5, I2c5Master);
343// impl_i2c!(I2c6, I2c6Master);
344// impl_i2c!(I2c7, I2c7Master);