Skip to content

Commit 415f64c

Browse files
committed
spi: SpiDevice transactiontake an operation slice instead of a closure.
1 parent 1533716 commit 415f64c

File tree

3 files changed

+320
-76
lines changed

3 files changed

+320
-76
lines changed

embedded-hal-async/src/spi.rs

Lines changed: 93 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
33
use core::{fmt::Debug, future::Future};
44

5-
use embedded_hal::digital::OutputPin;
65
use embedded_hal::spi as blocking;
76
pub use embedded_hal::spi::{
87
Error, ErrorKind, ErrorType, Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3,
98
};
9+
use embedded_hal::{digital::OutputPin, spi::Operation};
1010

1111
#[macro_export]
1212
/// Do an SPI transaction on a bus.
@@ -374,30 +374,112 @@ where
374374
type Error = ExclusiveDeviceError<BUS::Error, CS::Error>;
375375
}
376376

377-
impl<BUS, CS> blocking::SpiDevice for ExclusiveDevice<BUS, CS>
377+
impl<Word: Copy + 'static, BUS, CS> blocking::SpiDeviceRead<Word> for ExclusiveDevice<BUS, CS>
378378
where
379-
BUS: blocking::SpiBusFlush,
379+
BUS: blocking::SpiBusRead<Word>,
380380
CS: OutputPin,
381381
{
382-
type Bus = BUS;
382+
fn read_transaction(&mut self, operations: &mut [&mut [Word]]) -> Result<(), Self::Error> {
383+
self.cs.set_low().map_err(ExclusiveDeviceError::Cs)?;
384+
385+
let mut op_res = Ok(());
386+
387+
for buf in operations {
388+
if let Err(e) = self.bus.read(buf) {
389+
op_res = Err(e);
390+
break;
391+
}
392+
}
393+
394+
// On failure, it's important to still flush and deassert CS.
395+
let flush_res = self.bus.flush();
396+
let cs_res = self.cs.set_high();
397+
398+
op_res.map_err(ExclusiveDeviceError::Spi)?;
399+
flush_res.map_err(ExclusiveDeviceError::Spi)?;
400+
cs_res.map_err(ExclusiveDeviceError::Cs)?;
401+
402+
Ok(())
403+
}
404+
}
405+
406+
impl<Word: Copy + 'static, BUS, CS> blocking::SpiDeviceWrite<Word> for ExclusiveDevice<BUS, CS>
407+
where
408+
BUS: blocking::SpiBusWrite<Word>,
409+
CS: OutputPin,
410+
{
411+
fn write_transaction(&mut self, operations: &[&[Word]]) -> Result<(), Self::Error> {
412+
self.cs.set_low().map_err(ExclusiveDeviceError::Cs)?;
383413

384-
fn transaction<R>(
385-
&mut self,
386-
f: impl FnOnce(&mut Self::Bus) -> Result<R, <Self::Bus as ErrorType>::Error>,
387-
) -> Result<R, Self::Error> {
414+
let mut op_res = Ok(());
415+
416+
for buf in operations {
417+
if let Err(e) = self.bus.write(buf) {
418+
op_res = Err(e);
419+
break;
420+
}
421+
}
422+
423+
// On failure, it's important to still flush and deassert CS.
424+
let flush_res = self.bus.flush();
425+
let cs_res = self.cs.set_high();
426+
427+
op_res.map_err(ExclusiveDeviceError::Spi)?;
428+
flush_res.map_err(ExclusiveDeviceError::Spi)?;
429+
cs_res.map_err(ExclusiveDeviceError::Cs)?;
430+
431+
Ok(())
432+
}
433+
}
434+
435+
impl<Word: Copy + 'static, BUS, CS> blocking::SpiDevice<Word> for ExclusiveDevice<BUS, CS>
436+
where
437+
BUS: blocking::SpiBus<Word>,
438+
CS: OutputPin,
439+
{
440+
fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> {
388441
self.cs.set_low().map_err(ExclusiveDeviceError::Cs)?;
389442

390-
let f_res = f(&mut self.bus);
443+
let mut op_res = Ok(());
444+
445+
for op in operations {
446+
match op {
447+
Operation::Read(buf) => {
448+
if let Err(e) = self.bus.read(buf) {
449+
op_res = Err(e);
450+
break;
451+
}
452+
}
453+
Operation::Write(buf) => {
454+
if let Err(e) = self.bus.write(buf) {
455+
op_res = Err(e);
456+
break;
457+
}
458+
}
459+
Operation::Transfer(read, write) => {
460+
if let Err(e) = self.bus.transfer(read, write) {
461+
op_res = Err(e);
462+
break;
463+
}
464+
}
465+
Operation::TransferInPlace(buf) => {
466+
if let Err(e) = self.bus.transfer_in_place(buf) {
467+
op_res = Err(e);
468+
break;
469+
}
470+
}
471+
}
472+
}
391473

392474
// On failure, it's important to still flush and deassert CS.
393475
let flush_res = self.bus.flush();
394476
let cs_res = self.cs.set_high();
395477

396-
let f_res = f_res.map_err(ExclusiveDeviceError::Spi)?;
478+
op_res.map_err(ExclusiveDeviceError::Spi)?;
397479
flush_res.map_err(ExclusiveDeviceError::Spi)?;
398480
cs_res.map_err(ExclusiveDeviceError::Cs)?;
399481

400-
Ok(f_res)
482+
Ok(())
401483
}
402484
}
403485

embedded-hal-bus/src/spi.rs

Lines changed: 96 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
33
use core::fmt::Debug;
44
use embedded_hal::digital::OutputPin;
5-
use embedded_hal::spi::{Error, ErrorKind, ErrorType, SpiBusFlush, SpiDevice};
5+
use embedded_hal::spi::{
6+
Error, ErrorKind, ErrorType, Operation, SpiBus, SpiBusRead, SpiBusWrite, SpiDevice,
7+
SpiDeviceRead, SpiDeviceWrite,
8+
};
69

710
/// Error type for [`ExclusiveDevice`] operations.
811
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
@@ -50,29 +53,111 @@ where
5053
type Error = ExclusiveDeviceError<BUS::Error, CS::Error>;
5154
}
5255

