Skip to content

Commit ba9b85f

Browse files
committed
blocking/spi: add Read, ReadWrite, rename Transfer to ReadWriteInplace
1 parent a7c1233 commit ba9b85f

File tree

2 files changed

+96
-13
lines changed

2 files changed

+96
-13
lines changed

src/blocking/spi.rs

Lines changed: 93 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,30 @@
11
//! Blocking SPI API
22
3-
/// Blocking transfer
4-
pub trait Transfer<W> {
3+
/// Blocking simultaneous read+write with separate buffers
4+
pub trait ReadWrite<W> {
5+
/// Error type
6+
type Error;
7+
8+
/// Writes and reads simultaneously. `write` is written to the slave on MOSI and
9+
/// words received on MISO are stored in `read`.
10+
///
11+
/// It is allowed for `read` and `write` to have different lengths, even zero length.
12+
/// The transfer runs for `max(read.len(), write.len())` words. If `read` is shorter,
13+
/// incoming words after `read` has been filled will be discarded. If `write` is shorter,
14+
/// the value of words sent in MOSI after all `write` has been sent is implementation defined,
15+
/// typically `0x00`, `0xFF`, or configurable.
16+
fn read_write(&mut self, read: &mut [W], write: &[W]) -> Result<(), Self::Error>;
17+
}
18+
19+
/// Blocking simultaneous read+write with a single buffer
20+
pub trait ReadWriteInplace<W> {
521
/// Error type
622
type Error;
723

824
/// Writes and reads simultaneously. The contents of `words` are
925
/// written to the slave, and the received words are stored into the same
1026
/// `words` buffer, overwriting it.
11-
fn transfer(&mut self, words: &mut [W]) -> Result<(), Self::Error>;
27+
fn read_write_inplace(&mut self, words: &mut [W]) -> Result<(), Self::Error>;
1228
}
1329

1430
/// Blocking write
@@ -20,6 +36,16 @@ pub trait Write<W> {
2036
fn write(&mut self, words: &[W]) -> Result<(), Self::Error>;
2137
}
2238

39+
/// Blocking read
40+
pub trait Read<W> {
41+
/// Error type
42+
type Error;
43+
44+
/// Reads `words` to the slave. The word value sent on MOSI during
45+
/// reading is implementation defined, typically `0x00`, `0xFF`, or configurable.
46+
fn read(&mut self, words: &mut [W]) -> Result<(), Self::Error>;
47+
}
48+
2349
/// Blocking write (iterator version)
2450
pub trait WriteIter<W> {
2551
/// Error type
@@ -31,20 +57,53 @@ pub trait WriteIter<W> {
3157
WI: IntoIterator<Item = W>;
3258
}
3359

34-
/// Blocking transfer
35-
pub mod transfer {
60+
/// Blocking simultaneous read+write with separate buffers
61+
pub mod read_write {
62+
/// Default implementation of `blocking::spi::ReadWrite<W>` for implementers of
63+
/// `nonblocking::spi::FullDuplex<W>`
64+
pub trait Default<W>: crate::nb::spi::FullDuplex<W> {}
65+
66+
impl<W, S> crate::blocking::spi::ReadWrite<W> for S
67+
where
68+
S: Default<W>,
69+
W: Clone + core::default::Default,
70+
{
71+
type Error = S::Error;
72+
73+
fn read_write(&mut self, read: &mut [W], write: &[W]) -> Result<(), S::Error> {
74+
for i in 0..core::cmp::max(read.len(), write.len()) {
75+
let word_out = if i < write.len() {
76+
write[i].clone()
77+
} else {
78+
W::default()
79+
};
80+
nb::block!(self.write(word_out.clone()))?;
81+
82+
let word_in = nb::block!(self.read())?;
83+
if i < read.len() {
84+
read[i] = word_in;
85+
}
86+
}
87+
88+
Ok(())
89+
}
90+
}
91+
}
92+
93+
/// Blocking simultaneous read+write with separate buffers
94+
pub mod read_write_inplace {
3695
/// Default implementation of `blocking::spi::Transfer<W>` for implementers of
3796
/// `nonblocking::spi::FullDuplex<W>`
3897
pub trait Default<W>: crate::nb::spi::FullDuplex<W> {}
3998

40-
impl<W, S> crate::blocking::spi::Transfer<W> for S
99+
impl<W, S> crate::blocking::spi::ReadWriteInplace<W> for S
41100
where
42101
S: Default<W>,
43102
W: Clone,
44103
{
45104
type Error = S::Error;
46105

47-
fn transfer(&mut self, words: &mut [W]) -> Result<(), S::Error> {
106+
fn read_write_inplace(&mut self, words: &mut [W]) -> Result<(), S::Error> {
48107
for word in words.iter_mut() {
49108
nb::block!(self.write(word.clone()))?;
50109
*word = nb::block!(self.read())?;
@@ -78,6 +137,29 @@ pub mod write {
78137
}
79138
}
80139
}
140+
/// Blocking write
141+
pub mod read {
142+
/// Default implementation of `blocking::spi::Read<W>` for implementers
143+
/// of `nonblocking::spi::FullDuplex<W>`
144+
pub trait Default<W>: crate::nb::spi::FullDuplex<W> {}
145+
146+
impl<W, S> crate::blocking::spi::Read<W> for S
147+
where
148+
S: Default<W>,
149+
W: core::default::Default,
150+
{
151+
type Error = S::Error;
152+
153+
fn read(&mut self, words: &mut [W]) -> Result<(), S::Error> {
154+
for word in words.iter_mut() {
155+
nb::block!(self.write(W::default()))?;
156+
*word = nb::block!(self.read())?;
157+
}
158+
159+
Ok(())
160+
}
161+
}
162+
}
81163

82164
/// Blocking write (iterator version)
83165
pub mod write_iter {
@@ -129,15 +211,15 @@ pub trait Transactional<W: 'static> {
129211

130212
/// Blocking transactional impl over spi::Write and spi::Transfer
131213
pub mod transactional {
132-
use super::{Operation, Transfer, Write};
214+
use super::{Operation, ReadWriteInplace, Write};
133215

134216
/// Default implementation of `blocking::spi::Transactional<W>` for implementers of
135217
/// `spi::Write<W>` and `spi::Transfer<W>`
136-
pub trait Default<W>: Write<W> + Transfer<W> {}
218+
pub trait Default<W>: Write<W> + ReadWriteInplace<W> {}
137219

138220
impl<W: 'static, E, S> super::Transactional<W> for S
139221
where
140-
S: self::Default<W> + Write<W, Error = E> + Transfer<W, Error = E>,
222+
S: self::Default<W> + Write<W, Error = E> + ReadWriteInplace<W, Error = E>,
141223
W: Copy + Clone,
142224
{
143225
type Error = E;
@@ -146,7 +228,7 @@ pub mod transactional {
146228
for op in operations {
147229
match op {
148230
Operation::Write(w) => self.write(w)?,
149-
Operation::Transfer(t) => self.transfer(t).map(|_| ())?,
231+
Operation::Transfer(t) => self.read_write_inplace(t).map(|_| ())?,
150232
}
151233
}
152234

src/prelude.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ pub use crate::blocking::qei::Qei as _embedded_hal_blocking_Qei;
2222
pub use crate::blocking::rng::Read as _embedded_hal_blocking_rng_Read;
2323
pub use crate::blocking::serial::Write as _embedded_hal_blocking_serial_Write;
2424
pub use crate::blocking::spi::{
25-
Transfer as _embedded_hal_blocking_spi_Transfer, Write as _embedded_hal_blocking_spi_Write,
26-
WriteIter as _embedded_hal_blocking_spi_WriteIter,
25+
ReadWrite as _embedded_hal_blocking_spi_ReadWrite,
26+
ReadWriteInplace as _embedded_hal_blocking_spi_ReadWriteInplace,
27+
Write as _embedded_hal_blocking_spi_Write, WriteIter as _embedded_hal_blocking_spi_WriteIter,
2728
};
2829
pub use crate::blocking::watchdog::Disable as _embedded_hal_blocking_watchdog_Disable;
2930
pub use crate::blocking::watchdog::Enable as _embedded_hal_blocking_watchdog_Enable;

0 commit comments

Comments
 (0)