Skip to content

Commit 28afbe1

Browse files
Migrate I2C to embedded-hal 1.0
1 parent 23be68b commit 28afbe1

File tree

1 file changed

+173
-65
lines changed

1 file changed

+173
-65
lines changed

src/drivers/i2c.rs

Lines changed: 173 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
use embedded_hal::i2c::{NoAcknowledgeSource, Operation};
2+
13
use crate::time::Hertz;
24
use crate::traits::wg::blocking::i2c::{Read, Write, WriteRead};
5+
use crate::traits::wg1::i2c::{Error as ErrorTrait, ErrorType, I2c as I2cTrait};
36
use crate::typestates::pin::{
47
flexcomm::{
58
// Trait marking I2C peripherals and pins
@@ -33,6 +36,29 @@ pub enum Error {
3336
StartStop,
3437
}
3538

39+
impl ErrorTrait for Error {
40+
fn kind(&self) -> embedded_hal::i2c::ErrorKind {
41+
use embedded_hal::i2c::ErrorKind;
42+
match self {
43+
Self::Bus => ErrorKind::Bus,
44+
Self::ArbitrationLoss => ErrorKind::ArbitrationLoss,
45+
Self::NackAddress => ErrorKind::NoAcknowledge(NoAcknowledgeSource::Address),
46+
Self::NackData => ErrorKind::NoAcknowledge(NoAcknowledgeSource::Data),
47+
Self::StartStop => ErrorKind::Other,
48+
}
49+
}
50+
}
51+
52+
impl<PIO1, PIO2, I2C, PINS> ErrorType for I2cMaster<PIO1, PIO2, I2C, PINS>
53+
where
54+
PIO1: PinId,
55+
PIO2: PinId,
56+
I2C: I2c,
57+
PINS: I2cPins<PIO1, PIO2, I2C>,
58+
{
59+
type Error = Error;
60+
}
61+
3662
pub type Result<T> = core::result::Result<T, Error>;
3763

3864
// TODO: Parametrize with Master/Slave MODE
@@ -153,27 +179,7 @@ where
153179
Ok(())
154180
}
155181

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-
182+
fn write_inner_bytes(&mut self, bytes: &[u8]) -> Result<()> {
177183
// Send bytes
178184
for byte in bytes {
179185
// write a byte
@@ -194,6 +200,35 @@ where
194200
return Err(Error::Bus);
195201
}
196202
}
203+
Ok(())
204+
}
205+
206+
fn start_write(&mut self, addr: u8) -> Result<()> {
207+
self.return_on_error()?;
208+
209+
// Write the slave address with the RW bit set to 0 to the master data register MSTDAT.
210+
self.i2c
211+
.mstdat
212+
.modify(|_, w| unsafe { w.data().bits(addr << 1) });
213+
// Start the transmission by setting the MSTSTART bit to 1 in the master control register.
214+
self.i2c.mstctl.write(|w| w.mststart().start());
215+
// Wait for the pending status to be set (MSTPENDING = 1) by polling the STAT register
216+
// TODO: Consider implementing a timeout (loop at most N times...) :TODO
217+
while self.i2c.stat.read().mstpending().is_in_progress() {
218+
continue;
219+
}
220+
221+
self.return_on_error()?;
222+
if !self.i2c.stat.read().mststate().is_transmit_ready() {
223+
// dbg!(Error::Bus);
224+
return Err(Error::Bus);
225+
}
226+
Ok(())
227+
}
228+
229+
fn write_without_stop(&mut self, addr: u8, bytes: &[u8]) -> Result<()> {
230+
self.start_write(addr)?;
231+
self.write_inner_bytes(bytes)?;
197232

198233
// Fallthrough is success
199234
Ok(())
@@ -214,6 +249,62 @@ where
214249
// Fallthrough is success
215250
Ok(())
216251
}
252+
253+
fn read_byte(&mut self) -> u8 {
254+
self.i2c.mstdat.read().data().bits()
255+
}
256+
257+
fn wait_for_byte_ready(&mut self) -> Result<()> {
258+
// Wait for next byte
259+
while self.i2c.stat.read().mstpending().is_in_progress() {}
260+
261+
self.return_on_error()?;
262+
if !self.i2c.stat.read().mststate().is_receive_ready() {
263+
return Err(Error::Bus);
264+
}
265+
266+
Ok(())
267+
}
268+
269+
fn wait_for_next_byte(&mut self) -> Result<u8> {
270+
// Instruct master to continue
271+
self.i2c.mstctl.write(|w| w.mstcontinue().continue_());
272+
273+
self.wait_for_byte_ready()?;
274+
Ok(self.read_byte())
275+
}
276+
277+
fn start_read(&mut self, addr: u8) -> Result<()> {
278+
// Write the slave address with the RW bit set to 1 to the master data register MSTDAT.
279+
self.i2c
280+
.mstdat
281+
.modify(|_, w| unsafe { w.data().bits((addr << 1) | 1) });
282+
// Start the transmission by setting the MSTSTART bit to 1 in the master control register.
283+
self.i2c.mstctl.write(|w| w.mststart().start());
284+
Ok(())
285+
}
286+
287+
fn read_inner_bytes(&mut self, buffer: &mut [u8]) -> Result<()> {
288+
for byte in buffer {
289+
// Read a byte
290+
*byte = self.wait_for_next_byte()?;
291+
}
292+
Ok(())
293+
}
294+
295+
fn read_without_stop(&mut self, addr: u8, buffer: &mut [u8]) -> Result<()> {
296+
if let Some((first, buffer)) = buffer.split_first_mut() {
297+
self.start_read(addr)?;
298+
299+
self.wait_for_byte_ready()?;
300+
// read first byte
301+
*first = self.read_byte();
302+
self.read_inner_bytes(buffer)?;
303+
}
304+
305+
// Reading to an empty buffer is a noop
306+
Ok(())
307+
}
217308
}
218309

