Skip to content

Commit d99b53c

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

File tree

3 files changed

+70
-25
lines changed

3 files changed

+70
-25
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: 46 additions & 24 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;
@@ -508,25 +507,27 @@ impl<I2C: Instance> I2c<I2C> {
508507
pub fn transaction<'a>(
509508
&mut self,
510509
addr: u8,
511-
mut ops: impl Iterator<Item = Operation<'a>>,
510+
mut ops: impl Iterator<Item = Hal1Operation<'a>>,
512511
) -> Result<(), Error> {
513512
if let Some(mut prev_op) = ops.next() {
514513
// 1. Generate Start for operation
515514
match &prev_op {
516-
Operation::Read(_) => self.prepare_read(addr)?,
517-
Operation::Write(_) => self.prepare_write(addr)?,
515+
Hal1Operation::Read(_) => self.prepare_read(addr)?,
516+
Hal1Operation::Write(_) => self.prepare_write(addr)?,
518517
};
519518

520519
for op in ops {
521520
// 2. Execute previous operations.
522521
match &mut prev_op {
523-
Operation::Read(rb) => self.read_bytes(rb)?,
524-
Operation::Write(wb) => self.write_bytes(wb.iter().cloned())?,
522+
Hal1Operation::Read(rb) => self.read_bytes(rb)?,
523+
Hal1Operation::Write(wb) => self.write_bytes(wb.iter().cloned())?,
525524
};
526525
// 3. If operation changes type we must generate new start
527526
match (&prev_op, &op) {
528-
(Operation::Read(_), Operation::Write(_)) => self.prepare_write(addr)?,
529-
(Operation::Write(_), Operation::Read(_)) => self.prepare_read(addr)?,
527+
(Hal1Operation::Read(_), Hal1Operation::Write(_)) => {
528+
self.prepare_write(addr)?
529+
}
530+
(Hal1Operation::Write(_), Hal1Operation::Read(_)) => self.prepare_read(addr)?,
530531
_ => {} // No changes if operation have not changed
531532
}
532533

@@ -535,8 +536,8 @@ impl<I2C: Instance> I2c<I2C> {
535536

536537
// 4. Now, prev_op is last command use methods variations that will generate stop
537538
match prev_op {
538-
Operation::Read(rb) => self.read_wo_prepare(rb)?,
539-
Operation::Write(wb) => self.write_wo_prepare(wb)?,
539+
Hal1Operation::Read(rb) => self.read_wo_prepare(rb)?,
540+
Hal1Operation::Write(wb) => self.write_wo_prepare(wb)?,
540541
};
541542
}
542543

@@ -547,27 +548,47 @@ impl<I2C: Instance> I2c<I2C> {
547548
pub fn transaction_slice(
548549
&mut self,
549550
addr: u8,
550-
ops_slice: &mut [Operation<'_>],
551+
ops_slice: &mut [Hal1Operation<'_>],
551552
) -> Result<(), Error> {
552-
let mut ops = ops_slice.iter_mut();
553+
transaction_impl!(self, addr, ops_slice, Hal1Operation);
554+
// Fallthrough is success
555+
Ok(())
556+
}
557+
558+
fn transaction_slice_hal_02(
559+
&mut self,
560+
addr: u8,
561+
ops_slice: &mut [Hal02Operation<'_>],
562+
) -> Result<(), Error> {
563+
transaction_impl!(self, addr, ops_slice, Hal02Operation);
564+
// Fallthrough is success
565+
Ok(())
566+
}
567+
}
568+
569+
macro_rules! transaction_impl {
570+
($self:ident, $addr:ident, $ops_slice:ident, $Operation:ident) => {
571+
let i2c = $self;
572+
let addr = $addr;
573+
let mut ops = $ops_slice.iter_mut();
553574

554575
if let Some(mut prev_op) = ops.next() {
555576
// 1. Generate Start for operation
556577
match &prev_op {
557-
Operation::Read(_) => self.prepare_read(addr)?,
558-
Operation::Write(_) => self.prepare_write(addr)?,
578+
$Operation::Read(_) => i2c.prepare_read(addr)?,
579+
$Operation::Write(_) => i2c.prepare_write(addr)?,
559580
};
560581

561582
for op in ops {
562583
// 2. Execute previous operations.
563584
match &mut prev_op {
564-
Operation::Read(rb) => self.read_bytes(rb)?,
565-
Operation::Write(wb) => self.write_bytes(wb.iter().cloned())?,
585+
$Operation::Read(rb) => i2c.read_bytes(rb)?,
586+
$Operation::Write(wb) => i2c.write_bytes(wb.iter().cloned())?,
566587
};
567588
// 3. If operation changes type we must generate new start
568589
match (&prev_op, &op) {
569-
(Operation::Read(_), Operation::Write(_)) => self.prepare_write(addr)?,
570-
(Operation::Write(_), Operation::Read(_)) => self.prepare_read(addr)?,
590+
($Operation::Read(_), $Operation::Write(_)) => i2c.prepare_write(addr)?,
591+
($Operation::Write(_), $Operation::Read(_)) => i2c.prepare_read(addr)?,
571592
_ => {} // No changes if operation have not changed
572593
}
573594

@@ -576,12 +597,13 @@ impl<I2C: Instance> I2c<I2C> {
576597

577598
// 4. Now, prev_op is last command use methods variations that will generate stop
578599
match prev_op {
579-
Operation::Read(rb) => self.read_wo_prepare(rb)?,
580-
Operation::Write(wb) => self.write_wo_prepare(wb)?,
600+
$Operation::Read(rb) => i2c.read_wo_prepare(rb)?,
601+
$Operation::Write(wb) => i2c.write_wo_prepare(wb)?,
581602
};
582603
}
583-
584-
// Fallthrough is success
585-
Ok(())
586-
}
604+
};
587605
}
606+
use transaction_impl;
607+
608+
type Hal1Operation<'a> = embedded_hal_one::i2c::Operation<'a>;
609+
type Hal02Operation<'a> = embedded_hal::blocking::i2c::Operation<'a>;

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)