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);