219310
impl<PIO1, PIO2, I2C, PINS> Write for I2cMaster<PIO1, PIO2, I2C, PINS>
@@ -226,8 +317,7 @@ where
226317
type Error = Error;
227318

228319
fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<()> {
229-
self.write_without_stop(addr, bytes)?;
230-
self.stop()
320+
<Self as I2cTrait>::write(self, addr, bytes)
231321
}
232322
}
233323

@@ -241,45 +331,7 @@ where
241331
type Error = Error;
242332

243333
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(())
334+
<Self as I2cTrait>::read(self, addr, buffer)
283335
}
284336
}
285337

@@ -293,10 +345,66 @@ where
293345
type Error = Error;
294346

295347
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)?;
348+
<Self as I2cTrait>::write_read(self, addr, bytes, buffer)
349+
}
350+
}
298351

299-
Ok(())
352+
impl<PIO1, PIO2, I2C, PINS> I2cTrait for I2cMaster<PIO1, PIO2, I2C, PINS>
353+
where
354+
PIO1: PinId,
355+
PIO2: PinId,
356+
I2C: I2c,
357+
PINS: I2cPins<PIO1, PIO2, I2C>,
358+
{
359+
fn transaction(
360+
&mut self,
361+
address: u8,
362+
operations: &mut [embedded_hal::i2c::Operation<'_>],
363+
) -> core::result::Result<(), Self::Error> {
364+
let [ref mut current, ref mut rem @ ..] = operations else {
365+
// No operations mean noop
366+
return Ok(());
367+
};
368+
369+
// mut ref mut doesn't work above
370+
let mut current = current;
371+
let mut rem = rem;
372+
// None: first iteration
373+
// Some(true) iterating after a read
374+
// Some(false) iterating after a write
375+
let mut previous_was_read = None;
376+
377+
loop {
378+
match current {
379+
Operation::Read(buf) => {
380+
if previous_was_read == Some(true) {
381+
self.read_inner_bytes(buf)?;
382+
} else {
383+
self.read_without_stop(address, buf)?;
384+
}
385+
386+
previous_was_read = Some(true);
387+
}
388+
Operation::Write(buf) => {
389+
if previous_was_read == Some(false) {
390+
self.write_inner_bytes(buf)?;
391+
} else {
392+
self.write_without_stop(address, buf)?;
393+
}
394+
395+
previous_was_read = Some(false);
396+
}
397+
}
398+
399+
let [ref mut new_current, ref mut new_rem @ ..] = rem else {
400+
// No operations left
401+
self.stop()?;
402+
return Ok(());
403+
};
404+
405+
current = new_current;
406+
rem = new_rem;
407+
}
300408
}
301409
}
302410

0 commit comments

Comments
 (0)