53-
impl<BUS, CS> SpiDevice for ExclusiveDevice<BUS, CS>
56+
impl<Word: Copy + 'static, BUS, CS> SpiDeviceRead<Word> for ExclusiveDevice<BUS, CS>
5457
where
55-
BUS: SpiBusFlush,
58+
BUS: SpiBusRead<Word>,
5659
CS: OutputPin,
5760
{
58-
type Bus = BUS;
61+
fn read_transaction(&mut self, operations: &mut [&mut [Word]]) -> Result<(), Self::Error> {
62+
self.cs.set_low().map_err(ExclusiveDeviceError::Cs)?;
63+
64+
let mut op_res = Ok(());
65+
66+
for buf in operations {
67+
if let Err(e) = self.bus.read(buf) {
68+
op_res = Err(e);
69+
break;
70+
}
71+
}
72+
73+
// On failure, it's important to still flush and deassert CS.
74+
let flush_res = self.bus.flush();
75+
let cs_res = self.cs.set_high();
5976

60-
fn transaction<R>(
61-
&mut self,
62-
f: impl FnOnce(&mut Self::Bus) -> Result<R, <Self::Bus as ErrorType>::Error>,
63-
) -> Result<R, Self::Error> {
77+
op_res.map_err(ExclusiveDeviceError::Spi)?;
78+
flush_res.map_err(ExclusiveDeviceError::Spi)?;
79+
cs_res.map_err(ExclusiveDeviceError::Cs)?;
80+
81+
Ok(())
82+
}
83+
}
84+
85+
impl<Word: Copy + 'static, BUS, CS> SpiDeviceWrite<Word> for ExclusiveDevice<BUS, CS>
86+
where
87+
BUS: SpiBusWrite<Word>,
88+
CS: OutputPin,
89+
{
90+
fn write_transaction(&mut self, operations: &[&[Word]]) -> Result<(), Self::Error> {
6491
self.cs.set_low().map_err(ExclusiveDeviceError::Cs)?;
6592

66-
let f_res = f(&mut self.bus);
93+
let mut op_res = Ok(());
94+
95+
for buf in operations {
96+
if let Err(e) = self.bus.write(buf) {
97+
op_res = Err(e);
98+
break;
99+
}
100+
}
101+
102+
// On failure, it's important to still flush and deassert CS.
103+
let flush_res = self.bus.flush();
104+
let cs_res = self.cs.set_high();
105+
106+
op_res.map_err(ExclusiveDeviceError::Spi)?;
107+
flush_res.map_err(ExclusiveDeviceError::Spi)?;
108+
cs_res.map_err(ExclusiveDeviceError::Cs)?;
109+
110+
Ok(())
111+
}
112+
}
113+
114+
impl<Word: Copy + 'static, BUS, CS> SpiDevice<Word> for ExclusiveDevice<BUS, CS>
115+
where
116+
BUS: SpiBus<Word>,
117+
CS: OutputPin,
118+
{
119+
fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> {
120+
self.cs.set_low().map_err(ExclusiveDeviceError::Cs)?;
121+
122+
let mut op_res = Ok(());
123+
124+
for op in operations {
125+
match op {
126+
Operation::Read(buf) => {
127+
if let Err(e) = self.bus.read(buf) {
128+
op_res = Err(e);
129+
break;
130+
}
131+
}
132+
Operation::Write(buf) => {
133+
if let Err(e) = self.bus.write(buf) {
134+
op_res = Err(e);
135+
break;
136+
}
137+
}
138+
Operation::Transfer(read, write) => {
139+
if let Err(e) = self.bus.transfer(read, write) {
140+
op_res = Err(e);
141+
break;
142+
}
143+
}
144+
Operation::TransferInPlace(buf) => {
145+
if let Err(e) = self.bus.transfer_in_place(buf) {
146+
op_res = Err(e);
147+
break;
148+
}
149+
}
150+
}
151+
}
67152

68153
// On failure, it's important to still flush and deassert CS.
69154
let flush_res = self.bus.flush();
70155
let cs_res = self.cs.set_high();
71156

72-
let f_res = f_res.map_err(ExclusiveDeviceError::Spi)?;
157+
op_res.map_err(ExclusiveDeviceError::Spi)?;
73158
flush_res.map_err(ExclusiveDeviceError::Spi)?;
74159
cs_res.map_err(ExclusiveDeviceError::Cs)?;
75160

76-
Ok(f_res)
161+
Ok(())
77162
}
78163
}

0 commit comments

Comments
 (0)