Skip to content

Commit 9407777

Browse files
committed
implement embedded_hal::blocking::i2c::Transactional for I2C
1 parent 7402fde commit 9407777

File tree

3 files changed

+68
-73
lines changed

3 files changed

+68
-73
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- implement `embedded_hal::blocking::i2c::Transactional` for `I2c` [#671]
13+
14+
[#671]: https://github.com/stm32-rs/stm32f4xx-hal/pull/671
15+
1016
## [v0.17.0] - 2023-07-11
1117

1218
### Changed

src/i2c.rs

Lines changed: 44 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use crate::rcc::{Enable, Reset};
66
use crate::gpio;
77

88
use crate::rcc::Clocks;
9-
use embedded_hal_one::i2c::Operation;
109
use fugit::{HertzU32 as Hertz, RateExtU32};
1110

1211
mod hal_02;
@@ -504,84 +503,57 @@ impl<I2C: Instance> I2c<I2C> {
504503
self.write_bytes(bytes.into_iter())?;
505504
self.read(addr, buffer)
506505
}
506+
}
507507

508-
pub fn transaction<'a>(
509-
&mut self,
510-
addr: u8,
511-
mut ops: impl Iterator<Item = Operation<'a>>,
512-
) -> Result<(), Error> {
513-
if let Some(mut prev_op) = ops.next() {
514-
// 1. Generate Start for operation
515-
match &prev_op {
516-
Operation::Read(_) => self.prepare_read(addr)?,
517-
Operation::Write(_) => self.prepare_write(addr)?,
518-
};
519-
520-
for op in ops {
521-
// 2. Execute previous operations.
522-
match &mut prev_op {
523-
Operation::Read(rb) => self.read_bytes(rb)?,
524-
Operation::Write(wb) => self.write_bytes(wb.iter().cloned())?,
508+
macro_rules! transaction_impl {
509+
($vis:vis fn $function:ident: $operation:ty, $read:path, $write:path) => {
510+
$vis fn $function(
511+
&mut self,
512+
addr: u8,
513+
ops_slice: &mut [$operation],
514+
) -> Result<(), Error> {
515+
let mut ops = ops_slice.iter_mut();
516+
517+
if let Some(mut prev_op) = ops.next() {
518+
// 1. Generate Start for operation
519+
match &prev_op {
520+
$read(_) => self.prepare_read(addr)?,
521+
$write(_) => self.prepare_write(addr)?,
525522
};
526-
// 3. If operation changes type we must generate new start
527-
match (&prev_op, &op) {
528-
(Operation::Read(_), Operation::Write(_)) => self.prepare_write(addr)?,
529-
(Operation::Write(_), Operation::Read(_)) => self.prepare_read(addr)?,
530-
_ => {} // No changes if operation have not changed
531-
}
532-
533-
prev_op = op;
534-
}
535-
536-
// 4. Now, prev_op is last command use methods variations that will generate stop
537-
match prev_op {
538-
Operation::Read(rb) => self.read_wo_prepare(rb)?,
539-
Operation::Write(wb) => self.write_wo_prepare(wb)?,
540-
};
541-
}
542523

543-
// Fallthrough is success
544-
Ok(())
545-
}
546-
547-
pub fn transaction_slice(
548-
&mut self,
549-
addr: u8,
550-
ops_slice: &mut [Operation<'_>],
551-
) -> Result<(), Error> {
552-
let mut ops = ops_slice.iter_mut();
553-
554-
if let Some(mut prev_op) = ops.next() {
555-
// 1. Generate Start for operation
556-
match &prev_op {
557-
Operation::Read(_) => self.prepare_read(addr)?,
558-
Operation::Write(_) => self.prepare_write(addr)?,
559-
};
560-
561-
for op in ops {
562-
// 2. Execute previous operations.
563-
match &mut prev_op {
564-
Operation::Read(rb) => self.read_bytes(rb)?,
565-
Operation::Write(wb) => self.write_bytes(wb.iter().cloned())?,
566-
};
567-
// 3. If operation changes type we must generate new start
568-
match (&prev_op, &op) {
569-
(Operation::Read(_), Operation::Write(_)) => self.prepare_write(addr)?,
570-
(Operation::Write(_), Operation::Read(_)) => self.prepare_read(addr)?,
571-
_ => {} // No changes if operation have not changed
524+
for op in ops {
525+
// 2. Execute previous operations.
526+
match &mut prev_op {
527+
$read(rb) => self.read_bytes(rb)?,
528+
$write(wb) => self.write_bytes(wb.iter().cloned())?,
529+
};
530+
// 3. If operation changes type we must generate new start
531+
match (&prev_op, &op) {
532+
($read(_), $write(_)) => self.prepare_write(addr)?,
533+
($write(_), $read(_)) => self.prepare_read(addr)?,
534+
_ => {} // No changes if operation have not changed
535+
}
536+
537+
prev_op = op;
572538
}
573539

574-
prev_op = op;
540+
// 4. Now, prev_op is last command use methods variations that will generate stop
541+
match prev_op {
542+
$read(rb) => self.read_wo_prepare(rb)?,
543+
$write(wb) => self.write_wo_prepare(wb)?,
544+
};
575545
}
576546

577-
// 4. Now, prev_op is last command use methods variations that will generate stop
578-
match prev_op {
579-
Operation::Read(rb) => self.read_wo_prepare(rb)?,
580-
Operation::Write(wb) => self.write_wo_prepare(wb)?,
581-
};
547+
// Fallthrough is success
548+
Ok(())
582549
}
550+
};
551+
}
583552

584-
// Fallthrough is success
585-
Ok(())
586-
}
553+
type Hal1Operation<'a> = embedded_hal_one::i2c::Operation<'a>;
554+
type Hal02Operation<'a> = embedded_hal::blocking::i2c::Operation<'a>;
555+
556+
impl<I2C: Instance> I2c<I2C> {
557+
transaction_impl!(pub fn transaction_slice: Hal1Operation<'_>, Hal1Operation::Read, Hal1Operation::Write);
558+
transaction_impl!(fn transaction_slice_hal_02: Hal02Operation<'_>, Hal02Operation::Read, Hal02Operation::Write);
587559
}

src/i2c/hal_02.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
mod blocking {
22
use super::super::{Error, I2c, Instance};
3-
use embedded_hal::blocking::i2c::{Read, Write, WriteIter, WriteIterRead, WriteRead};
3+
use embedded_hal::blocking::i2c::{
4+
Operation, Read, Transactional, Write, WriteIter, WriteIterRead, WriteRead,
5+
};
46

57
impl<I2C> WriteRead for I2c<I2C>
68
where
@@ -72,4 +74,19 @@ mod blocking {
7274
self.read(addr, buffer)
7375
}
7476
}
77+
78+
impl<I2C> Transactional for I2c<I2C>
79+
where
80+
I2C: Instance,
81+
{
82+
type Error = Error;
83+
84+
fn exec<'a>(
85+
&mut self,
86+
address: u8,
87+
operations: &mut [Operation<'a>],
88+
) -> Result<(), Self::Error> {
89+
self.transaction_slice_hal_02(address, operations)
90+
}
91+
}
7592
}

0 commit comments

Comments
 (0)