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