lpc55s6x_hal/drivers/
i2c.rs

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